이건 전형적인 조기 최적화의 예시임
영구 식별자에 데이터를 담는 건 데이터 관리의 금기사항임
노르웨이 주민번호처럼 생년월일을 ID에 넣으면, 나중에 출생일을 잘못 알았던 이민자들이 생기거나, 1월 1일 생이 너무 많아 번호가 모자라는 문제를 겪게 됨
과거 카드 카탈로그 시절엔 조회 비용을 줄이려 데이터와 식별자를 섞는 게 이해되지만, 지금은 강력한 데이터베이스가 있으니 굳이 그럴 필요가 없음
이 예시는 사실 잘못된 기본값 설정 문제라고 생각함
모르는 생일을 1월 1일로 지정한 게 문제였지, 날짜를 키에 넣은 게 본질적 문제는 아님
만약 00이나 99 같은 비날짜 값을 썼다면 충돌이 없었을 것임
UUID에 타임스탬프를 넣는 건 의미 부여가 아니라 성능 최적화 목적임
시간 순으로 증가하는 키는 B-tree 재작성 비용을 줄여 DB 삽입 성능을 높임
이탈리아 주민번호도 성별을 포함하는데, 성전환 수술 후엔 문제가 생김
“영구 식별자엔 데이터를 담지 말라”는 건 일반론일 뿐, 상황에 따라 트레이드오프를 감수할 수도 있음
예를 들어 md5 해시를 UUID로 써서 인덱스를 구성하면 단편화는 생기지만 관리 가능한 수준임
UUIDv7은 단순히 시간 편향(random bias) 을 가진 생성 방식일 뿐, 실제 정보를 담는 건 아님
랜덤 vs 시간 기반 UUID 선택은 밀리초 단위가 아니라 초 단위의 성능 차이를 만들 수 있음
작은 DB에선 조기 최적화지만, 규모가 커지면 오히려 반대의 접근이 필요함
대규모 DB에선 샤딩과 분산이 필수라 UUID가 오토인크리먼트보다 낫게 작동함
노르웨이 주민번호 예시에 대해, 실제로 1월 1일 생이 그렇게 많을 수 있는지 의문임
포맷이 DDMMYYXXXXX라면 10만 명까지 커버 가능한데, 정말 그 정도로 몰릴 수 있는지 궁금함
아마 특정 연도에 난민이 대거 유입된 경우 같은 특수 상황일 것 같음
UUID는 보안 토큰처럼 쓰면 안 됨
추측이 어렵다는 이유만으로 보안 기능으로 쓰는 건 위험함
랜덤 값의 목적은 추측 방지뿐 아니라, 연속된 ID 간의 관계를 숨기는 데 있음
DB 종류에 따라 PK 전략이 완전히 달라짐
Postgres에선 랜덤 PK가 비효율적이지만, Cockroach나 Spanner 같은 분산 DB에선 오히려 단조 증가 키가 핫샤드 문제를 일으킴
분산 DB에서도 완전 랜덤보단 증가 경향이 있는 키가 좋음
UUIDv7은 상위 비트가 정렬 가능하고 하위 비트는 랜덤이라 노드 간 분산성과 로컬 저장 효율을 동시에 얻을 수 있음
DB 종류보단 DB 구조의 차이로 봐야 함
일반적인 비샤딩 DB에선 랜덤 키가 B-tree 단편화를 유발함
Google Cloud Bigtable에선 순차 키를 역순(reverse) 으로 써서 자동 분산을 이끌어냄
샤딩된 Postgres라면 랜덤 PK가 유리함
하지만 범위 조회(range query)가 많다면 랜덤 키는 불리함
결국 워크로드 특성에 따라 선택해야 함
쓰기 중심, 시간 편향이 큰 워크로드라면 Postgres에서도 랜덤 PK가 더 나을 수 있음
글의 요지는 UUIDv4를 PK로 쓰는 단점을 잘 짚었지만, 제시된 정수 난독화 방식은 실서비스엔 부적합해 보임
소규모 DB라면 UUIDv7이 합리적 절충안임
나는 UUIDv7 대신 UUIDv4를 선호함
생성 시각이 노출되길 원치 않기 때문임
데이터가 많아 UUIDv4의 랜덤성이 성능 문제를 일으키지 않는 한, v4가 더 안전한 선택임
Postgres에선 단일 시퀀스를 쓰는 걸 좋아함
약간의 정보 노출은 있지만, 운영상 충분히 모호함
단순히 사용자 수를 숨기고 싶다면, 오토인크리먼트 키에 암호화(permutation) 를 적용하면 됨
예를 들어 AES-128로 변환 후 base64로 인코딩하면 YouTube 영상 ID처럼 보이게 만들 수 있음
나는 기술 실사 중 많은 회사를 보는데, 빠른 샤딩 가능성이 기업 성장의 핵심임
UUID를 모든 테이블에 두면 샤딩 시 구조 변경 없이 확장 가능함
약간의 공간·시간 손해보다 훨씬 큰 확장성 이점을 줌
UUIDv7은 단조 증가 특성 덕분에 Postgres에서도 성능상 이점이 있음
우리도 샤딩 과정에서 UUID가 없어 고생했음
결국 복잡한 데이터 모델이라 UUID 유무보다 마이그레이션 자체가 어려웠음
우리 앱은 정수 PK를 암호화해 UUID처럼 보이게 만듦
순차 ID가 노출되면 고객 수 추정이나 딕셔너리 공격이 가능하기 때문임
암호화된 ID는 복호화 실패로 스캐닝 시도를 즉시 탐지할 수 있음
하지만 키 분실이나 교체 시 복호화 불가 문제가 생길 수 있음
키 관리 방식이 궁금함 — 환경 변수로 주입하는지, 코드에 내장하는지, AES-GCM 같은 AEAD 스킴을 쓰는지 등 보안 관리가 중요함
“20억 개면 충분하다”는 말은 위험함
모든 DBA는 그런 결정으로 시작된 악몽 같은 사례를 하나쯤 갖고 있음
글에서 “랜덤 값은 정렬이 비효율적”이라 했는데, 사실 바이트 순서 정렬은 가능함
다만 랜덤 키는 순차 삽입이 아니므로 B-tree 재균형이 자주 일어나 성능 저하가 생김
UUIDv4는 분산 환경에서 유용하지만, 128비트 공간과 비순차성의 대가를 감수해야 함
글쓴이는 이후 B-tree 인덱스 비교 실험을 추가했다고 함
정수 PK는 인덱스가 메모리에 잘 맞고, UUIDv4는 페이지 접근이 많아 지연(latency) 이 커졌다고 함
기술적으로 근거가 약하다는 의견도 있었음
B-tree는 증가 키일수록 삽입 효율이 높고, 랜덤 키는 캐시 친화성이 떨어짐
데이터 접근이 생성 시점과 밀접할수록, 시간 순 정렬이 성능상 유리함
이 글은 문제보다 해결책이 먼저 나온 조기 최적화로 보임
UUIDv4는 대부분의 경우 충분히 괜찮음
성능 문제는 실제로 발생할 때 고려해야 함
하지만 한 번 UUIDv4로 시작하면 나중에 int64로 재키(rekey) 하긴 거의 불가능함
실제로 성능 문제가 생길 땐 이미 성장 단계라 PK를 바꿀 여유가 없음
요약하자면, Postgres에선 UUIDv7이 v4보다 약간 더 나은 성능을 보임
최신 버전에선 플러그인 없이도 UUIDv7 지원이 가능함
다만 글의 핵심은 “가능하면 시퀀스·정수형 PK를 쓰라”는 권장임
Postgres 18부터는 내장 uuidv7() 함수가 있지만, 확장 기능이 더 많은지는 아직 불분명함
Hacker News 의견들
이건 전형적인 조기 최적화의 예시임
영구 식별자에 데이터를 담는 건 데이터 관리의 금기사항임
노르웨이 주민번호처럼 생년월일을 ID에 넣으면, 나중에 출생일을 잘못 알았던 이민자들이 생기거나, 1월 1일 생이 너무 많아 번호가 모자라는 문제를 겪게 됨
과거 카드 카탈로그 시절엔 조회 비용을 줄이려 데이터와 식별자를 섞는 게 이해되지만, 지금은 강력한 데이터베이스가 있으니 굳이 그럴 필요가 없음
모르는 생일을 1월 1일로 지정한 게 문제였지, 날짜를 키에 넣은 게 본질적 문제는 아님
만약 00이나 99 같은 비날짜 값을 썼다면 충돌이 없었을 것임
UUID에 타임스탬프를 넣는 건 의미 부여가 아니라 성능 최적화 목적임
시간 순으로 증가하는 키는 B-tree 재작성 비용을 줄여 DB 삽입 성능을 높임
“영구 식별자엔 데이터를 담지 말라”는 건 일반론일 뿐, 상황에 따라 트레이드오프를 감수할 수도 있음
예를 들어 md5 해시를 UUID로 써서 인덱스를 구성하면 단편화는 생기지만 관리 가능한 수준임
랜덤 vs 시간 기반 UUID 선택은 밀리초 단위가 아니라 초 단위의 성능 차이를 만들 수 있음
대규모 DB에선 샤딩과 분산이 필수라 UUID가 오토인크리먼트보다 낫게 작동함
포맷이 DDMMYYXXXXX라면 10만 명까지 커버 가능한데, 정말 그 정도로 몰릴 수 있는지 궁금함
아마 특정 연도에 난민이 대거 유입된 경우 같은 특수 상황일 것 같음
UUID는 보안 토큰처럼 쓰면 안 됨
추측이 어렵다는 이유만으로 보안 기능으로 쓰는 건 위험함
랜덤 값의 목적은 추측 방지뿐 아니라, 연속된 ID 간의 관계를 숨기는 데 있음
DB 종류에 따라 PK 전략이 완전히 달라짐
Postgres에선 랜덤 PK가 비효율적이지만, Cockroach나 Spanner 같은 분산 DB에선 오히려 단조 증가 키가 핫샤드 문제를 일으킴
UUIDv7은 상위 비트가 정렬 가능하고 하위 비트는 랜덤이라 노드 간 분산성과 로컬 저장 효율을 동시에 얻을 수 있음
일반적인 비샤딩 DB에선 랜덤 키가 B-tree 단편화를 유발함
하지만 범위 조회(range query)가 많다면 랜덤 키는 불리함
결국 워크로드 특성에 따라 선택해야 함
글의 요지는 UUIDv4를 PK로 쓰는 단점을 잘 짚었지만, 제시된 정수 난독화 방식은 실서비스엔 부적합해 보임
소규모 DB라면 UUIDv7이 합리적 절충안임
생성 시각이 노출되길 원치 않기 때문임
데이터가 많아 UUIDv4의 랜덤성이 성능 문제를 일으키지 않는 한, v4가 더 안전한 선택임
약간의 정보 노출은 있지만, 운영상 충분히 모호함
예를 들어 AES-128로 변환 후 base64로 인코딩하면 YouTube 영상 ID처럼 보이게 만들 수 있음
나는 기술 실사 중 많은 회사를 보는데, 빠른 샤딩 가능성이 기업 성장의 핵심임
UUID를 모든 테이블에 두면 샤딩 시 구조 변경 없이 확장 가능함
약간의 공간·시간 손해보다 훨씬 큰 확장성 이점을 줌
결국 복잡한 데이터 모델이라 UUID 유무보다 마이그레이션 자체가 어려웠음
우리 앱은 정수 PK를 암호화해 UUID처럼 보이게 만듦
순차 ID가 노출되면 고객 수 추정이나 딕셔너리 공격이 가능하기 때문임
암호화된 ID는 복호화 실패로 스캐닝 시도를 즉시 탐지할 수 있음
“20억 개면 충분하다”는 말은 위험함
모든 DBA는 그런 결정으로 시작된 악몽 같은 사례를 하나쯤 갖고 있음
글에서 “랜덤 값은 정렬이 비효율적”이라 했는데, 사실 바이트 순서 정렬은 가능함
다만 랜덤 키는 순차 삽입이 아니므로 B-tree 재균형이 자주 일어나 성능 저하가 생김
정수 PK는 인덱스가 메모리에 잘 맞고, UUIDv4는 페이지 접근이 많아 지연(latency) 이 커졌다고 함
이 글은 문제보다 해결책이 먼저 나온 조기 최적화로 보임
UUIDv4는 대부분의 경우 충분히 괜찮음
성능 문제는 실제로 발생할 때 고려해야 함
요약하자면, Postgres에선 UUIDv7이 v4보다 약간 더 나은 성능을 보임
최신 버전에선 플러그인 없이도 UUIDv7 지원이 가능함