UUID v1 생성기

Generate time-based UUID v1 with embedded timestamp

포맷

개수:
Note:UUID v1은 호스트 MAC 주소와 생성 타임스탬프를 내장하여 대부분의 현대 애플리케이션에서 프라이버시 우려를 제기합니다. 새 프로젝트에서는 시간 순서 디코딩 가능 식별자가 특별히 필요하지 않는 한 UUID v4가 권장됩니다.

UUID v1이란 무엇인가요?

UUID v1은 RFC 4122(2005)에서 표준화된 원래 UUID 버전입니다. 고정밀 타임스탬프와 생성 호스트의 MAC 주소, 하위 타임스탬프 해상도를 처리하는 짧은 클럭 시퀀스를 결합하여 고유 식별자를 생성합니다.

타임스탬프가 내장되어 있으므로 동일한 호스트의 UUID v1 값은 시간이 지남에 따라 단조 증가합니다——자연스럽게 순서가 있습니다. 이는 각 노드가 조율 없이 독립적으로 UUID를 생성할 수 있는 분산 시스템을 위해 설계되었습니다.

오늘날 UUID v1은 UUID v7(정렬 가능, MAC 누출 없음)과 UUID v4(완전히 무작위, 비공개)로 크게 대체되었습니다. Apache Cassandra 및 레거시 분산 데이터베이스 같은 시스템에서 계속 사용됩니다.

UUID v1 구조 분석

550e8400-e29b-11d4-a716-446655440000과 같은 UUID v1 문자열은 6개의 서로 다른 필드를 인코딩합니다:

필드크기설명
time_low32 bits60비트 그레고리안 타임스탬프의 32비트 하위 필드(1582년 10월 15일부터 100나노초 간격)
time_mid16 bits60비트 타임스탬프의 중간 16비트 필드
time_hi_and_version16 bits60비트 타임스탬프의 상위 12비트와 4비트 버전 번호(항상 <code>1</code>)
clock_seq_hi_res8 bits2비트 RFC 4122 변형 마커와 결합된 6비트 클럭 시퀀스 상위 필드
clock_seq_low8 bits클럭 시퀀스의 하위 8비트
node48 bits48비트 노드 식별자——일반적으로 생성 네트워크 인터페이스의 MAC 주소, 또는 MAC을 사용할 수 없는 경우 무작위 48비트 값

클럭 시퀀스 필드(clock_seq_hi_res + clock_seq_low)는 14비트 카운터입니다. 시스템 클럭이 뒤로 이동(예: NTP 조정)하거나 마지막으로 알려진 타임스탬프를 저장하지 않고 시스템이 재시작될 때 증가합니다.

UUID v1 타임스탬프 디코딩

60비트 타임스탬프는 UUID의 세 필드에 흩어져 있습니다. 생성 시간을 재구성하려면:

  1. time_low(바이트 0-3), time_mid(바이트 4-5), time_hi(바이트 6-7, 버전 니블 제외)를 추출
  2. 재조립: (time_hi &lt;&lt; 48) | (time_mid &lt;&lt; 32) | time_low
  3. 결과는 1582년 10월 15일(그레고리안 달력 에포크)부터의 100나노초 간격의 60비트 카운트
  4. 그레고리안에서 Unix 오프셋 빼기: 122,192,928,000,000,000(1582년 10월 15일부터 1970년 1월 1일까지의 100ns 간격)
  5. 10,000으로 나누어 100나노초 간격을 밀리초로 변환
  6. 결과를 Unix 밀리초 타임스탬프로 Date 객체 구성
  7. 사람이 읽을 수 있도록 ISO 8601로 포맷

타임스탬프 정밀도는 100나노초——UUID v7의 밀리초 정밀도보다 훨씬 세밀합니다. 그러나 실제로 대부분의 OS는 밀리초 미만 클럭 해상도를 제공하지 않아 하위 비트가 종종 0이거나 합성입니다.

프라이버시 우려

