데이터베이스에서 각 행을 구분하는 ID를 1, 2, 3으로 순서대로 매기다 보면, 서버를 분산하거나 데이터를 병합할 때 ID가 충돌하는 문제가 생긴다. 이런 상황에서 쓰는 게 UUID다.
UUID가 뭔가
UUID(Universally Unique Identifier)는 128비트(32자리 16진수) 길이의 식별자다. 전 세계 어디서 생성하든 중복될 확률이 사실상 0에 가깝도록 설계되었다.
형태550e8400-e29b-41d4-a716-446655440000
8자리-4자리-4자리-4자리-12자리, 총 36문자(하이픈 포함)
세 번째 블록의 첫 숫자가 버전을 나타낸다. 위 예시는 4로 시작하므로 UUID v4(랜덤 기반)다.
UUID 버전별 차이
| 버전 | 생성 방식 | 특징 |
|---|---|---|
| v1 | 타임스탬프 + MAC 주소 | 시간 기반이라 순서 보장, 단 MAC 주소 노출 위험 |
| v3 | 이름 + 네임스페이스 (MD5) | 같은 입력이면 항상 같은 UUID 생성 |
| v4 | 랜덤 난수 | 가장 널리 사용. 완전 무작위, 순서 없음 |
| v5 | 이름 + 네임스페이스 (SHA-1) | v3의 SHA-1 버전. 더 안전 |
| v7 | 타임스탬프 + 랜덤 | 시간순 정렬 가능. v1보다 개인정보 안전 |
실무에서 가장 많이 쓰이는 건 v4다. 별도의 입력값 없이 난수만으로 생성되기 때문에 구현이 간단하고, 어떤 환경에서든 바로 쓸 수 있다.
충돌 확률은 얼마나 되나
UUID v4의 랜덤 비트는 122비트다. 가능한 조합 수는 약 5.3 × 10³⁶개로, 이 숫자가 어느 정도인지 감이 안 올 수 있다.
- 초당 10억 개씩 생성해도 충돌이 발생하려면 약 85년이 걸린다.
- 10조 개의 UUID를 만들었을 때 충돌 확률은 약 0.000000006%다.
현실적으로 충돌을 걱정할 필요가 없는 수준이다. 단, 난수 생성기의 품질이 나쁘면(예: 시드값이 고정된 경우) 이론과 달리 충돌이 발생할 수 있으므로, 암호학적 난수 생성기를 쓰는 게 좋다.
UUID를 쓰는 이유
- 분산 시스템에서 ID 충돌 방지
- 여러 서버가 동시에 데이터를 생성할 때, 중앙 서버 없이 각자 UUID를 만들어도 겹치지 않는다.
- 보안
- 순차 ID(1, 2, 3...)는 다음 ID를 예측할 수 있어서 URL 조작 공격에 취약하다. UUID는 예측이 불가능하다.
- 데이터 병합
- 서로 다른 DB의 데이터를 합칠 때 ID가 겹치지 않아 병합이 수월하다.
UUID 생성 방법
코드에서 생성
// JavaScript
crypto.randomUUID()
// "3b241101-e2bb-4d7a-8613-e02b8b0a7e22"
# Python
import uuid
str(uuid.uuid4())
# "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
온라인에서 생성
테스트용으로 빠르게 하나 만들거나 대량으로 여러 개가 필요하면 UUID 생성기에서 버튼 하나로 생성할 수 있다. 하이픈 제거, 대문자 변환, 중괄호 포맷({...}), URN 형식(urn:uuid:...) 등 포맷을 선택할 수 있고, 대량 생성 후 텍스트 파일로 다운로드하는 것도 가능하다.
UUID 포맷 종류
| 포맷 | 예시 | 사용처 |
|---|---|---|
| 기본 | 550e8400-e29b-41d4-a716-446655440000 | 대부분의 시스템 |
| 하이픈 제거 | 550e8400e29b41d4a716446655440000 | URL, 파일명 |
| 중괄호 | {550e8400-e29b-41d4-a716-446655440000} | Windows GUID |
| URN | urn:uuid:550e8400-e29b-41d4-a716-446655440000 | XML, 표준 문서 |
ID 하나 때문에 데이터가 덮어씌워지는 건 복구하기 어려운 사고다. 순차 ID의 한계가 보이는 시점에 UUID로 전환하면, 분산 환경에서도 충돌 걱정 없이 확장할 수 있다.