Skip to content

GUID 버전 해설: v1–v7의 차이와 선택 가이드

2026-07-09

태그: Windows · GUID · 가이드 · QuickGUID


UUID 라이브러리를 열면 uuid1(), uuid3(), uuid4(), uuid5(), 그리고 점점 더 uuid7()이 보입니다. 사양은 여덟 개의 버전을 정의합니다. 실제로는 어떤 것을 써야 할까요?

짧은 대답: 거의 모든 것엔 v4, 데이터베이스 기본 키엔 v7, 같은 입력이 항상 같은 GUID를 내야 할 때는 v5. 이 글의 나머지는 그 이유를 설명합니다 — 바이트 구성, 각 버전이 존재하는 진짜 이유, 언어별 코드 요약표와 함께.

GUID가 처음이시라면 먼저 GUID란 무엇인가?에서 구조와 고유성의 기초를 잡으세요. 이 글은 그 기술적 동반자로, 각 버전을 더 깊이 파고듭니다.

GUID/UUID 버전 전경

각 버전은 같은 128비트를 채우는 서로 다른 레시피입니다. 버전 니블(세 번째 세그먼트의 첫 16진 숫자)이 어떤 레시피를 썼는지 알려줍니다.

버전생성 원천정렬 가능전형적 용도
v1시간 + MAC레거시 시스템 (프라이버시 위험)
v2DCE Security드묾, 전문 용도
v3MD5 네임스페이스 해시아니오사용 중단 (v5 사용)
v4무작위아니오일반 기본값
v5SHA-1 네임스페이스 해시아니오결정론적 ID
v6재정렬된 v1 시간v1의 직접 대체
v7밀리초 타임스탬프DB 기본 키
v8벤더 정의커스텀전문 용도

v1, v4, v5, v7이 실사용의 99%를 덮습니다. 하나씩 살펴봅시다.

v1: 시간과 MAC 주소

v1은 RFC 4122의 원조 레시피입니다. 세 가지를 128비트에 채워 넣습니다:

| time_low (32) | time_mid (16) | ver+time_hi (16) | var+clk_seq (16) | node/MAC (48) |
  • 60비트 타임스탬프 — 1582-10-15(그레고리력 채용일) 이후 100나노초 간격. 타임스탬프는 time_low, time_mid, time_hi에 걸쳐 쪼개집니다.
  • 14비트 클록 시퀀스 — 같은 클록 틱 안에서 생성된 두 GUID, 또는 시스템 시계가 뒤로 돌아간 경우를 구별하는 카운터.
  • 48비트 노드 — 네트워크 카드의 MAC 주소.

MAC 주소 문제

노드 필드는 하드웨어 지문입니다. 게시하는 모든 v1 GUID가 여러분 머신의 MAC 주소를 실어 나릅니다 — 그리고 IP 주소와 달리 MAC 주소는 전역적으로 고유하고 영속적이도록 설계되었습니다. 이건 진짜 프라이버시 유출입니다.

이론이 아닙니다. 연구자들은 파일 메타데이터에 박힌 v1 GUID를 읽어 문서를 만든 머신까지 역추적할 수 있음을 보였습니다. Microsoft 스스로 이게 시연된 뒤 Office 원격측정에서 v1 생성을 제거했습니다. 현대 OS도 같은 이유로 Wi-Fi 네트워크에 보여주는 MAC을 무작위화합니다.

결론: 새 코드에서는 v1을 피하세요. 레거시 시스템, COM 인터페이스, 일부 하드웨어 인접 도구에 살아남습니다 — 하지만 오늘날 직접 생성할 이유는 없습니다.

v2: DCE Security

v2는 사실상 결코 마주치지 못할 버전입니다. v1의 배치(타임스탬프 + MAC)를 가져와 그 위에 POSIX UID/GID — DCE(Distributed Computing Environment) 보안 모델의 로컬 사용자 및 그룹 식별자 — 를 올려, UUID가 고유성과 함께 접근 제어 정보도 실어 나르게 합니다.

v2는 레거시 엔터프라이즈 시스템의 DCE/RPC 인증과 ACL을 위해 존재합니다. 명시적으로 DCE Security를 사용하는 소프트웨어를 유지보수하지 않는 한, v2를 생성하거나 소비할 일은 없을 것입니다. 이 항목은 버전 목록을 완전하게 두고, 언젯가 그 니블에서 '2'가 보일 때 그 의미를 헤매지 않도록 하려는 것뿐입니다.

v3: 사용 중단된 이유

v3는 SHA-1 대신 MD5를 쓴다는 점만 빼면 v5와 동일합니다. MD5는 실용적인 충돌 공격이 있습니다 — 서로 다른 두 입력이 같은 해시를 내도록 만들 수 있습니다. 그게 적대적 환경에서 v3의 결정성 보증을 깹니다.

