9.7 KiB
title, source_type, url, archive_url, related_branches, related_projects, tags, created, vendor, last_reviewed
| title | source_type | url | archive_url | related_branches | related_projects | tags | created | vendor | last_reviewed | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| official-doc / ULID — Universally Unique Lexicographically Sortable Identifier (공식 Spec) | official-doc | https://github.com/ulid/spec |
|
|
|
2026-05-31 | ulid/spec (alizain — original author) | 2026-05-31 |
official-doc / ULID Spec — Universally Unique Lexicographically Sortable Identifier
Layer:
raw/official-docs/— ULID 공식 사양(spec) 원문 발췌 및 출처 기록. 검증된 요약은/ingest후wiki/concepts/에 별도 작성. 원본은 raw 에 영구 보관.
Parent / 활용 branch (필수)
이 자료는 혼자 존재하지 않는다. 아래 branch 의 구현 결정 근거로서 보관됨.
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-resource-identifier-contract | D1 (resource ID 기본 형식 후보로서 ULID 26자 base32), D2 (Crockford base32 charset — I/L/O/U 제외), D3 (base32 case-insensitive + URL-safe 특성), D7 (48bit millisecond timestamp 평문 노출 — timestamp leak 위험 범위 정의), D10 (lexicographic 단조 정렬 → DB B-tree index 단편화 완화 근거) |
출처 / Source
- 원본 URL: https://github.com/ulid/spec
- 아카이브 URL: (미입력)
- 저자 / 조직: alizain (original author), ulid GitHub org
- 발행일: (최초 commit 이후 지속 관리 — pinned spec)
- 마지막 확인일: 2026-05-31
왜 저장했는지 / Why archived
ca-skeleton 의 resource ID 기본 형식 결정(D1)에서 ULID 가 유력 후보로 거론된다. 이 자료는 ULID 의 공식 사양(인코딩 형식, 타임스탬프 노출, 단조 정렬 보장, 바이너리 레이아웃)을 원문 그대로 기록하여, D1/D2/D3/D7/D10 결정의 verbatim 근거를 제공한다.
핵심 인용 / Key quotes (verbatim, 5개)
[§Spec header — bullet list, line 28] "Canonically encoded as a 26 character string, as opposed to the 36 character UUID"
[§Specification → Components → Timestamp, lines 105-107] "48 bit integer" / "UNIX-time in milliseconds" / "Won't run out of space 'til the year 10889 AD."
[§Specification → Encoding, line 129] "Crockford's Base32 is used as shown. This alphabet excludes the letters I, L, O, and U to avoid confusion and abuse."
[§Specification → Sorting, line 115] "The left-most character must be sorted first, and the right-most character sorted last (lexical order). The default ASCII character set must be used. Within the same millisecond, sort order is not guaranteed"
[§Specification → Monotonicity, lines 137-139] "When generating a ULID within the same millisecond, we can provide some guarantees regarding sort order. Namely, if the same millisecond is detected, the
randomcomponent is incremented by 1 bit in the least significant bit position (with carrying)."
[§Specification → Binary Layout and Byte Order, line 177] "The components are encoded as 16 octets. Each component is encoded with the Most Significant Byte first (network byte order)."
Claims Extracted / 추출된 주장
이 자료가 직접 말하는 것만 claim 으로 분리한다. ca-skeleton 에 적용한 결론은 여기 쓰지 않는다.
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| ULID-C1 | ULID 는 128비트 식별자를 26자 Crockford base32 문자열로 인코딩한다 (UUID 의 36자 대비 shorter) | [§header] "Canonically encoded as a 26 character string, as opposed to the 36 character UUID" | official-standard |
ULID spec 을 따르는 모든 구현체 | 특정 언어 라이브러리가 이 길이를 올바르게 구현함을 증명하지 않음 |
| ULID-C2 | ULID 의 타임스탬프 컴포넌트는 48비트 정수이며 Unix millisecond epoch 이다 | [§Timestamp] "48 bit integer" / "UNIX-time in milliseconds" | official-standard |
ULID spec 준수 구현체 | 48bit 노출이 특정 privacy 위험을 야기함을 spec 이 직접 주장하지 않음; D7 위험 평가는 별도 분석 필요 |
| ULID-C3 | Crockford base32 알파벳은 I, L, O, U 를 제외하여 혼동과 오용을 방지한다; case-insensitive 특성이 spec 에 명시됨 | [§Encoding] "Crockford's Base32 is used as shown. This alphabet excludes the letters I, L, O, and U to avoid confusion and abuse." / [§header] "Case insensitive" | official-standard |
Crockford base32 인코딩을 사용하는 ULID | case-insensitive 동작이 모든 DB/HTTP layer 에서 자동 적용됨을 증명하지 않음; normalize 정책은 구현 결정 |
| ULID-C4 | ULID 는 lexicographic 정렬(leftmost-first, ASCII)을 보장하나, 동일 밀리초 내에서는 보장 없음 | [§Sorting] "The left-most character must be sorted first, and the right-most character sorted last (lexical order). The default ASCII character set must be used. Within the same millisecond, sort order is not guaranteed" | official-standard |
ULID 문자열 비교·정렬 전반 | lexicographic 정렬이 DB index 단편화를 완화함을 spec 이 직접 증명하지 않음; DB 성능 영향은 별도 벤치마크 필요 |
| ULID-C5 | Monotonic factory 는 동일 밀리초 내 ULID 생성 시 random 컴포넌트를 최하위 비트에서 1 증가(carrying)하여 단조 정렬을 보장한다 | [§Monotonicity] "if the same millisecond is detected, the random component is incremented by 1 bit in the least significant bit position (with carrying)." |
official-standard |
monotonic generator API 를 사용하는 ULID 구현체 | 기본(non-monotonic) ULID factory 가 동일 밀리초 내 정렬을 보장하지 않음; 구현체가 monotonic factory 를 기본 노출하는지는 각 라이브러리 doc 확인 필요 |
| ULID-C6 | ULID 바이너리 레이아웃은 16 옥텟, Most Significant Byte first (network byte order) 로 인코딩된다 | [§Binary Layout] "The components are encoded as 16 octets. Each component is encoded with the Most Significant Byte first (network byte order)." | official-standard |
binary(16) 컬럼 저장 또는 UUID ↔ ULID 변환 시 | JavaScript 구현체가 binary format 을 아직 미구현했다고 spec 이 주기적으로 언급 (note 참조); 모든 라이브러리가 binary layout 을 지원하는지 별도 확인 필요 |
Strength 허용값
이 문서의 모든 claim 은 ULID 원저자가 관리하는 GitHub 공개 spec 에서 직접 인용하였으므로 official-standard 로 분류.
Usage Boundaries / 적용 경계
-
이 자료가 직접 증명하는 것:
ULID-C1: ULID 는 26자 Crockford base32 이며 128bit 식별자 (UUID 와 동일 비트 수)ULID-C2: 타임스탬프가 48bit millisecond Unix epoch — D7 timestamp leak 위험의 spec 근거ULID-C3: 알파벳이 I/L/O/U 제외 32자이며 case-insensitive — D2/D3 charset 근거ULID-C4: 문자열 lexicographic 정렬 보장 (동일 ms 내 제외) — D10 DB index 정렬 성능 주장의 전제ULID-C5: Monotonic factory 의 동작 정의 — D10 에서 단조 증가 보장이 필요한 경우의 근거ULID-C6: Binary(16) 레이아웃 정의 — DB primary key binary(16) 저장 정책(D10)의 format 근거
-
이 자료가 증명하지 않는 것:
- DB B-tree index 단편화 완화 효과 (정량 벤치마크 필요 — UUID v4 vs ULID 비교 데이터는 별도 자료)
- 특정 Java ULID 라이브러리(예:
de.huxhorn.sulky:sulky-ulid,com.github.f4b6a3:ulid-creator)의 구현 품질 또는 thread-safety - ULID 의 timestamp leak 이 GDPR/CCPA 위반을 구성하는지 (법적 해석은 별도 분석)
- monotonic factory 를 기본 제공하는지 여부 (라이브러리마다 API 다름)
- PostgreSQL
uuidnative 타입과 ULID 26자 varchar 저장의 성능 차이 - UUID v7 (RFC 9562) 과 ULID 의 timestamp 인코딩 방식 차이 (RFC 9562 별도 자료 필요)
-
ca-skeleton 에 적용하려면 추가 확인이 필요한 것:
- Java ULID 라이브러리 선택 (API 안정성, 활성 유지보수, monotonic factory 노출 방식)
- Spring/Hibernate 에서 ULID 26자를
varchar(26)vsbinary(16)중 어느 컬럼 타입으로 저장할지 - JPA
@GeneratedValue커스텀 generator 구현 방식 (D5 architecture layer 결정 전제) - URL path 에서 대소문자 normalize 의무 여부 (RFC 3986 §2.3 + D3 결정과 연동)
메모 / Notes
- spec README 가 JavaScript 구현체를 canonical reference 로 명시하지만, binary format 은 "not yet implemented in JavaScript" 라고 적혀 있음. 다른 언어 구현체(Java, Go 등)는 binary layout 구현 여부가 다름.
1.21e+24 unique ULIDs per millisecond는 spec 의 bullet 항목이나, 이것은 80bit random 의 수학적 최대치이지 monotonic factory 의 실제 처리량 한계와 다름 (monotonic factory 는 2^80 을 넘으면 exception).- Crockford base32 알파벳 문자열:
0123456789ABCDEFGHJKMNPQRSTVWXYZ(32자, 대문자 기준) — self-grep line 132. - 최대 유효 ULID:
7ZZZZZZZZZZZZZZZZZZZZZZZZZ(spec 명시, line 171). 이보다 큰 값은 모든 구현체가 reject 해야 함. - ULID 의 Prior Art 로 Instagram sharding ID (2011) 와 Firebase pushID (2015) 를 spec 이 언급.
Related / 관련
- 같은 결정 영역의 다른 공식 자료 (예정):
- raw/official-docs/rfc9562-uuid.md — UUID v4/v7 공식 스펙 (RFC 9562)
- raw/official-docs/cuid2-spec.md — CUID2 timestamp-free 식별자 spec
- raw/official-docs/crockford-base32-spec.md — Crockford base32 원 사양
- raw/official-docs/rfc3986-uri-generic-syntax.md — URI 허용 charset / case sensitivity 규칙 (D3 근거)
- 이 자료를 인용한 wiki 요약: (생성 전)