UUID와 ULID

niz w·2025년 1월 13일

Spring

목록 보기
13/17

PK로 둘 ID 값을 배운대로만 써먹다 보니, AUTO INCREMENT만 생각했었다😂

그러다가 찾아보니 UUID와 ULID 자체를 PK로도 많이 쓸 뿐 아니라,
내가 알던 UUID보다 ULID가 속도도 좋아서 많이들 쓴다고 한다!



✨ UUID

  • 128비트 길이의 고유 식별자
  • 다양한 버전이 있으며, 주로 4 버전이 사용된다.
  • 랜덤 값과 시간 기반 값 등을 사용해 설정한다.
  • 32개의 16진수로 구성되고, 4개의 하이픈으로 구분한다. (8-4-4-4-12 형식 / 총 36자).

🎈 생성 방법

  • 완전한 랜덤값을 사용하여 생성한다. (4버전)
    ex) 550e8400-e29b-41d4-a716-446655440000

UUID는 총 5가지 버전이 있는데, 버전에 따라 생성 방식이 조금씩 다르다!

버전 1: 현재 시간 및 하드웨어 주소(MAC) 기반.
버전 2: DCE 보안 버전 (잘 사용되지 않음).
버전 3: MD5 해시 기반.
버전 4: 랜덤 값 기반.
버전 5: SHA-1 해시 기반.


🎈 장점

  • 전역 고유성을 보장해준다.
    물론 랜덤중에서도 중복은 발생할 수 있다지만, 그 확률은 매우 희박하다.
  • 표준화되어 있어서 다양한 시스템과 언어에서 지원된다.
  • 분산 시스템에 적합하다.
    중앙 서버 없이도 고유 ID가 생성이 가능하게 된다.

🎈 단점

  • 정렬에 비효율적이다.
    랜덤 값 기반이기에, 인덱스 정렬이 비효율적이다.
    순서대로 들어온 값을 구별하려면 INSERT 날짜 등을 별도로 집어넣어야 한다.
  • 가독성이 낮다.
    사람이 읽거나 기억하기는 어려운 값이다.



✨ ULID

  • UUID의 단점을 보완한 식별자로 나왔다.
  • 128비트 길이의 고유 식별자지만, 시간 기반으로 정렬 가능하게 설계되었다.
  • ulid/spec에 정의된 표준을 따른다.
  • Crockford의 Base32(알파벳과 숫자 조합)로 인코딩되어 26자로 표현한다. (A-Z, 0-9)

🎈 생성 방법

  • 앞의 10자는 시간값으로 생성하고, 나머지 16자는 랜덤으로 생성한다.
    ex) 01HZYV4TYEBP64KM5Q0M8Z2WFE
  • 시간은 UNIX Epoch 시간(밀리초 단위)를 기반으로 생성한다고 한다.

🎈 장점

  • 정렬이 가능하다.
    앞의 10자가 시간관련 수치이므로 순서 정렬이 가능하다.
  • 가독성이 개선되었다.
    Base32 사용을 통해 문자열 길이가 짧아져, 사람이 읽기 쉬워졌다.
  • 전역 고유성이 보장된다.
    시간 + 랜덤 값의 조합이기에 고유성은 그대로 보장이 된다.

🎈 단점

  • 시간 의존성이 있다.
    밀리초 기준으로 동일한 시간인 경우 충돌 가능성이 조금은 높아진다.
    하지만, 애초에 UUID든 ULID든 충돌 가능성 자체가 매우 낮긴 하다.
  • 지원이 부족하다.
    UUID만큼의 광범위한 표준 지원은 부족할 수 있다.



✨ 사용하기

🎈 UUID

java.util.UUID 클래스를 import 하여 생성하면 된다.

// UUID 생성
UUID uuid = UUID.randomUUID();

👉 UUID: 3f2a7c1c-7bfb-4c35-a536-9e45d7ddef42


3이나 5버전에서는 입력값에 따른 UUID를 생성할 수 있다!
다만, 입력값이 동일하면 UUID도 동일해진다는 점;;;

UUID namedUuid = UUID.nameUUIDFromBytes(입력값.getBytes());

👉 Input: "example"
UUID: c3b18248-1a1d-3f42-96a4-fb6637b93934

👉 Input: "different-example"
UUID: 502a72c2-1d27-3a58-8ab2-4122e692d107

이렇게 다르게 설정할 수 있다.
예를 들어 중복이 없는 id를 기준으로 만드는 경우라면, 충돌없이 가능할 것이다.


그리고! 3번째 묶음에서 첫 번째 숫자가 해당 UUID의 버전이라고 하니 참고~!


🎈 ULID

지원 라이브러리를 사용해야한다.
Gradle 기준으로 implementation 'com.github.f4b6a3:ulid-creator:5.2.0'를 넣어준다!

// ULID 생성
String ulid = UlidCreator.getUlid();

자세히 보면 알겠지만, ULIDString 객체로 반환된다는 점!


하지만 여기서 시간을 임의로 설정하고 싶다거나, 동시에 들어오는 작업이 걱정된다면!

String monotonicUlid = UlidCreator.getMonotonicUlid(timestamp);

timestamp 부분에 밀리초로 된 값을 넣어주면 된다.
동시에 들어오는 작업을 처리할 때는 System.currentTimeMills()를 넣어주면 된다.

단조 증가 모드가 작동되어, 같은 타임스탬프 내에서도 ULID의 나머지 랜덤 부분이 증가하도록 처리된다고 한다.




따라서 온전한 랜덤성이 필요하고 이미 UUID를 사용하던 프로젝트라면 UUID로!
랜덤성은 어느정도 지키면서 정렬 가능성이 있고, 가독성이 필요하다면 ULID로!

0개의 댓글