03 / 가이드
UUID vs ULID: 애플리케이션의 식별자 선택하기
UUID v4 대 v7, ULID의 구조와 정렬 가능성, 무작위 식별자가 B-트리 인덱스에 미치는 영향, 충돌 확률, URL에서의 노출, 그리고 로컬에서의 식별자 생성.
애플리케이션 식별자가 해야 하는 것
생성되는 식별자의 본업은 유일함 하나이고, 거기에 따라붙는 일이 몇 가지 있습니다. 조정 없이 어디서나 생성될 것, 컴팩트하게 저장될 것, 예측 가능하게 정렬될 것, 난처한 정보를 새지 않을 것. UUID와 ULID는 둘 다 유일성 관문을 통과합니다. 다른 점은 그 이후의 모든 것입니다.
- 조정 불필요분산 생성: 어떤 서비스, 워커, 브라우저 탭이든 중앙 카운터에 묻지 않고 식별자를 주조할 수 있습니다. 두 형식이 분산 시스템에 맞는 이유가 이것입니다.
- 같은 128비트어느 쪽이든 128비트: UUID는 하이픈 있는 16진수 36자로 쓰는 128비트 값이고, ULID는 같은 128비트를 26자의 base32로 담습니다.
- 레이아웃이 차이진짜 질문은 레이아웃입니다. 어떤 비트가 무작위이고 어떤 비트가 시간을 부호화하는지가 인덱스 안에서 식별자의 거동과 그것이 드러내는 것을 결정합니다.
UUID 버전: v4는 무작위, v7은 시간순
RFC 9562는 여러 UUID 버전을 정의하지만 애플리케이션 작업을 지배하는 것은 둘입니다. 버전 4는 128비트 중 122비트를 무작위로 채우고 다른 것은 아무것도 심지 않습니다. 버전 7은 48비트 Unix 밀리초 타임스탬프로 시작해 나머지 74비트를 무작위로 채웁니다.
- v4: 순수 무작위v4는 프라이버시 최대의 선택입니다. 값은 언제 어디서 만들어졌는지 아무것도 말하지 않고, 122개의 무작위 비트는 어떤 애플리케이션도 다 쓰지 못할 유일성입니다.
- v7: 시간이 먼저v7은 생성 시각으로 밀리초 정밀도로 정렬되므로, 나중에 생성된 식별자가 먼저 것 뒤에 놓입니다. 데이터베이스가 기본 키에 바라는 바로 그 성질입니다.
- v1은 건너뛰기오래된 버전은 레거시입니다. v1은 MAC 주소와 시계 값을 심어 둘 다 샜고, v3와 v5는 안정된 ID를 도출하기 위한 이름 기반 해시이지 신선한 무작위가 아닙니다.
ULID: 텍스트로도 정렬 가능하고 컴팩트
ULID는 Crockford base32의 26자입니다. 처음 10자가 48비트 밀리초 타임스탬프를 부호화하고, 나머지 16자가 80개의 무작위 비트를 부호화합니다. 알파벳은 I, L, O, U를 의도적으로 제외해서, 소리 내어 읽거나 스크린샷에서 손으로 옮겨도 식별자가 살아남습니다.
- 문자열 정렬=시간 정렬사전식 순서가 곧 시간 순서: ULID를 평범한 문자열로 정렬하면 파싱 없이 생성 시각순으로 정렬됩니다. 로그 줄, 파일 이름, 키-값 저장소에서 유용합니다.
- 26개의 안전 문자컴팩트하고 URL 안전: 대소문자를 가리지 않는 26자에 하이픈도 기호도 없어서 UUID의 36자보다 짧고, 어떤 경로 세그먼트나 쿼리 파라미터에도 안전합니다.
- 밀리초당 단조같은 밀리초 안에서는 순서가 무작위 부분에서 나옵니다. Toolars 배치 생성기처럼 그것을 단조 증가시키는 생성기는 같은 밀리초의 식별자까지 생성 순서를 유지합니다.
무작위 ID는 인덱스를 단편화한다
B-트리 인덱스는 정렬되어 있고, 무작위 UUID v4의 삽입은 매번 무작위 리프에 씁니다. 페이지가 쪼개지고, 버퍼 캐시가 출렁이고, 인덱스가 죽은 공간으로 불어납니다. 시간순 식별자는 인덱스의 오른쪽 가장자리 근처에 추가되어 삽입을 B-트리의 최선 사례로 바꿉니다.
이것이 이 선택이 처음 느려지는 분기 이후가 아니라 스키마 설계 시점의 몫인 이유입니다. 기본 키 마이그레이션은 모든 행과 그것을 참조하는 모든 외래 키의 재작성을 뜻합니다. 테이블이 계속 작게 유지된다면 v4의 무질서는 결코 모습을 드러내지 않습니다. 끊임없는 쓰기 아래 수억 행으로 자랄 것이라면, 정렬된 형식은 첫날부터 보답합니다.
- 무작위는 흩뿌린다v4를 기본 키로 쓰면 삽입이 많은 테이블에서 같은 크기의 정렬된 키에 비해 페이지 분할이 늘고, 채움률이 낮아지고, 쓰기 처리량이 측정 가능할 만큼 나빠집니다.
- 정렬은 이어 붙인다v7과 ULID는 생성을 분산한 채로 지역성을 회복합니다. 시퀀스도 조정도 없고, 다른 행의 ID에 대한 예측 가능성도 여전히 없습니다.
- 대가를 재라대가는 실재하지만 완만합니다. 128비트는 bigint 저장의 두 배이고, 시간순 키는 오늘의 쓰기를 인덱스 오른쪽 가장자리에 집중시키지만, 그것이 문제가 되는 것은 매우 높은 삽입률에서뿐입니다.
충돌, URL, 그리고 ID가 드러내는 것
먼저 충돌 수학입니다. v4의 122개 무작위 비트로 10억 개의 식별자를 생성해도 충돌 확률은 10^18분의 1 정도——사실상 절대 일어나지 않습니다. ULID의 80개 무작위 비트가 지키는 예산은 다릅니다. 같은 밀리초 안에 만들어지는 식별자들입니다.
수상한 값은 무엇이든 검증기에 붙여 넣으세요. RFC 9562 배리언트와 버전 니블을 갖춘 정규 36자 UUID 형태, 오버플로 규칙을 갖춘 26자 ULID 알파벳을 인식하고, 시간순 형식의 내장 타임스탬프를 보고합니다. 로그의 값이, 그것을 바탕으로 무언가를 만들기 전에, 자신이 무엇인지 알려줍니다.
- 확률은 무시 가능어느 형식도 보안 경계가 아닙니다. URL 안의 식별자는 주소 지정에는 괜찮지만, 그것을 본 사람은 누구나 인용할 수 있습니다. 인가는 ID의 불투명성이 아니라 접근 검사에서 나와야 합니다.
- ID는 비밀이 아니다v7과 ULID는 설계상 생성 시각을 샙니다. 검증기는 그것을 공개적으로 추출합니다. 대개는 무해한 메타데이터지만, 공개 대상 객체에서는 의식적으로 결정하세요.
- 시간은 보인다순차적 데이터베이스 ID는 규모와 성장률을 샙니다. 무작위 및 시간+무작위 식별자는 레코드가 몇 건인지에 대해 아무것도 드러내지 않습니다.
서버 없이 생성하고 검증하기
식별자 생성에는 딱 하나의 희소 자원——좋은 무작위성——이 필요하고, 브라우저는 이미 그것을 가지고 있습니다. 작업 영역은 crypto.getRandomValues에서 가져와 배치 전체를 탭 안에서 생성하고, 어떤 값도 전송하지 않습니다.
- 배치당 1~100UUID v4, UUID v7, ULID 중에서 고르고 배치당 1~100개를 생성하세요. v7과 ULID 배치는 무작위 필드를 단조 증가시키므로 배치 전체가 생성 순서를 유지합니다.
- 대소문자와보내기출력 대소문자는 표시상의 선택입니다. 정규, 대문자, 소문자. 전체 복사에 더해, 각 식별자의 내장 시각을 기록하는 줄바꿈 텍스트와 CSV 다운로드가 있습니다.
- 즉시 검증검증은 구조에 관한 질문에 즉답합니다. 길이, 알파벳, UUID 버전과 배리언트, nil과 max 특수 값, ULID 오버플로, 그리고 UTC의 내장 타임스탬프.
ULID는 base32이고, 당신의 토큰은 아마 Base64입니다.
바이트-텍스트 인코딩은 모든 식별자와 토큰 밑에 깔려 있습니다. 그 비용과, 쓸 값어치가 있는 곳을 배워 보세요.