RFC 4122는 하위 호환을 위해 v3를 남겨뒀지만 v5가 대체했습니다. 오늘날 v3를 생성할 이유는 없습니다. 야생에서 v3를 만나면 레거시로 취급하세요.

v4: 무작위 기본값

v4는 사실상 모든 “GUID 생성” 호출 [guid]::NewGuid(), Guid.NewGuid(), crypto.randomUUID(), uuid.uuid4(), NEWID()이 돌려주는 것입니다. 128비트 중 122비트를 암호학적으로 강한 무작위로 채웁니다(나머지 6비트는 버전·변형 마커).

타임스탬프도, MAC도, 머신 상태도 없음 — 순수 무작위. 그래서 v4는 노출해도 안전하고, 병렬화는 자명하며, 현실적인 어떤 부하에도 충분한 충돌 내성을 가집니다. 충돌 수학의 전모(그리고 “10억 년”이라는 떠도는 주장이 생일 역설을 왜 틀리게 읽는지)는 허브 글을 보세요.

결론: 이것이 기본값입니다. 다른 걸 고를 구체적 이유가 없다면 v4를 고르세요.

v5: 결정론적 네임스페이스 ID

이건 대부분 개발자가 들어는 봤지만 실제로 써본 적 없는 버전입니다 — 그런데 진짜 쓸모 있는 문제를 해결합니다.

v5는 같은 입력에서 매번 같은 GUID를 도출하게 해 줍니다. 네임스페이스 UUID와 이름 문자열을 주면 결정론적 식별자를 돌려줍니다:

python
import uuid

# 같은 입력 → 같은 GUID, 매 실행, 모든 머신에서
dns_guid = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
url_guid = uuid.uuid5(uuid.NAMESPACE_URL, 'https://prunelab.net/blog/guid-explained')

