UUID, 전 세계에서 고유한 식별자
UUID(Universally Unique Identifier)는 전 세계 어디서나 고유한 128비트 식별자입니다. 데이터베이스 Primary Key, API 토큰, 파일명 등 고유성이 필요한 모든 곳에 사용됩니다.
UUID를 올바르게 이해하면 분산 시스템, 데이터 동기화, 마이크로서비스 아키텍처를 더 잘 설계할 수 있습니다.
1부: UUID란?
UUID의 기본 형식
550e8400-e29b-41d4-a716-446655440000
형식: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
구성: 8-4-4-4-12 총 36글자 (하이픈 포함)
본질: 16바이트 = 128비트 데이터UUID vs AUTO_INCREMENT
AUTO_INCREMENT:
1, 2, 3, 4, 5...
장점: 작음, 순차적, 예측 가능
단점: 서버 의존, 충돌 위험 (분산 시스템에서)
UUID:
550e8400-e29b-41d4-a716-446655440000
장점: 고유성 보장, 서버 독립적
단점: 크기 큼, 랜덤2부: UUID 버전
UUID v1 (타임스탬프 기반)
구성:
- 60비트: 타임스탬프 (1970년 이후 마이크로초)
- 12비트: 클락 시퀀스
- 48비트: MAC 주소 (또는 랜덤)
장점: 시간 순서 정렬 가능
단점: MAC 주소 노출 (privacy 문제), 시스템 시간 의존
예: 550e8400-e29b-11d4-a716-446655440000UUID v4 (랜덤)
구성: 대부분이 난수로 생성됨
장점:
- 개인정보 노출 없음
- 생성 간단
- 충돌 확률 극히 낮음 (2^122)
단점:
- 시간 정렬 불가
- 약간 느림
예: 550e8400-e29b-41d4-a716-446655440000 (4는 v4를 의미)UUID v5 (SHA-1 기반)
구성:
- 네임스페이스 (예: DNS 도메인)
- 이름 (예: example.com)
- SHA-1 해시
장점:
- 결정적 (같은 이름 → 같은 UUID)
- 네임스페이스 분리
단점:
- 충돌 가능성 (매우 낮음)
예:
UUID v5 with DNS namespace of 'example.com':
6ba7b810-9dad-11d1-80b4-00c04fd430c8UUID v6, v7 (최신)
UUID v6: v1의 개선 (시간순 정렬, privacy 보호)
UUID v7: 최신 표준
- Unix 타임스탬프 + 랜덤
- 시간순 정렬 가능
- 현대적이고 안전
- 권장 버전
예: 015bf6f5-4c3e-7000-80b4-1234567890ab3부: UUID 생성
JavaScript에서 UUID 생성
UUID v4 (랜덤)
// 내장 기능 (Node.js 15.6+)
import { randomUUID } from 'crypto';
const uuid = randomUUID();
// 550e8400-e29b-41d4-a716-446655440000
// npm 라이브러리 (브라우저)
import { v4 as uuidv4 } from 'uuid';
const uuid = uuidv4();
// 간단한 구현
function generateUUIDv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}UUID v5 (결정적)
import { v5 as uuidv5 } from 'uuid';
const DNS_NAMESPACE = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
const uuid = uuidv5('example.com', DNS_NAMESPACE);
// 같은 이름 → 같은 UUIDPython에서 UUID 생성
import uuid
# UUID v4 (랜덤)
id = uuid.uuid4()
# 550e8400-e29b-41d4-a716-446655440000
# UUID v5 (결정적)
id = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')4부: 데이터베이스에서의 UUID
MySQL/PostgreSQL
-- UUID 컬럼
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100),
email VARCHAR(100) UNIQUE
);
-- 또는
CREATE TABLE users (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100) UNIQUE
);성능 최적화
문제: UUID는 크기가 크고 랜덤해서 인덱싱 성능 저하
ID 크기
INT 4바이트
BIGINT 8바이트
UUID 16바이트 (4배 큼!)
랜덤 → B-tree 인덱스 분산, 캐시 효율 저하해결책: ULID/UUID v7 사용
// ULID: UUID + 타임스탐프
// 시간순 정렬 가능 + UUID의 고유성
01ARZ3NDEKTSV4RRFFQ69G5FAV
// 또는 UUID v7 (최신 권장)
015bf6f5-4c3e-7000-80b4-1234567890ab
→ 앞 부분이 타임스탬프라 정렬 가능5부: UUID 사용 사례
1. API 응답 ID
GET /api/users/550e8400-e29b-41d4-a716-446655440000
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe"
}2. 파일 업로드
파일명: document.pdf
저장명: 550e8400-e29b-41d4-a716-446655440000.pdf
→ 파일명 충돌 방지, 추적 용이3. 분산 시스템
데이터베이스 1: ID 550e8400...
데이터베이스 2: ID 550e8401...
데이터베이스 3: ID 550e8402...
→ 서버 간 조율 없이도 고유한 ID 생성 가능4. 트랜잭션 추적
주문 트랜잭션 ID: 550e8400-e29b-41d4-a716-446655440000
→ 로그, 모니터링, 추적에 사용6부: UUID의 장단점
장점
- 고유성: 충돌 확률 극히 낮음
- 분산 친화적: 중앙 서버 불필요
- 보안: 예측 불가능
- 이동성: 데이터 마이그레이션 용이
단점
- 크기: 16바이트 (INT는 4바이트)
- 성능: 인덱싱 성능 저하
- 가독성: 사람이 읽기 어려움
- 데이터베이스: 저장 공간 증가
7부: UUID vs 대안
ULID (UUID의 대안)
형식: 01ARZ3NDEKTSV4RRFFQ69G5FAV (26글자)
크기: 128비트 (UUID와 동일)
장점:
- 타임스탬프 기반 (정렬 가능)
- 더 읽기 쉬움
- UUID 호환
예: 01ARZ3NDEKTSV4RRFFQ69G5FAVNano ID (경량)
형식: V1StGXR_Z5j3eK4Ur0V (21글자)
크기: 더 작음 (충돌 확률은 여전히 낮음)
장점:
- 매우 작음
- 빠른 생성
- URL 안전
예: V1StGXR_Z5j3eK4Ur0V자주 하는 실수
1. UUID v1 사용 (privacy 문제)
❌ UUID v1 (MAC 주소 노출)
✅ UUID v4 또는 v7
2. 대소문자 처리
❌ 대소문자 구분
✅ 항상 소문자로 통일
3. UUID 직렬화
❌ 바이너리로 저장 (호환성 문제)
✅ 문자열로 저장 (표준)
4. 성능 무시
❌ 대규모 시스템에서 UUID 무분별 사용
✅ ULID 또는 UUID v7로 정렬 가능하게
마무리
UUID는 현대 웹 개발의 필수 요소입니다. 올바른 버전 선택과 최적화를 통해 확장 가능한 시스템을 설계하세요.