UUID를 Primary Key로 사용하기

avatar

최근 MSA1 가 곽광받기 시작하면서
UUID를 Primary Key 로 사용하는 경우가 많아졌다.
UUID를 사용하면 어떤 이점이 있는지 어떤 경우에 사용해야하는지 알아보고자 한다.

UUID (Universally Unique Identifier)

범용 고유 식별자라고도 하며 RFC4122 (opens in a new tab) 에도 등재되어있다.

분산 컴퓨팅 환경에서 개체들을 서로 구별하기 위해서
고유한(유일성을 보장할 수 있는) 식별자가 필요한데 이를 위해 등장하였다.

UUID 는 총 32개의 16진수로 이루어져있으며
하이픈(-)으로 조합해 다음과 같은 형태를 가지고있다.

UUID 생성

중복될 확률은 없을까?

To put these numbers into perspective, the annual risk of a given person being hit by a meteorite is estimated to be one chance in 17 billion, which means the probability is about 0.00000000006 (6 × 10−11), equivalent to the odds of creating a few tens of trillions of UUIDs in a year and having one duplicate. In other words, only after generating 1 billion UUIDs every second for approximately 100 years would the probability of creating a single duplicate reach 50%.
> Read more (opens in a new tab)

UUID

1년에 사람이 운석에 맞을 확률은 170억 분의 1로 추정된다.
즉, 확률은 약 0.00000000006 (6 × 10−11) 이며,
이는 1년에 수십조 개의 UUID를 생성하는동안
한개의 중복을 가질 확률과 동일하다.

다시말해 앞으로 100년 동안
매초 10억 개의 UUID를 생성한다 해도
한개의 중복이 발생할 확률은 약 50% 정도다

Auto Increment 형식의 한계

기존 모놀리식 아키텍처(Monolithic Architecture)에서는
일반적으로 자동으로 증가하는 Sequential Number(Auto Increment)를 PK로 사용하고
이는 당연하게도 하나의 코드베이스를 사용하기 때문에 유일성을 보장한다

하지만 많은 기업들이 MSA를 도입하면서 UUID를 이용한 디자인이 늘고있다
왜 UUID 안쓰시고 Auto Increment 사용하셨어요? 라는 말을 들을정도
그럼 Auto Increment를 PK (resource id) 로 사용할 경우 어떤 단점이 있을까?

분산형 시스템에서 통합의 한계

분산형 시스템에서 시스템간의 통합
UUID는 모든 시스템에서 유일성을 보장하기 때문에 시스템간 통합이 간편한 반면
Auto Increament의 경우 단일 시스템 내에서만 유일성을 보장하기 때문에 통합이 어렵다.

e.g.
A 시스템의 유저와 B 시스템의 유저의 통합시
A 시스템의 User.id 와 B 시스템의 User.id 의 중복

보안상으로 외부 노출의 위험

id 그 자체로 정보 유추가 가능하다 다음과 같은 회원을 조회하는 API 가 있다고 가정

api/users/42338

알 수 있는 사실

  • api/users/42339 로 다음 회원 조회 가능
  • 최소 42338개의 회원 id가 생성됨

이렇게 외부에 알려질 경우 정보가 유츌될 위험이 있다.


💁🏻
그럼 Auto Increament말고 UUID를 써야겠군요!

장단점에 대해서 더 알아보자

성능

  • 기본적으로 16바이트를 차지하는 UUID가 Auto Increment보다 더 많은 공간을 차지한다.
  • 클러스터링된 PK를 사용하는 RDB의 경우 Auto Increment가 아닌
    임의의 UUID를 사용하게되면 PK에 맞춰 행을 재정렬해야하기 때문에 삽입 성능에 영향을 준다.

따라서 스토리지 / 메모리 등에 영향을 준다.

가독성, 디버깅

ticket-42
ticker-20ff7190-590f-4700-ab62-a6c45a066628

postId = 24
postId = bb785b82-f3a2-492c-8c17-28bb8e957b8f

어느쪽이 읽기 쉬울까?

Stateless

Auto Increment의 경우 새로 PK를 사용하기 위해 기존 데이터베이스를 참조해야하지만
UUID는 유일무이에 가깝기때문에 언제 어디서든 바로 생성해서 사용이 가능하다.

결론

🤷🏻
그럼 뭘 사용해야하죠?

정답은 없다

위의 장단 필요에 따라 사용하면 될거같다.

분산 시스템이 필요한가?
리소스의 외부 노출에 민감한 내용인가?
가독성이 중요한가?

변칙적인 경우도 존재한다.

Sequentially 한 UUID를 생성해 사용하는 방법도 있으나
순서 유추가 불가능한 UUID의 장점을 저해하는 부분이기도 하고
둘다 사용하는 방법도 있다.


Footnotes

  1. Micro Service Architecture
    대규모 애플리케이션을 각 기능별로 독립한 서비스로 구성된 아키텍처