UUID v1의 가장 중요한 단점은 노드 필드에 생성 호스트의 MAC 주소를 내장한다는 것입니다. 즉 모든 UUID v1은 생성한 머신의 영구적이고 전 세계적으로 고유한 지문을 갖습니다.

UUID v1을 얻은 공격자는 (1) ID가 생성된 대략적인 시간, (2) 생성 호스트의 MAC 주소, (3) 여러 UUID를 분석하여 ID 생성 속도를 결정할 수 있습니다.

이런 이유로 이 정보를 공개하는 것이 편하지 않다면 UUID v1을 공개 식별자(URL이나 API 응답 등)로 절대 사용해서는 안 됩니다.

UUID v1이 여전히 적절한 경우

Apache Cassandra 기본 키
Cassandra는 UUID v1(TimeUUID 타입을 통해)을 핵심 설계 패턴으로 사용합니다. 타임스탬프 순서가 Cassandra의 스토리지 모델에 자연스럽게 매핑되어 효율적인 시간 범위 쿼리를 가능하게 합니다.
레거시 분산 시스템
UUID v7이 존재하기 전(2024년 이전)에 구축되어 타임스탬프 순서 UUID에 의존하고 새 형식으로 쉽게 마이그레이션할 수 없는 시스템.
감사 및 이벤트 로그
생성 호스트 신원이 알려져 있고 신뢰할 수 있을 때 MAC 주소 내장이 감사 이벤트에 추가적인 추적 가능성을 제공할 수 있습니다.
내부 식별자
제어된 내부 시스템 외부에 절대 노출되지 않는 ID로, MAC 주소 공개가 우려 사항이 아닌 경우.
별도 타임스탬프 열 없는 시간 범위 쿼리
내장된 타임스탬프를 디코딩하여 생성 시간으로 행을 필터링하고 결합된 ID 및 타임스탬프로 사용할 수 있습니다.
이전 UUID v1 생성기와의 상호 운용
UUID v1 값을 생성하는 외부 시스템에서 수신하거나 처리할 때 표시나 분석을 위해 내장된 타임스탬프를 디코딩합니다.

UUID v1 대 UUID v7

UUID v7은 시간 순서 식별자를 위한 UUID v1의 현대적 후계자입니다. 직접 비교:

측면UUID v1UUID v7
에포크 / 시간 기준그레고리안 에포크(1582년 10월 15일)Unix 에포크(1970년 1월 1일)
정밀도100나노초1밀리초
노드 식별자MAC 주소(호스트 신원 누출)무작위(비공개)
프라이버시MAC 주소와 생성 타임스탬프 누출호스트 정보 내장 없음
DB 인덱스 성능양호——호스트별 순차탁월——모든 생성기에 걸쳐 k-sortable
표준RFC 4122(2005)RFC 9562(2024)

새 프로젝트에서 UUID v7은 UUID v1의 권장 대체품입니다. 호스트 MAC 주소 내장의 프라이버시 함의 없이 유사한 시간 순서 보장을 제공합니다.

코드 예제

UUID v1 생성은 브라우저나 Node.js에서 네이티브로 사용 불가능합니다. uuid npm 패키지를 사용하세요:

JavaScript (browser)
// Generate a UUID v1 using the Web Crypto API
function generateUuidV1() {
  const buf = new Uint8Array(16)
  crypto.getRandomValues(buf)

  const ms = BigInt(Date.now())
  const gregorianOffset = 122192928000000000n
  const t = ms * 10000n + gregorianOffset

  const tLow   = Number(t & 0xFFFFFFFFn)
  const tMid   = Number((t >> 32n) & 0xFFFFn)
  const tHiVer = Number((t >> 48n) & 0x0FFFn) | 0x1000  // version 1

  const clockSeq    = (buf[8] & 0x3F) | 0x80  // variant 10xxxxxx
  const clockSeqLow = buf[9]

  const hex  = (n, pad) => n.toString(16).padStart(pad, '0')
  const node = [...buf.slice(10)].map(b => b.toString(16).padStart(2, '0')).join('')

  return `${hex(tLow,8)}-${hex(tMid,4)}-${hex(tHiVer,4)}-${hex(clockSeq,2)}${hex(clockSeqLow,2)}-${node}`
}

