1. 기본키로 UUID를 사용할 때 오는 이점
테이블의 기본키로 UUID를 사용하는 방법은 3가지 이점이 있다.
(a) 데이터베이스가 여러 개인 경우, 하나의 ID가 여러 데이터베이스에서도 고유한 값이라고 볼 수 있다.
이러한 전제가 있으면, 서로 다른 테이블에서 관리되던 데이터를 하나의 데이터 소스로 합치기 쉽다.
예를 들어, 뉴스 콘텐츠 테이블이 1개가 있고, 이를 검색 엔진 (ElasticSearch)에 복제하고 있다고 가정해보자. 이후, 잡지 콘텐츠 테이블이 필요하게 되어, 이 정보를 동일한 ElasticSearch에 추가해야하는 상황이 왔다고 상상해보자. 두 테이블이 숫자 기반의 pk를 사용하고 있었다면 두 콘텐츠의 ID가 충돌나는 현상이 발생하게 된다. 이 때문에 두 테이블을 하나의 소스에 합치기 어려워진다.
(b) UUID는 데이터에 대한 정보를 노출하지 않기 때문에 보안상 안전하다.
increment pk는 식별키값이 외부에 노출되기 쉽다. 그래서 의도하지 않은 사용자에게 데이터가 노출될 위험이 있다. 예를 들어, 회원 정보를 increment pk로 조회하는 API가 /user/{pk}/ 같은 URL 패턴이라면, pk를 증분하면 다른 고객의 정보가 쉽게 노출될 수 있다는 리스크가 있다. 그래서 봇이 URL을 스캔해 데이터가 유출될 가능성이 있다.
그리고 increment pk로 데이터의 수를 유추할 수 있기 때문에, 비즈니스 적으로 의미있는 수치가 외부에 노출될 가능성이 있다. 예를 들어 주문, 상품 테이블의 식별값이 increment pk로 사용된다면, 외부에 누적 주문수와 상품수가 노출될 수 있다.
(c) UUID는 Stateless하다.
uuid는 stateless하기 때문에 함수를 사용하여 키를 생성할 수 있다. 반면 increment pk는 데이터베이스를 조회해야지만 유니크한 키를 알 수 있다. 그래서 insert query를 호출하기 전에 매번 increment pk를 구하는 쿼리를 db에 요청해야한다. 만약 분산 데이터베이스를 사용하고 있다면, increment pk를 구하는 작업이 SPOF (single-point-of-failure)를 발생시킬 수도 있다.
uuid는 이러한 과정을 생략할 수 있어서 성능상 이점이 있다.
2. 그래도 기본키로 UUID를 사용하면 안되는 이유
이렇게 보면 pk 식별자로 increment pk가 아니라 UUID를 사용하는 것이 무조건 좋아보인다. 🙅🏻♀️🙅🏻♀️🙅🏻♀️
그러나 UUID는 increment pk 보다 더 많은 저장 장소를 필요로한다. 그리고 관계 테이블에서 fk로 uuid를 사용한다면, 더 많은 저장 장소를 사용하게 된다. 이 경우, 테이블과 인덱스 크기가 커져서, 데이터베이스의 디스크와 메모리를 많이 사용하게 된다.
3. 테이블의 기본키는 외부에 노출되면 안된다.
데이터의 기본키는 외부에 노출되면 안된다. increment pk, uuid 모두 상관없이 그러하다.
pk를 변경하는 비용은 높다. pk는 언젠가 변경될 수 있기 때문에, 기본키를 외부에 노출하면 이 비용은 더 높아진다.
예를 들어, 기본키가 변경되면, 외부에 공개되었던 페이지의 데이터가 조회되지 않는 현상이 발생할 수 있다.
시스템에서 절대~~ 변경되지 않는 것은 없다. 예를 들어, 데이터가 많아져서 저장소를 RDB에서 NoSQL으로 이전하게 되는 경우, pk가 숫자형에서 문자형으로 변경될 수 있다.
4. 결론 : UUID와 increment PK는 언제 사용해야할까?
애플리케이션 내부용 키로는 increment pk를, 외부에 공개할 키로는 uuid를 사용하는 것을 권장한다. 애플리케이션 내부에서는 increment pk를 사용하여 관계 데이터를 참조하면 성능과 저장 장소 측면에서 이점을 얻을 수 있다.
식별값이 노출되는 서비스가 내부 시스템일지라도 uuid으로 데이터를 식별하는 것이 좋다. 외부에 공개될 식별자로 uuid를 사용하게되면, 향후에 내부 기본키를 변경해야하더라도 영향 범위를 데이터베이스로 한정지을 수 있다.
uuid이 사용자 친화적이지 않아서, url에 붙여서 사용할 수 없는 경우가 있다. 이 때에는 slug를 사용하여 사용자 친화적인 url 패턴을 만들면 된다. 만약 slug가 중복된다면, 뒤에 해시값을 붙여서 대체 식별자를 만들 수 있다. 블로그에서 URL에 글의 제목을 활용하는 사례가 이와 같은 방식이다.
https://tomharrisonjr.com/uuid-or-guid-as-primary-keys-be-careful-7b2aa3dcb439
https://bytebase.com/blog/choose-primary-key-uuid-or-auto-increment
'소프트웨어-이야기 > 데이터 저장소 + 시각화 ' 카테고리의 다른 글
<고승범> 실전 카프카 개발부터 운영까지 (1) | 2023.10.03 |
---|---|
Kafka Windowing (0) | 2023.07.22 |
(PostgreSQL) AWS PostgreSQL RDS에 Transaction ID Wraparound 알럿 설정하기 (2) | 2021.04.04 |
(PostgreSQL) Truncate TABLE VS delete (0) | 2021.03.28 |
elasticsearch와 RDB 데이터 저장하기 (0) | 2019.10.23 |