카테고리 없음

[cs] Spring에서 ULID적용하기

엄지성 2024. 10. 14. 01:06

ULID란?

Universally Unique Lexicographically Sortable Identifier의 약자로 대소문자를 구분하지 않는 시간을 나타내는 10글자와 16글자의 임의의 값으로 구성한다.

 

ULID

ULID는 앞에 타임스태프가 있듯이 생성 순서를 밀리세컨 단위로 기록할 수 있어 순서대로 정렬이 가능하다. 하지만 만약 밀리세컨까지 동일하게 생성된다는 가정을 한다면, 순서는 랜덤으로 배정된다.

 

또한, ULID는 Crockford’s Base32 기반으로 만들어져 (I, L, O, U)는 들어가지 않는다. 제외된 이유는 이것들은 대소문자에 의해 사람들에게 헷갈릴 수도 있기 때문에라고 한다.

 

논리대로라면 1ms에 2^80개를 만들 수 있다. 그러면 충돌할 가능성이 존재할까?

https://medium.com/zendesk-engineering/how-probable-are-collisions-with-ulids-monotonic-option-d604d3ed2de


Spring에 적용하는 방법

적용하는 방법은 두가지가 존재한다. 한 가지는 https://github.com/ulid/spec#monotonicity 에 사람들이 다양한 언어를 위해 만들어놓은 것을 사용하는 것 하나와 다른 방법은 직접 ulid를 구현하는 것이다. 

 

이번에는 ULIDGenerater를 사용하여 ULID를 적용하는 방법을 적어볼 것 이다.


ULIDGenerater

 

이건 실제로 적용한 ULID를 생성하는 로직이다. 로직을 보면 현재 시간을 밀리초 단위로 가져와서, 16바이트 배열에 현재 시간랜덤 long 값Big Endian(높은 바이트부터 낮은 바이트 순서로 데이터를 저장하고 읽는 방식) 순서로 저장한 후 그 배열을 반환하는 로직입니다.

 

이런 식으로 따로 ULIDGenerater를 만들어 사용할 수 있다. 이것을 이제 Entity에 적용해야 id에 ULID가 정상적으로 값이 들어간다.

 

 

이렇게 Entity에서 id에 이런 식으로 적용하면 된다.

  • GenratedValue: ulidGenerator라는 생성기로 생성
  • GenericGenerator: strategy는 ULID를 생성하는 클래스의 경로를 표시하고 name으로 생성기의 이름을 지정
  • Column: 취향것(nullable, unique), columnDefinition은 데이터베이스에서 어떤 타입을 사용할지 지정

마무리

프로젝트에서 UUID를 사용하기를 고민중이라면 ULID도 한번쯤 고민해보면 좋을 것 같다. UUID도 랜덤한 고유한 식별자이지만 순서가 존재하지 않고 완전한 랜덤이라 정렬이 불가능하다는 단점이 존재하기 때문이다. 정렬이 불가능하다는 것은 데이터베이스 조회나 삭제, 수정 등에서도 좋지 않는 성능을 보일 수 있기 떄문이다. 그래서 정렬이 가능한 ULID를 사용하는 것이 데이터베이스 성능에서도 UUID보다 이점을 보이는 경우가 있다. 이점을 유의해서 사용을 고려해보면 좋을 것 같다.