// Extract the embedded timestamp from a UUID v1
function extractTimestamp(uuid) {
  const parts = uuid.split('-')
  const tHex = parts[2].slice(1) + parts[1] + parts[0]
  const t = BigInt('0x' + tHex)
  const ms = (t - 122192928000000000n) / 10000n
  return new Date(Number(ms))
}

const id = generateUuidV1()
console.log(id)                      // e.g. "1eb5e8b0-6b4d-11ee-9c45-a1f2b3c4d5e6"
console.log(extractTimestamp(id))    // e.g. 2023-10-15T12:34:56.789Z
Python
import uuid
from datetime import datetime, timezone

# Generate UUID v1 (uses MAC address by default)
uid = uuid.uuid1()
print(uid)

# Extract embedded timestamp
# uuid.time is 100-ns intervals since Oct 15, 1582
GREGORIAN_OFFSET = 122192928000000000  # 100-ns intervals
ts_100ns = uid.time
ts_ms = (ts_100ns - GREGORIAN_OFFSET) // 10000
dt = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc)
print(dt.isoformat())   # e.g. "2023-10-15T12:34:56.789000+00:00"
Go
package main

import (
    "fmt"
    "time"

    "github.com/google/uuid"  // go get github.com/google/uuid
)

func main() {
    id, _ := uuid.NewUUID()  // UUID v1
    fmt.Println(id)

    // Extract timestamp from UUID v1
    // uuid.Time is 100-ns ticks since Oct 15, 1582
    t := id.Time()
    sec  := int64(t)/1e7 - 12219292800  // convert to Unix seconds
    nsec := (int64(t) % 1e7) * 100
    ts   := time.Unix(sec, nsec).UTC()
    fmt.Println(ts.Format(time.RFC3339Nano))
}

자주 묻는 질문

UUID v1에서 타임스탬프를 디코딩할 수 있나요?
예. 생성 타임스탬프는 UUID v1 문자열에서 완전히 복구할 수 있습니다. 이 도구가 정확히 그것을 합니다——UUID v1을 붙여넣으면 디코딩된 UTC 타임스탬프를 표시합니다.
MAC 주소가 항상 UUID v1에 존재하나요?
반드시 그런 것은 아닙니다. RFC 4122는 네트워크 인터페이스가 없거나 프라이버시가 원하는 경우 MAC 주소 대신 무작위로 생성된 48비트 값을 대체할 수 있도록 허용합니다. 브라우저는 MAC 주소를 노출하지 않으므로 브라우저 생성 UUID v1 값은 항상 무작위 노드 값을 사용합니다.
UUID v1 타임스탬프가 1582년을 에포크로 사용하는 이유는?
그레고리안 달력 개혁은 1582년 10월 15일에 발효되었습니다. UUID v1 타임스탬프는 Unix 에포크(1970년) 이전의 안정적인 범용 참조점을 제공하기 위해 이 날짜를 기준으로 정의되었습니다.
UUID v1 대 UUID v7——언제 여전히 v1을 사용해야 하나요?
오늘날 UUID v1을 사용하는 주요 이유는 기존 시스템과의 호환성입니다——특히 TimeUUID 타입으로 v1을 사용하는 Apache Cassandra. 모든 새 시스템에서 UUID v7이 엄격히 더 낫습니다.
UUID v1 값이 충돌할 수 있나요?
이론적으로 동일한 MAC 주소가 같은 100나노초 간격 내에서 두 UUID를 생성하고 클럭 시퀀스가 동일하면 두 UUID v1 값이 충돌할 수 있습니다. 클럭 시퀀스는 정확히 이를 방지하기 위해 존재합니다——빠른 연속 호출 시 증가합니다. 실제로 올바르게 구현된 시스템에서 UUID v1 충돌은 매우 드뭅니다.