Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jjangga0214/73481a3749271d8d2198d80f67035cb1 to your computer and use it in GitHub Desktop.
Save jjangga0214/73481a3749271d8d2198d80f67035cb1 to your computer and use it in GitHub Desktop.

Comparision between artificial and natural pk

Pk 를 artificial key 로 택할때의 단점

  • 이론적으로는 불필요한 공간, 인덱싱 요구.
  • Natural Key 에 unique constraint 를 설정하는 것을 잊을 위험.
  • Existence Dependency가 깊을 때, Dependency를 한번에 여럿 거슬러 올라가기 위해 서브쿼리 또는, 인라인 뷰가 복수겹 필요한 경우가 있음.

Pk 를 natural key 로 택할때의 단점

  • lack of opacity : pk를 노출시켜야 할 때 부적절한 경우가 많다.

    ex: www.example.com/users/1/ 위의 url 에서는 User 테이블의 pk 가 1,2,3 과 같은 artificial id 임을 추론할 수 있다. 만약 이메일이나 전화번호, 주민등록번호라면, 정보보호 측면서 부적절하다.

  • natural key 를 PK 로 삼으면, 자연스레 composite key 를 pk 로 사용하게 되는 경우가 생긴다. composite key 가 pk로 사용될 때, 다음과 같은 몇가지 단점이 있다.

    • 간결하지 않은 외부 표현 : REST API 등으로 id를 간결하게 표현하는 것에 방해가 된다.

      ex : www.example.com/articles/Interesting%20Article_1 위의 url 에서는 Article 테이블의 pk 는 글의 제목과 유저의 pk 임을(composite key) 추론할 수 있다.(물론, 이것은 예를 보이기 위함이고, 일반적으로 실제 pk는 저렇게 지정되지 않을 것이다.) 이때, Article 을 지정하기 위해 글제목 + "_" + 유저id => "Interesting Article" + "_" + "1" 형식으로 표현했다. 이는 API 명세 또는 URL 을 간결하게 표현하려는 트렌드와는 잘 부합하지 않는다.

    • 애플리케이션 레벨에서 id를 핸들링 : 비용이 생긴다.

      ex : www.example.com/articles/Interesting%20Article_1 만약, artificial key 를 pk 로 사용하면, heirarchical 한 특성의 url과 relational 한 database와의 mismatch 를 핸들링하는 로직도 필요없을 것이다.

    • depth : Existence dependency depth 가 깊어질 수록, pk가 방대해진다. 또한, 이는 해당 테이블과 관련된 애플리케이션 코드에 전역적으로 영향을 미친다.

    • 문서의 요구 : 테이블이 많을 경우, 어떤 테이블의 pk 가 어떤 것들인지 관리해야하는 부담이 커지고, DBA와 개발자와의 소통을 위해 좀 더 정교한 주의사항과, 문서가 요구된다. 만일, 예를 들어, 모든 테이블의 pk 를 'id' 라는 필드로 통일했다면, 문서와 유의사항, 시스템 개편시 주의점이 줄어들 것이고, 개발자가 기억하기도 용이해 개발 생산성이 높아진다.

    • 쿼리 작성의 불편 : 특히 Existence dependency 가 깊을 경우, 쿼리가 방대해지고, 관리하기가 번거롭다.

  • 유지보수성 저하 : natural value 는 항상 그 특성이 바뀔 수 있다. 특히, pk 가 natural composite key 라면, 시스템 확장, 유지보수, 요구사항 변경으로 schema 변경시 pk 가 변경될 가능성이 높다. 그렇다면, 해당 변경사항이 애플리케이션 레벨로 전파되어 pk 를 다루는 코드들을 모두 바꿔야 한다. 만일, 단일 artificial key 였다면, (테이블 자체가 merge되거나 없어지거나 하지 않는 이상) database schema 변경에 영향을 상당히 적게 받을 것이고, 애플리케이션 레벨로 그 변화가 전파되는 경우도 적을 것이다.

    ex : 예를 들어, Foo 라는 모듈서 특정 조건 시에 Bar 테이블의 pk 를 통해 레코드 하나를 조회한다고 하자. 이때, Foo 는 내부 context 에 의해 그때 마다 필요한 pk 를 알고 있다. 애플리케이션 레벨서 SELECT * FROM BAR WHERE ID = ${ID}; 와 같은 sql 을 사용한다면, schema 가 변경되도, 해당 부분의 코드는 잘 작동한다. 그러나, pk가 artificial value가 아니면, 해당 어플리케이션 코드(pk 를 다른 모듈서 핸들링 하는 부분, sql에 파라미터 건네주는 부분, sql 자체 등)도 바꿔야 할 가능성이 커진다.

가치의 충돌

RDBMS는 무결성을 엄격하게 충족하면서, 저장공간의 효율성을 확보하는 데에 초점을 둔다. 수학적 엄밀성에 매료된 일부 순수주의자들은 과거 이런 철학을 아주 강하게 따르기도 했다. 그렇지만, 관계지향적 철학은 "현재 있는 데이터를 어떻게 잘 저장할지"에 초점을 맞추다보니, "앞으로 데이터의 변화가 어떻게 전개될지", "개발자가 개발하기 편하려면 어떻게 해야할지" 와 같은 관점에는 관심을 두지 않는다. 때문에 유지보수성, 유연성(확장성), 생산성과 같은 관점과 상충되는 면이 있다. 또한, 엄밀히 그 규칙을 따르다 보면, 추상화가 잘 이루어지지 않는다. 예를 들어, 관계지향성을 엄밀히 따르면, 데이터베이스 레벨을 뛰어넘어, 애플리케이션 레벨에 그 영향이 강하게 전파되고, 심지어 end-user level 까지 관계지향성이 전파된다. 짧은 예로, 앞서 설명한 www.example.com/articles/Interesting%20Article_1 를 보면, DB의 구조가 애플리케이션 레벨을 거쳐 end-user 까지 전파되어, 유저가 애플리케이션을 사용하는 방법 자체를 정의하고 있다. 만일 레이어가 잘 구분된다면, 하부 또는 모듈화된 내부 시스템이 어떤 철학이고, 어떤 구조이던지 간에, 해당 시스템을 사용하는 쪽에 강한 결합을 만드는 일은 최소화되는 것이 좋다. 하지만, RDB의 가치는 근본 이론부터 그런 쪽에 큰 신경을 쓰지 않는다. 따라서 RDB가 잘 모듈화되지 않고 오히려 강한 결합을 만들어 내, RDB 내부의 변화가 외부로 전파되고, 유지보수성, 개발 자유도, 생산성을 떨어뜨리고, 개발하는 어플리케이션 자체의 유연성을 떨어뜨리는 경우가 있다.

정말 개인적인 철학이지만, 하나의 이론으로 완전히 컨트롤 되기에는 실제세계의 차원이 더 높아서, 순수주의, 혹은 극단주의적 접근으로 하나의 이론을 100% 따르기로 한다면, (꼭 데이터베이스가 아니더라도) 이런 side-effect이 발생할 확률이 높다고 생각한다일부러 . 그래서 개인적으로는 상황에 따라 이론을 적절히 따르는 것이 효과적이지 않을까 한다.

끝맺는 말

이번 이슈 관련한 부분에 관해 일부러 RDB의 negative 한 면을 다루어 보았습니다. 저도 정리하고, 교수님의 의견도 궁금해서 글을 적어 보았습니다. (쓰다보니 길어지네요^^;) 긴 글 읽어주셔서 감사합니다 :)

참조

https://stackoverflow.com/questions/4960263/sql-primary-key-column-artificial-id-column-vs-natural-columns

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment