Primary Key를 어떻게 가져가야 할까? 에 대한 생각 정리

uncle.ra·2023년 8월 27일
2
post-thumbnail

주의 사항

주의!) 많이 고민하고 적은 내용이지만 제 의견도 포함되어 있는 글입니다! 혹시나 잘못된 부분이 있으면 지적 부탁드릴게요🙏

개요

DB Table을 설계 시, Primary Key는 주로 Id 컬럼을 활용한다. Id값을 생성하는 방식은 정말 다양하다. UUID, Sequence, UID 등이 존재한다. 프로젝트를 진행하면서 이 부분에 대한 고민을 했었는데 이번 기회에 내가 느꼈던 각 방식의 장/단점과 PK를 어떻게 가져갈지에 대한 생각을 정리해 보고자 한다🤔

숫자 + 영문자(대문자/소문자)의 조합 11자리?

https://www.youtube.com/watch?v=kiaLrHZAwFU

Youtube 영상 중 아이유의 '겨울잠' 노래를 들으면서 글을 쓰고 있다. 🎶
해당 영상의 Id값을 유추해보면 kiaLrHZAwFU인데 총 11자리로 되어 있다.
이 방식으로 테이블의 PK로 가져가면 어떨까?

예측할 수 없다.

이 방식은 내가 생각했을 때 장점이자 단점으로 받아 들여졌다.

장점으로는 외부에서 Id값을 예측하기 어려워 데이터를 크롤링해 가기 어렵게 만든다. 또한 경쟁 업체가 존재한다면 경쟁 업체 역시 해당 상품의 재고가 어느 정도 있는지, 회원이 어느 정도 있는지 파악하기 어렵기 때문에 예측할 수 없게 한다.(UUID의 장점으로도 생각된다.)

단점도 존재한다. 사실 Id값을 실무에서 사용한다면 고객, 경쟁 업체 뿐만 아니라 회사의 동료들도 서로간의 소통 수단으로서 사용하게 된다.

동일한 상품이 4개가 앞에 놓여 있을 때 동료들은 상품들을 구별하며 소통할 수 있을까?

"1I82AWqAOP" 상품 상태가 어때요!?

와 같이 구두로 소통하기는 어려움이 있다. 그렇기 때문에 다른 unique한 값을 컬럼에 추가해서 소통하게 될 것이라고 생각한다.

정렬하기 어렵다.

일반적으로 웹 서비스와 같은 오라인 트랜젝션 환경(OLTP, On-Line Transaction Processing)에서는 쓰기와 읽기의 비율이 2:8 또는 1:9 정도이기 때문에 조금 느린 쓰기를 감수하고 읽기를 빠르게 유지하는 것은 매우 중요하다.

Real MySQL 8.0 - 클러스터링 인덱스의 장점과 단점

위 글을 인용한 이유는, 웹서비스에서 조회는 굉장히 많은 비율을 차지하고 있다는 점을 나타내고 싶었다. 그리고 조회를 할 경우 대부분 최신순, 업데이트 순 등으로 정렬을 해서 응답하게 된다. 하지만 영문자(대/소문자) + 숫자의 조합이라면 정렬하기 어렵다.
테이블 마다 생성일과 수정일이 있으면 되지 않을까 생각을 하지만, 자체 DB조작으로 인한 생성일과 수정일이 중복되는 경우가 있을 수 있기 때문에 안전하지 않다고 생각한다.

UUID?

velog에서 글을 작성할 때 보이는 상단의 url을 약간 수정해서 가져와 봤다.

https://velog.io/write?id=f91b897b-b6ae-42b5-b5ff-1a2c49241ce2

UUID는 다른 PK 종류의 비해 비교적 느리다.

UUID는 Universally Unique Identifier의 약자로 총 36개의 문자로 구성되어 있다. UUID는 128bits의 저장 공간을 차지하기 때문에 저장 및 조회 시에 AUTO_INCREMENT, 11자리 영문자/숫자 조합에 비해 비교적 느리다.

[MySQL] UUID의 개념과 성능 개선 결과 글에서는
UUID V1을 VARCHAR(36) -> BINARY(16)으로 저장 공간을 최소화하고, UUID V1의 Timestamp를 활용해서 정렬 역시 가능하게 했다.

UUID는 고유성에 초점을 맞췄을 때 동일한 Id값이 생성될 확률은 0에 가깝고 보안적인 측면에서도 유리하다. 하지만 Sequence PK와 비교해서 Read/Write의 성능은 비교적 느리다.

Sequence PK는 어떨까?

https://test.com/members/1002

위에는 예시로 url을 작성해 보았다.

예측할 수 있다.

상단의 숫자 + 영문자(대문자/소문자)의 조합 11자리? 에서 예측할 수 없다. 카테고리의 내용의 장/단점이 바뀌었다고 생각하면 좋다.

동료들과의 소통의 측면에서 훨씬 편하다는 장점이 존재한다. 하지만 외부 경쟁 업체 혹은 사용자에게 예측되기 쉽다는 단점이 존재한다.

최신순 정렬이 가능하다.

Sequence PK 방식을 사용하면 최신순에 한정이지만, 정렬이 가능하다.

생각 정리

그렇다면 어떻게 가져가는게 좋을까?

지금 내가 생각하기에, 기본적으로 Primary Key는 Sequence 방식으로 가져가는게 맞다고 생각이 들었다. 이유는 성능적인 이점, 최신순 정렬, 그리고 동료들과 소통을 하는 부분이다. 하지만, 외부적으로 Id값이 노출이 되는 테이블과 그렇지 않은 테이블이 존재한다.
전자의 경우(ex. USER, ITEM) 같은 테이블의 경우 영문자(대/소문자) + 숫자의 조합으로 Unique한 외부 노출용 컬럼을 하나 더 만들어 두고 방법으로 접근하려고 한다.

글을 작성하면서 아쉬웠던 부분

프로젝트를 진행하면서 했던 경험들을 토대로 정리를 해봤는데 부족한 부분이 많다.🥲

JPA에 관련된 내용은 뒤에 프로젝트를 진행하면서 직접 겪고 업데이트 해두는게 낫다고 판단이 들어서 적지 않았다. 또, MySQL의 InnoDB Storage Engine에서는 테이블당 PK와 관련되어서 클러스터링 인덱스를 지원해 주는 부분도 차츰 추가해 넣을 생각이다.

0개의 댓글