UUID를 PK로 쓰면 인덱스 성능이 떨어진다?
코드 리뷰에서 시작된 궁금증
카카오테크캠퍼스에서 선물하기 API를 구현하면서 회원 식별자로 UUID를 썼다. 코드 리뷰에서 멘토님이 이런 코멘트를 남겼다.
“준영님이라면 이미 아실 것 같기도 한데요. UUID를 사용하셨으니, ULID에 대해서도 한번 참고해보시면 좋겠어요.”
ULID가 뭔지 찾아봤는데 궁금한 점이 생겼다. 멘토님한테 질문했다.
“지금처럼 UUID를 PK로 잡으면 대규모 서비스에서 성능 저하로 이어지나요? 그리고 UUIDv7도 해당 단점을 해결한 것으로 알고 있는데, UUIDv7보다 ULID가 더 권장되나요?”
UUID v4가 느리다는 말의 정체
멘토님 답변은 요약하면 이거였다. 데이터가 커질수록 이런 사소한 차이가 누적될 수 있다.
“네, 그렇습니다. 데이터가 많으면 사소해보이는 성능 저하가 서비스 장애로 이어질 수 있어요.”
UUID v4는 완전히 랜덤하게 생성된다. 이게 B-Tree 인덱스에선 불리할 수 있다.
Auto Increment(순차 삽입)
- 보통 새 데이터가 인덱스 끝에 붙는다
- 페이지 분할이 거의 안 일어난다
UUID v4(랜덤 삽입)
- 새 데이터가 인덱스 아무 데나 끼어든다
- 페이지 분할이 자주 일어난다
- 인덱스가 조각나서 조회도 느려진다
여기서 중요한 건 UUID가 늘 느리다는 뜻이 아니라, 쓰기 패턴(삽입 순서)에 따라 B-Tree에 불리해질 수 있다는 점이었다.
그럼 ULID가 대안인가?
멘토님 답변:
“ULID 사용이 더 권장된다고 볼 수 없을 것 같아요. 저도 UUIDv7에 대해 준영님 덕에 알게 되었는데요. 내용을 조금 찾아보니 UUIDv7은 표준으로 정의되고 있는 과정이더라고요. 저라면 UUIDv7을 사용하는 것을 더 권장드릴 것 같아요. 다만 ULID는 한번 더 인코딩된다는 장점이 있긴 하네요.”
| 특성 | UUID v4 | ULID | UUIDv7 |
|---|---|---|---|
| 시간순 정렬 | 안 됨 | 됨 | 됨 |
| 표준 | RFC 4122 | 비표준 | RFC 9562 |
| 길이 | 36자 | 26자 | 36자 |
ULID도 장점(짧은 길이, 시간순 정렬)이 있지만 비표준이라 팀/조직 표준이나 생태계를 고려할 필요가 있다. 반대로 UUIDv7은 시간순 성질을 가져가면서도 표준이라 설명 비용이 적다.
랜덤성이 오히려 도움이 될 때
멘토님이 다른 관점도 하나 알려줬다.
“데이터를 분산시키려는 목적이라면 UUID v4의 랜덤성이 오히려 이점일 수도 있어요.”
샤딩 환경에서 데이터가 특정 샤드에 몰리지 않게 하려면 랜덤한 키가 유리할 수 있다.
정리
- UUID v4는 랜덤 삽입 특성 때문에 B-Tree 인덱스에 불리할 수 있다(페이지 분할, 조각화).
- 시간순 정렬이 필요하거나, 인덱스 쓰기 부담을 줄이고 싶다면 UUIDv7 같은 선택지가 있다.
- 반대로 분산이 더 중요한 상황(예: 샤딩 키)에서는 랜덤성이 장점이 될 수도 있다.
- 정리하면, 키는 유행 따라 고르기보다 워크로드와 확장 방식을 기준으로 판단하는 편이 낫다.
프로젝트: 카카오테크캠퍼스 3기 선물하기 API 클론 코딩 관련 링크
- GitHub: Neibce/spring-gift-wishlist