print(dns_guid)  # 항상  cf14e0a3-... (같은 값)
print(dns_guid == uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com'))  # True

작동 방식

내부적으로 v5는 네임스페이스 UUID 바이트와 이름의 UTF-8 바이트를 이어 붙이고, 결과에 SHA-1을 돌리고, 앞 16바이트를 취한 뒤 버전(5)·변형 비트를 찍습니다. 네임스페이스 자체도 UUID입니다 — NAMESPACE_DNS, NAMESPACE_URL, NAMESPACE_OID, NAMESPACE_X500이 미리 정의되어 있지만, 어떤 UUID든 네임스페이스로 쓸 수 있습니다.

v5가 알맞은 도구일 때

  • 재현 가능한 테스트 픽스처 — 실행 간 안정적인 테스트 데이터 ID를 생성해서, 실패한 테스트가 항상 같은 엔티티를 가리키게 하기.
  • URL 유래 식별자 — 데이터베이스 조회 없이 URL을 GUID로 바꾸기. 같은 URL에 독립적으로 uuid5(NAMESPACE_URL, url)을 계산한 두 시스템은 항상 일치합니다.
  • 멱등 중복 제거 — 같은 레코드를 두 번 가져오면 GUID가 자기 자신과 충돌하므로, 키만으로 중복을 감지할 수 있습니다.

v4와의 핵심 대조: v4는 호출마다 고유값을 돌려줍니다(같은 입력이어도); v5는 같은 입력에 안정적인 값을 돌려줍니다. 둘은 교환 가능하지 않습니다.

결론: 입력 문자열에서 재현 가능하게 도출되는 GUID가 필요할 때마다 v5를 쓰세요.

v6: 아마 필요 없는 v1 수정판

v6은 v1과 정확히 같은 데이터 — 같은 타임스탬프, 같은 클록 시퀀스와 MAC — 를 담지만, 값이 자연스럽게 연대순으로 정렬되도록 타임스탬프 비트를 재배열합니다. v1에서는 타임스탬프가 어색하게 쪼개져(low, mid, high) 있지만, v6에서는 high-first로 저장되어 문자열의 사전식 정렬이 시간 정렬과 같습니다.

v6은 2024년에 v7과 함께 RFC 9562로 표준화되었습니다. 주로 v1의 클록·MAC 모델에 이미 묶인 시스템용 직접 마이그레이션 경로로 존재합니다: 기존 타임스탬프 로직은 그대로 두고 비트 배치만 다시 쓰면 됩니다.

새 시스템에서는 v7이 거의 항상 더 나은 선택입니다. v7은 밀리초 타임스탬프(v1/v6의 100ns 그레고리력 계산보다 단순)를 쓰고, MAC 주소를 박지 않으며, 더 깔끔한 무작위 채우기를 가집니다. v6은 “생성 모델을 바꾸지 않고 v1을 어떻게 현대화하나”에 답하고, v7은 “앞으로 뭘 써야 하느냐”에 답합니다.

v7: 데이터베이스를 위한 시간 정렬

v7은 v4 이후 가장 중요한 추가입니다. v4가 데이터베이스에서 만드는 문제를 해결합니다.

데이터베이스에서의 v4 문제

데이터베이스가 GUID를 기본 키로 쓰면, 그 키는 B+ 트리 인덱스를 떠받칩니다. B+ 트리는 삽입이 대략 정렬되어 있을 때 효율을 유지합니다 — 새 값이 오른쪽 끝에 가서 기존 페이지를 채웁니다. 무작위 v4 GUID는 전체 키 공간에 흩어지므로, 매 삽입마다 무작위 페이지를 칩니다. 큰 테이블에서는 이게 끊임없는 페이지 분할, 인덱스 파편화, 캐시 스래시, 쓰기 증폭을 일으킵니다. SQL Server의 해결책(NEWSEQUENTIALID())은 시퀀싱을 누출하는 독점적이고 이식성 없는 핵입니다.

v7의 구성

| unix_ts_ms (48) | ver (4) | rand_a (12) | var (2) | rand_b (62) |
  • 48비트 밀리초 Unix 타임스탬프 — 선행 필드라 값이 시간에 따라 증가합니다.
  • 4비트 버전7로 설정.
  • 12비트 rand_a — 무작위, 또는 같은 밀리초 안에서 순서를 매기는 단조 카운터로 선택적 사용.
  • 2비트 변형 — 표준 RFC 9562 마커.
  • 62비트 rand_b — 무작위.

타임스탬프가 앞에 오기 때문에, 연속으로 생성된 v7 GUID는 자연스럽게 정렬됩니다: 인덱스 삽입이 오른쪽 끝에 모이고, 페이지가 깔끔하게 채워지며, B+ 트리는 자동증가 정수처럼 행동합니다 — 그러면서도 중앙 조정자 없이 전역 고유합니다.

v7이 가치 없을 때

  • 인메모리 스토어(Redis, memcached) — B+ 트리 없음, 파편화 비용 없음. v4면 충분.
  • 작은 테이블 — 수백만 행 아래에서는 v4와 v7의 차이가 보이지 않습니다.
  • 비키 열 — GUID가 저장된 속성이지 인덱스 키가 아니면 순서는 무관합니다.
  • 불투명해야 하는 GUID — v7은 생성 밀리초를 누출하고, 보안에 민감한 맥락에서는 바람직하지 않을 수 있습니다.

결론: GUID가 진짜 데이터베이스의 클러스터형 기본 키면 v7을 쓰세요. 그 외엔 v4.

v8: 벤더 정의

v8은 비상구입니다: RFC 9562는 버전 니블이 8이고 변형 비트가 올바른 한 벤더가 자체 비트 배치를 정의하도록 허용합니다. 그 밖의 모든 것 — 타임스탬프 폭, 무작위 원천, 인코딩 — 은 구현자 마음입니다.

v8은 특정 이유로 커스텀 UUID 스키마를 설계한 시스템(예: 라우팅을 위해 샤드 ID나 노드 ID를 UUID에 구워 넣는 경우)에서만 볼 수 있습니다. 그런 시스템을 구축하지 않는다면 v8은 무관합니다; 구축 중이라면 규칙은 이 글의 어떤 것이 아니라 당신 자신의 스키마가 정의합니다.

실제로 어떤 버전을 써야 할까?

의사결정 가이드:

  • “일반 용도의 ID 생성?”v4. 90% 경우의 답입니다.
  • “DB 기본 키, 또는 시간 정렬 필요?”v7. 특히 큰 테이블의 클러스터형 인덱스에서.
  • “같은 입력에 매번 같은 GUID 필요?”v5. 문자열에서의 결정론적 매핑.
  • “v1을 기대하는 레거시 시스템 작업?”v1(호환성 유지), 단 v7 마이그레이션 계획.
  • “누가 v3를 쓰라고 했다?” → 안 됩니다. 대신 v5를(v3의 MD5는 망가졌습니다).
  • “가장 새 게 좋다.” → 그건 이유가 아닙니다. v7은 새롭고 동시에 진짜 문제(DB 정렬)를 해결합니다; v6은 새롭고 동시에 주로 v1 마이그레이션 보조입니다. 신규성이 아니라 유스케이스로 고르세요.

여전히 망설이면 v4를 쓰세요. 기본값이 있는 데는 이유가 있습니다.

버전과 언어별 GUID 생성

언어 / 도구v4(기본값)v5(결정론적)v7(정렬형)
PowerShell[guid]::NewGuid()
C# / .NETGuid.NewGuid()Guid.CreateVersion7() (.NET 9+)
Pythonuuid.uuid4()uuid.uuid5(uuid.NAMESPACE_URL, 'name')uuid.uuid7() (3.14 beta) / 라이브러리
JavaScriptcrypto.randomUUID()(npm uuid v11+)
Node.js (uuid 라이브러리)uuid.v4()uuid.v5('name', NAMESPACE)uuid.v7()
SQL ServerNEWID()
PostgreSQLgen_random_uuid()(확장)

몇 가지 메모: 표준 라이브러리에 v7 네이티브 지원은 2026년 현재 여전히 자리잡는 중입니다. Node.js uuid 패키지(v11+)와 .NET 9가 네이티브로 제공하고, Python은 3.14에서 uuid.uuid7()을 추가하며; 오래된 런타임은 라이브러리가 필요합니다. v5 지원은 거의 보편적인데, 엔트로피 원천 없이 순수 SHA-1 수학이기 때문입니다.

자주 묻는 질문

v7이 v4를 기본값에서 대체하나요?

아니오. v4가 일반 기본값으로 남습니다. v7은 GUID가 정렬된 기본 키일 때만 이깁니다 — 다른 대부분의 용도(세션 토큰, 요청 ID, 콘텐츠 해시, DB 밖의 모든 것)에서 v4의 무작위성은 단점이 아니며, v7의 선행 타임스탬프는 이득 없이 타이밍 정보만 누출할 것입니다.

v1은 여전히 안전하게 쓸 수 있나요?

아니오. v1은 네트워크 카드의 MAC 주소를 박습니다 — 영속적인 하드웨어 지문입니다. 연구자들이 문서에 박힌 GUID로 머신을 추적한 뒤, Microsoft 스스로 Office 원격측정에서 v1을 제거했습니다. 새 코드에서는 v1을 완전히 피하세요; 레거시 v1은 v7로의 마이그레이션을 계획하세요.

v3와 v5의 차이는?

둘 다 결정론적 네임스페이스 해시입니다(같은 입력 → 같은 GUID). v3는 MD5, v5는 SHA-1을 씁니다. MD5에는 실용적 충돌 공격이 있어 v3는 무결성 목적에서 망가진 것으로 간주되고 v5로 대체되었습니다. 오늘날 v3를 생성할 이유는 없습니다.

v4 GUID를 v7로 변환할 수 있나요?

아니오. 버전은 바꿔 끼울 수 있는 꼬리표가 아닙니다 — 각 버전은 완전히 다른 생성 로직을 씁니다. v4에는 추출할 타임스탬프가 없어서, “v7을 얻는” 유일한 방법은 새로 하나 생성하는 것입니다. v4 기본 키 열을 v7로 마이그레이션해야 한다면, 실제로는 새 열을 추가하고 다시 쓰는 것입니다.

.NET은 v7을 네이티브로 지원하나요?

네. Guid.CreateVersion7()이 .NET 9(2024년 11월 출시)에 추가되었습니다. .NET 8 이전이라면 NuGet 패키지 GenVaultUUIDv7을 쓰거나, 업그레이드하세요.

QuickGUID: v4·v7 생성, 모든 형식 변환

일상적인 GUID 작업에 QuickGUID는 전체 워크플로를 덮는 Windows 네이티브 도구 상자입니다:

  • 일괄 생성 v4 또는 v7, 한 번에 최대 1,000개
  • 10+ 형식 변환: 표준, 하이픈 없음, 중괄호, Base64, C 바이트 배열, DEFINE_GUID 매크로 — 모두 실시간 미리보기
  • 스마트 추출: 로그나 소스 코드를 붙여 넣으면 모든 GUID를 자동으로 찾아 변환
  • 실시간 데코레이터: 따옴표, 접두/접미사, 대/소문자 — 전역 토글하고 바로 복사

완전 무료, 100% 오프라인.

맺음말

버전 시스템이 있는 건, 서로 다른 일이 서로 다른 보증을 요구하기 때문입니다: v4는 추적 불가능한 무작위성을, v5는 재현성을, v7은 정렬성을 줍니다. 기본은 v4, 데이터베이스 키에서는 v7, 같은 입력에 같은 GUID가 필요할 땐 v5를 쓰세요.

GUID가 처음이신가요? GUID란 무엇인가?에서 구조, 하이픈 형식, 그리고 왜 128비트면 실전에서 충돌을 논제외로 만들기에 충분한지의 기초를 먼저 보세요.