🗓️ 2025. 01. 19
⏱️ 10

범용 고유 식별자, UUID 그리고 v7

범용적인데 유일하다니, 유일하면서 범용적이라니

개요

저는 요즘 코드를 작성할 때 객체나 작업(task)처럼 식별이 필요한 요소가 보이면 곧바로 UUID를 사용하곤 합니다.
고유성에 대한 고민과 추가 구현없이도 식별자를 편리하게 부여할 수 있기 때문인데요, 다른 분들께도 이 편의성을 알리고 싶어 간단한 글을 준비해봤습니다.

이 글에선 UUID의 개념과 사용 사례, 그리고 장단점 등을 다룹니다.

탄생 배경

컴퓨터 시스템에서 고유 식별자는 오래전부터 중요한 개념이었습니다.
네트워크 장비, 데이터베이스의 기본 키, 파일 이름을 비롯해 최근엔 IoT 기기에 이르기까지 각각의 개체를 고유한 값으로 나타낼 수 있어야 식별할 수 있기 때문입니다.

과거엔 식별자를 만들기 위해서 단순히 숫자를 증가시키는 auto increment 방식이나 특정 범위 내의 랜덤한 값을 사용하는 방법 등이 일반적이었습니다. 그런데 여기엔 몇 가지 문제가 있습니다.

  1. 동일한 시스템이 여러 환경에 있을 때, 각 환경에서 동일한 식별자가 만들어질 가능성이 높음.
  2. 한번에 여러 식별자를 발급해야 하는 경우 충돌 없이 빠르게 생성하기 어려움.
  3. 식별자를 발급해주는 중앙 시스템이 필요함

이같은 문제들을 해결하기 위해 탄생한 것이 바로 범용 고유 식별자, UUID(Universally unique identifier)입니다.

UUID는 국제 기구인 IETF(Internet Engineering Task Force)가 RFC 4122 표준으로 정의하면서 널리 사용되기 시작했습니다. 표준이라고 하면 마음이 좀 든든해지죠?

하지만 UUID라고 해서 중복될 확률이 절대 없는 것은 아닙니다. 절대란 건 원체 어려운 일이니까요.
그럼에도 안심하고 쓸 수 있습니다. 확률이 정말 정말 정말 낮거든요. UUID v4로 예를 들어볼게요.

UUID v4는 보통 122비트의 랜덤 값을 기반으로 생성됩니다. 122비트로 가능한 조합의 수는 2의 122승인데, 이 경우의 수는 80억 명이 매초마다 10억 개의 식별자를 생성해도 100조 년이 지나야 50% 확률로 중복이 발생하는 수준입니다. 이정도면 '절대'라고 할 순 없어도 '사실상' 중복이 없다고는 말할 수 있겠죠. 실제로 같은 이유로 다들 걱정없이 잘 사용하고 있습니다.

특징

형태

UUID는 128비트로 이뤄져 있습니다. 보통은 이 128비트를 32개의 16진수로 나타냅니다.
랜덤한 문자열 길이가 32씩이나 되면 한눈에 들어오지 않기 때문에 8-4-4-4-12 형태로 구분지어 표현합니다.

550e8400-e29b-41d4-a716-446655440000

하이픈(-)으로 구분 짓는 기준은 UUID 버전마다 조금씩 다릅니다.
UUID는 버전마다 고유성을 보장하는 방식이 서로 다르기 때문입니다.
같은 이유로 특정 버전이 어떤 버전보다 높거나 낮다고 해서 특별히 더 좋거나 나쁜 것도 아닙니다.

세 번째 구간의 첫 번째 숫자는 고정적으로 UUID 버전을 나타내는 데 사용됩니다.
예를 들어 위 UUID의 세 번째 구간은 41d4이므로 첫 번째 숫자가 나타내는 4가 UUID 버전입니다.

사용처

UUID는 등장 이후로 다양한 시스템에서 사용되고 있습니다.
특히 근래엔 클라우드 환경과 마이크로서비스가 일반화(?)되면서 독립적으로 고유 식별자를 생성할 수 있는 UUID를 선택하는 추세가 증가하고 있습니다. 게다가 대부분의 언어에서 UUID를 생성하는 라이브러리가 존재하기 때문에 애플리케이션 내에서 얼마든지 활용할 수 있습니다.

