UUID v4 vs UUID v7 비교: B-Tree 인덱스 특성과 데이터베이스 키 설계
RFC 9562 신규 표준 UUIDv7이 왜 데이터베이스(PostgreSQL, MySQL)의 B-Tree 인덱스 단편화를 줄이고 쓰기 성능을 개선하는지 설명합니다.
UUID 생성기
서버 전송 없이 100% 브라우저 로컬에서 안전하게 직접 테스트하고 검증해보세요.
분산 시스템 기본 키(PK)로서의 UUIDv4의 장점과 한계
UUID(Universally Unique Identifier)는 중앙 발급 기관 없이도 전 세계에서 중복 없는 고유값을 생성할 수 있는 128비트 식별자입니다. 그중 UUIDv4는 122비트의 완전한 암호학적 난수를 사용하여 프론트엔드나 분산 마이크로서비스에서 DB 요청 없이 ID를 선발급할 수 있어 널리 쓰여왔습니다.
하지만 UUIDv4를 관계형 데이터베이스(PostgreSQL, MySQL InnoDB)의 클러스터형 기본 키(Clustered Primary Key)로 채택하면, 테이블이 대규모로 확장될 때 쓰기 성능에 병목이 발생할 수 있습니다.
UUIDv4가 데이터베이스 B-Tree 인덱스 성능에 미치는 영향
관계형 데이터베이스는 기본 키를 B-Tree 인덱스 구조로 관리합니다:
- 순차 증가 정수(AUTO_INCREMENT)를 쓰면 새로운 행은 항상 B-Tree의 맨 오른쪽 리프 노드에 순차적으로 추가됩니다. 한 페이지가 차면 새 페이지를 깔끔하게 할당하므로 높은 페이지 적재 밀도를 유지합니다.
- 반면 UUIDv4는 무작위 난수이므로 B-Tree 전체 리프 페이지에 불규칙하게 파고듭니다. 이미 가득 찬 중간 페이지에 새 데이터가 들어가면 디스크 블록을 둘로 쪼개는 페이지 분할(Page Split)이 빈번하게 발생합니다.
- 데이터 인덱스가 서버 메모리(RAM) 용량을 넘어서면 매 인서트마다 디스크에서 무작위 페이지를 읽어오고 더티 페이지를 쓰는 랜덤 I/O가 늘어나 대규모 테이블에서 쓰기 처리 성능이 크게 저하될 수 있습니다.
RFC 9562 신규 표준 UUIDv7: 시간 순차 정렬의 구조
RFC 9562 표준의 UUIDv7은 기존의 무작위 방식의 장점(충돌 방지)과 순차 정수 방식의 장점(B-Tree 인덱스 정렬성)을 결합했습니다:
- 상위 48비트: 밀리초 단위의 Unix 타임스탬프가 빅엔디안 정수로 기록됩니다(서기 10000년 이후까지 유효).
- 중간 4비트: UUID 버전 정보(
0111, 즉 버전 7). - 중간 12비트 (
rand_a): 밀리초 미만 순서 정렬을 위한 시퀀스 카운터 또는 분수 타임스탬프(고속 연속 발급 시 순서 유지). - 다음 2비트: UUID 변형(Variant
10). - 하위 62비트 (
rand_b): 암호학적 난수 바이트.
UUIDv7은 생성 시점 순서대로 자연 정렬되므로, 데이터베이스에 삽입될 때 최신 리프 페이지 끝에 순차적으로 추가되어 B-Tree 페이지 분할을 크게 줄여줍니다.
현대 프로그래밍 언어 및 데이터베이스에서 UUIDv7 도입 가이드
- PostgreSQL: PostgreSQL 18부터 내장 함수
uuidv7()이 지원됩니다. PostgreSQL 17 이하 버전에서는pg_uuidv7확장이 제공하는uuid_generate_v7()함수를 사용할 수 있습니다. - Node.js / TypeScript: 표준
uuid패키지의v7()함수를 사용할 수 있습니다. - Python: Python 3.14 이상에서
uuid.uuid7()이 기본 탑재되었습니다. - DevUtils의 UUID Generator 도구에서도 단일/대량 UUIDv4 및 UUIDv7을 즉시 생성하고 테스트할 수 있습니다.
무중단 마이그레이션 전략: UUIDv4에서 UUIDv7으로의 전환 실무
기존 대규모 프로덕션 데이터베이스를 UUIDv4에서 UUIDv7으로 전환할 때는 테이블 락(Lock)을 방지하기 위한 체계적인 무중단 마이그레이션이 필수적입니다:
- 그림자 컬럼(Shadow Column) 추가: 기존
id컬럼 외에 새로운 nullableid_v7컬럼을 추가합니다. - 애플리케이션 계층 듀얼 라이트(Dual-Write): 신규 인서트 시 UUIDv7을 발급하여
id_v7에 저장하되, 조회 쿼리는 기존id를 계속 사용합니다. - 비동기 백필(Backfill): 트래픽이 적은 시간대에 백그라운드 워커를 가동하여, 기존 행의 원본 생성일(
created_at) 타임스탬프를 기반으로 UUIDv7을 생성하여 빈 슬롯을 채웁니다. - 동시성 인덱스 생성(Concurrent Indexing): PostgreSQL의
CREATE UNIQUE INDEX CONCURRENTLY를 사용하여 쓰기 락 없이id_v7에 유니크 인덱스를 구축합니다. - 제약조건 교체 및 컷오버: 짧은 트랜잭션 내에서 기본 키 제약조건을 교체하고 레거시 컬럼을 단계적으로 제거합니다.
-- PostgreSQL 무중단 UUIDv7 인덱스 생성 및 마이그레이션 패턴
ALTER TABLE orders ADD COLUMN id_v7 UUID DEFAULT uuidv7();
-- 기존 데이터 비동기 백필 (쓰기 락 최소화)
UPDATE orders SET id_v7 = uuidv7() WHERE id_v7 IS NULL;
-- 서비스 중단 없이 읽기/쓰기를 허용하며 유니크 인덱스 생성
CREATE UNIQUE INDEX CONCURRENTLY idx_orders_id_v7 ON orders(id_v7);UUID 생성기
온라인 무료 UUID v4 생성기. Web Crypto API를 사용한 안전한 고성능 랜덤 UUID 생성.