15P by neo | ★ favorite | 댓글 4개
  • PostgreSQL 18에서는 UUIDv7을 기본 지원하며, 정렬 가능하고 인덱스 친화적인 고유 식별자를 제공
  • UUIDv7은 기존 UUID의 분산 환경에서의 고유성과 보안성은 유지하면서, btree 인덱스에 유리한 시간 기반 정렬 구조를 채택함
  • 기존 UUID 사용의 단점이었던 정렬 불가, 인덱스 난삽, 메모리 크기 중 앞의 두 문제를 해결하며 시간순 정렬 및 삽입 최적화를 실현함
  • PostgreSQL 18에서는 uuidv7() 함수로 UUID 생성이 가능하고, 타임스탬프 추출 및 커스텀 시간 입력 기능도 제공함
  • 이제 UUID를 기본 키로 사용하는 것을 주저하던 이유가 해소되어, 분산 시스템 및 다중 테넌트 환경에서 더 적합한 선택지가 됨

PostgreSQL 18

  • PostgreSQL 18의 베타 버전이 출시되었고, 9월 정식 릴리스를 목표로 테스트가 진행 중임
  • 주요 기능:
    • Async I/O: io_uring 기반 비동기 입출력으로 시퀀스 스캔 및 vacuum 2~3배 속도 개선
    • 멀티 컬럼 btree 인덱스의 Skip scan, OR/IN 쿼리 최적화
    • 업그레이드 간 플래너 통계 유지
    • UUIDv7 함수
    • 가상 생성 칼럼, OAuth 로그인, EXPLAIN에 I/O/CPU/WAL 정보 추가 등

UUID의 장점

  • 분산 환경에서 고유 ID 생성 가능
  • 예측 불가능한 공개 식별자로 보안성 강화
  • 클라이언트에서 직접 ID 생성 가능하여 서버 통신 최소화

기존 UUID의 단점

  • 정렬 불가능
  • 인덱스 비국소성으로 인한 삽입 성능 저하
  • 128비트 크기로 인한 오버헤드

UUIDv7의 해결책

  • RFC 9562 (2024년 5월 발표) 에 따라 도입된 신형 UUID 버전
  • 앞의 48비트에 Unix Epoch 기반 타임스탬프, 나머지에는 무작위값 + 카운터를 조합
  • 시간 순 정렬 가능하며, 인덱스 삽입 효율 증가
  • UUIDv6는 하위 호환용, UUIDv8은 실험/벤더 확장용
  • UUIDv7만이 실질적으로 의미 있는 새로운 표준

PostgreSQL 18에서의 UUIDv7 사용

  • uuidv7() 함수로 현재 시각 기반 UUID 생성
  • uuidv7(INTERVAL)을 통해 원하는 시간 offset 반영 가능
  • uuid_extract_version(), uuid_extract_timestamp() 함수로 UUID 버전 및 생성 시간 추출 가능
  • 예시:
    CREATE TABLE test (  
        id uuid DEFAULT uuidv7() PRIMARY KEY,  
        name text  
    );  
    
    INSERT INTO test (name) VALUES ('foo');  
    INSERT INTO test (name) VALUES ('bar');  
    INSERT INTO test (id, name) VALUES (uuidv7(INTERVAL '-1 hour'), 'oldest');  
    
    SELECT uuid_extract_timestamp(id), name FROM test ORDER BY id;  
    
  • uuidv4()gen_random_uuid()의 별칭으로 추가됨

결론 및 권장 사항

  • UUIDv7은 기존 UUID 사용 시 성능 문제를 겪던 사용자들에게 적합
  • 정렬성과 인덱스 성능을 확보하면서도 UUID의 장점 유지
  • PostgreSQL 18 베타에서 지금 바로 테스트 가능
  • 분산 시스템, 다중 테넌트 앱, 서버리스 환경에서의 ID 생성에 적합한 선택지

“UUIDv7는 조용하지만 강력한 기능 추가로, Postgres에서 UUID를 기본 키로 사용하는 것을 다시 고려하게 만듦”

GeekNews Weekly에 포함된 글입니다. 에디터 코멘트 보기

댓글과 토론

저는 대신 Prisma + ULID를 사용하고 있습니다. 훨씬 짧고 좋아요.

uuid_generate_v7() 같은 함수 만들어서 사용하고 있었는데 반가운 소식이네요.