대표적인 예시는 다음과 같습니다.

  • Database의 Primary Key와 Index
  • 네트워크의 Request ID 등 트래킹 기능
  • 비동기 작업에서 Task ID 부여
  • 분산 시스템에서 리소스 식별

UUID의 종류

UUID는 RFC 9562을 기점으로 v7까지 표준으로 정의되어 총 7개의 버전이 있습니다.
그중에서 가장 널리 쓰이는 건 v4이고, 앞으로의 사용이 기대되는 건 v7입니다.

따라서 v4와 v7에 대해서만 소개드리겠습니다.

v4

UUID v4는 완전히 랜덤하게 생성되는 식별자로, 대부분의 사람들이 생각하는 UUID가 v4입니다.
예측 불가능하게 생성되므로 식별자가 공개되는 경우에도 보안 문제가 발생하지 않습니다.
따라서 보안이 중요한 시스템의 id나 API key, 비밀번호 초기화 토큰 등에 주로 이용됩니다.

가장 널리 쓰이는 만큼 대부분의 언어에서 자체적으로 지원하는 경우가 많습니다.
Python의 경우 내장된 uuid 모듈을, Node.js의 경우 crytpo 모듈을 사용할 수 있습니다.

# 파이썬
from uuid import uuid4

uuid_v4 = uuid4()

print(uuid_v4) # fbfea600-f515-4325-bfc9-8c2fc02c305c
import { v4 } from 'uuid'; // uuid 패키지를 설치해서 생성할 수도 있음
import { randomUUID } from 'node:crypto'

console.log(v4()); // fbfea600-f515-4325-bfc9-8c2fc02c305c
console.log(randomUUID()); // 95a4aba8-c21d-46c3-8a11-bbdd80cfa712

v7

UUID v7는 2024년 5월에 표준으로 정의되었습니다.
따끈따끈한 스펙인만큼 아직 프로그래밍 언어 자체적으로 v7을 지원하는 경우는 많지 않습니다.
Python에서는 uuid7이라는 패키지가 필요하고, Node.js에서도 uuid라는 패키지가 필요합니다.

v7은 v4처럼 랜덤하지만, 앞부분 48비트가 Unix timestamp 기반으로 만들어집니다.
그래서 시간순 정렬이 가능하다는 장점이 있지만, 같은 이유로 v4 만큼의 보안성이 있지는 않습니다.
해당 식별자가 만들어진 시각을 알아낼 수 있기 때문입니다.

import { v7 } from 'uuid';

const extractTimestamp = (uuid: string): Date => {
	const timestampHex = v.replace(/-/g, "").substring(0, 12);
	const timestampMs = parseInt(timestampHex, 16);

	return new Date(timestampMs);
};

const uuid = v7();

console.log(uuid); // 01947d5b-b044-7017-84d9-2b7b11b00438
console.log(extractTimestamp(uuid)); // 2025-01-19T06:59:08.484Z

하지만 식별자가 생성된 시각이 알려져도 딱히 상관없는 일반적인 시스템이라면 크게 신경쓰지 않아도 괜찮습니다.

최근엔 보안 이슈가 덜한 데다 정렬 가능한 uuid라는 특성덕분에 Database의 Index 컬럼에 곧잘 사용되고 있습니다. 앞으로의 활약이 기대되는 버전입니다.

번외

GUID

UUID를 알아보다 보면 GUID라는 용어도 발견할 수 있습니다.
GUID(Globally Unique Identifier)는 Microsoft에서 자체적으로 구현한 UUID로 보시면 됩니다.
(때문에 GUID를 국제 표준이라 말할 순 없습니다)

Microsoft가 만든 언어인 C#에서는 아예 GUID를 생성하는 메서드가 존재하기도 합니다.

Guid g = Guid.NewGuid();
Console.WriteLine(g); // 0f8fad5b-d9cb-469f-a165-70867728950e

UUID와의 차이점도 몇 가지 있는데, GUID는 중괄호 를 포함하거나 대문자로 표기하는 경우가 많습니다.
윈도우 환경에서 레지스트리를 좀 만져보셨다면 아마 익숙한 형태이실 거예요.

{550E8400-E29B-41D4-A716-446655440000}

UUID 표준을 공유하고 있긴 하지만 엄연히 Windows만의 스펙이기 때문에 GUID라는 워딩을 사용하는 건 권장하고 싶지 않습니다.

참고

돌아가기
© 2025 VERYCOSY.