Hacker News 의견들
  • 이건 전형적인 조기 최적화의 예시임
    영구 식별자에 데이터를 담는 건 데이터 관리의 금기사항임
    노르웨이 주민번호처럼 생년월일을 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() 함수가 있지만, 확장 기능이 더 많은지는 아직 불분명함
    • 대부분의 사용자는 이제 별도 확장이 필요 없을 것임