← 블로그 목록

UUID/GUID 완벽 가이드: 고유 식별자 생성과 활용

UUID의 버전별 특징, 생성 방법, 데이터베이스 설계까지. 전역 고유 식별자를 완벽히 이해하세요.

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-446655440000

UUID 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-00c04fd430c8

UUID v6, v7 (최신)

UUID v6: v1의 개선 (시간순 정렬, privacy 보호)

UUID v7: 최신 표준
- Unix 타임스탬프 + 랜덤
- 시간순 정렬 가능
- 현대적이고 안전
- 권장 버전

예: 015bf6f5-4c3e-7000-80b4-1234567890ab

3부: 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);
// 같은 이름 → 같은 UUID

Python에서 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 호환

예: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Nano 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는 현대 웹 개발의 필수 요소입니다. 올바른 버전 선택과 최적화를 통해 확장 가능한 시스템을 설계하세요.