ULID 디코더
ULID에서 만들어진 시각과 난수 부분을 뜯어 봅니다. 특정 시각의 ULID 범위를 만들어 기간 조회 조건으로 쓸 수도 있습니다.
26글자입니다. 소문자와 I·L·O도 받아 정규화합니다.
만들어진 시각
2016-07-30T23:54:10.259Z
밀리초로 1,469,922,850,259입니다
사용 방법
- 1ULID 26글자를 붙여 넣으면 만들어진 시각과 난수 부분이 나옵니다.
- 2시각으로 범위 만들기로 바꾸면 그 밀리초의 가장 작은 ULID와 가장 큰 ULID가 나옵니다.
- 3그 두 값을 BETWEEN 조건에 넣으면 인덱스를 그대로 타는 기간 조회가 됩니다.
자주 묻는 질문
128비트를 48비트 밀리초 타임스탬프와 80비트 난수로 나누고 Crockford Base32로 26글자에 담습니다. 앞 10글자가 시각이고 뒤 16글자가 난수입니다. 시각이 앞쪽에 있어 문자열을 그냥 정렬하면 만들어진 순서가 됩니다.
사전순 정렬이 곧 시간순 정렬이 됩니다. UUID v4는 전부 난수라 정렬해도 순서에 뜻이 없습니다. 데이터베이스 인덱스에서도 차이가 나는데, B-tree에 무작위 키를 넣으면 삽입 지점이 흩어져 페이지가 자주 쪼개지지만 증가하는 키는 오른쪽 끝에 붙어 쪼개짐이 적습니다.
완전히 다릅니다. RFC 4648의 base32는 A~Z와 2~7을 쓰지만 Crockford는 0~9와 A~Z에서 I·L·O·U를 뺀 32글자를 씁니다. I와 L은 1과, O는 0과 헷갈리기 때문이고 U를 뺀 것은 우연히 욕설이 만들어지는 것을 피하려는 것입니다. 읽을 때는 I·L을 1로, O를 0으로 받아 주고 대소문자도 가리지 않습니다.
26글자 × 5비트 = 130비트라 128비트보다 두 비트가 많기 때문입니다. 남는 두 비트는 맨 앞에 붙어 언제나 0이어야 하므로 첫 글자의 값이 7을 넘을 수 없습니다. 가장 큰 ULID는 7ZZZZZZZZZZZZZZZZZZZZZZZZZ이고, 8부터 Z로 시작하는 26글자는 형식은 맞아 보여도 ULID가 아닙니다.
시작 시각의 가장 작은 ULID와 끝 시각의 가장 큰 ULID를 만들어 BETWEEN 조건에 넣습니다. 난수 부분을 전부 0으로 채우면 그 밀리초의 하한, 전부 Z로 채우면 상한이 됩니다. 사전순이 시간순과 같으므로 인덱스를 그대로 타며, 별도의 생성시각 컬럼이나 함수 호출이 필요 없습니다.
48비트 밀리초라 서기 10889년까지입니다. 그보다 큰 값은 26글자에 담을 수 없습니다. 실무에서 걸릴 일은 없지만, 시각을 직접 넣어 ULID를 만들 때는 범위를 검사해야 하는 이유입니다.
전송되지 않습니다. 모든 계산은 브라우저 안에서만 이루어집니다. 다만 ULID의 앞부분은 만들어진 시각을 그대로 담고 있으니, 시각이 드러나면 곤란한 곳에는 쓰지 않는 편이 좋습니다.
알아두면 좋은 점
- ULID의 앞부분은 만들어진 시각을 그대로 드러냅니다. 시각을 감춰야 하는 곳에는 적합하지 않습니다.
- 증가하는 키는 인덱스의 마지막 페이지에 쓰기가 몰립니다. 쓰기가 아주 많은 분산 환경에서는 오히려 불리할 수 있습니다.
- Crockford Base32는 RFC 4648의 base32와 문자표가 달라 서로 호환되지 않습니다.
함께 보면 좋은 도구
마지막 검증: 2026년 8월 31일 · 결과는 참고용 추정치입니다.