-
GUID대신 ULID를 사용해 보자.프로그래밍 2024. 10. 23. 11:39
고유 식별자는 엔터티를 고유하고 일관되게 구별하기 위한 소프트웨어 개발에 필수적이다.
가장 일반적인 유형으로는 GUID, UUID 및 ULID가 있다.
이 문서에서는 GUID, UUID 및 ULID에 대한 차이점과 ULID를 추천하는 이유에 대해 설명한다.
주된 이유는 ULID는 난수 임에도 시간 정렬이 가능하다는 것이다.
GUID(Globally Unique Identifier, 전역 고유 식별자)
개요
- GUID는 Globally Unique Identifier의 약자.
- 컴퓨터 시스템의 정보를 고유하게 식별하는 데 사용되는 128비트 숫자.
- Microsoft 기술에서 일반적으로 사용.
판
- 표준 형식: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- 본보기: 123e4567-e89b-12d3-a456-426614174000
특성
- 임의성: 주로 난수 또는 의사 난수를 기반으로 함.
- 고유성: 매우 독특하지만 시간 순서가 지정되지 않음.
- 가독성: 사람이 읽을 수 없음.
사용 사례
- 데이터베이스 키.
- 분산 시스템의 식별자.
- .NET 응용 프로그램.
장점
- 매우 높은 고유성.
- 다양한 프로그래밍 언어 및 플랫폼에서 널리 지원.
단점
- 연대순이 없음.
- 크기가 더 커서 스토리지 및 인덱싱 성능에 영향을 줄 수 있음.
ULID(Universally Unique Lexicographicically Sortable Identifier, 보편적으로 고유하게 사전적으로 정렬할 수 있는 식별자)
개요
- ULID는 Universally Unique Lexicographically Sortable Identifier의 약자.
- 정렬 가능하고 고유하게 설계.
판
- 표준 형식: 01AN4Z07BY79KA1307SR9X4MV3
- 본보기: 01ARZ3NDEKTSV4RRFFQ69G5FAV
특성
- 시간 기반: 48비트 타임스탬프와 80비트 임의 구성 요소를 인코딩.
- 정렬 가능성: 사전 편찬으로 정렬할 수 있으며, 이는 생성 시간을 기준으로 정렬할 수 있음을 의미.
- 가독성: GUID 및 UUID에 비해 사람이 더 쉽게 읽을 수 있음.
사용 사례
- 이벤트 로그.
- 순차적 정렬이 필요한 데이터베이스.
- 정렬 가능한 고유 식별자가 필요한 분산 시스템.
장점
- 사전 순으로 정렬 가능.
- 시간 기반 접두사.
- 더 나은 가독성.
단점
- GUID 및 UUID보다 최신이며 널리 지원되지 않습니다.
- 자동 증가 정수와 같은 더 간단한 ID에 비해 큽니다.
GUID는 특히 Sql Server에서 채번하는 GUID는 그 형태에서 그룹요소가 발생한다.
따라서, DB 마이그레이션이 발생하는 경우 KEY 정렬을 수행할 때 매우 복잡한 상황이 발생할 수 있고, 그룹요소가 깨질 경우 마이그레이션이 불가능 하게 된다. 또한 정렬 성능도 그 크기에 의해 매우 떨어지게 된다.
필자가 ULID를 추천하는 이유는 해당 ID가 시간을 기반으로 생성하는 정렬 가능한 ID 이기 때문이다.
만약 ULID를 사용하기로 하였다면 DB 채번이 아닌 Application 채번이 될 것 이기에 기존 DB 채번에 익숙하다면 혼란할 수 있지만, 정수 KEY가 아닌 ULID를 사용한다면, 특히 멀티 테넌트의 경우에는 효과적으로 DB KEY를 다루기가 편해질 수 있다.
닷넷에는 NUlid가 있다.
RobThree/NUlid: .Net ULID implementation
GitHub - RobThree/NUlid: .Net ULID implementation
.Net ULID implementation. Contribute to RobThree/NUlid development by creating an account on GitHub.
github.com
NUld를 사용할 경우 loop에서 채번을 하면 시간순 정렬이 되지 않는 경우가 있다.
이러한 경우를 위해 RNG를 사용하게 되는데 코드는 아래와 같다.
public class UlidGenerator { private static Lazy<UlidGenerator> _instance = new Lazy<UlidGenerator>(() => new UlidGenerator()); public static UlidGenerator Instance => _instance.Value; private UlidGenerator(){} private MonotonicUlidRng _rng = new MonotonicUlidRng(); public Ulid Generate() => Ulid.NewUlid(_rng); public string GenerateString() => Ulid.NewUlid(_rng).ToString(); public Ulid Generate(DateTimeOffset offset) => Ulid.NewUlid(offset); }
위 코드에서는 기본적으로 모두 RNG를 사용하게 하였다.
RNG는 동일한 밀리초 내에 ULID를 생성할 때 정렬 순서와 관련하여 몇 가지 보장을 제공할 수 있는 기능으로 Loop에서 채번을 해야 한다면 위 코드를 참고하면 되겠다.
만약, GUID 이슈로 고통받고 있다면 ULID를 사용해 보자.
도움이 되기를 바라며...
'프로그래밍' 카테고리의 다른 글
시계열 데이터를 전송하는 방법 (0) 2024.10.25 사용자 Session을 처리하는 방법 (1) 2024.10.24 AntdUI 소개 (1) 2024.10.22 리소스 관리 전략 (0) 2024.10.22 Json을 통한 Kafka ObjectId에 대한 처리 (1) 2024.10.21