Back

UUID v4는 정말로 중복되지 않을까? (로또보다 확률 낮은 수학의 비밀)

소프트웨어 개발에서 고유 식별자(Unique Identifier)를 생성하는 것은 매우 흔하면서도 중요한 문제입니다.

데이터베이스의 Primary Key, 세션 ID, 트랜잭션 추적 등 다양한 곳에서 우리는 무언가를 유일하게 식별해야 합니다.

이때 가장 널리 사용되는 표준이 바로 **UUID(Universally Unique Identifier)**입니다.

그중에서도 난수 기반의 UUID Version 4는 생성 방법이 간단하고 중앙 집중식 레지스트리가 필요 없어 분산 시스템에서 특히 사랑받고 있습니다.

하지만 개발자라면 한 번쯤 이런 의문을 가져보았을 것입니다.

"무작위로 생성하는데, 정말로 전 세계에서 중복이 발생하지 않을까?"

이 글에서는 UUID v4의 구조와 수학적 확률, 그리고 안전한 생성을 위한 기술적 요건에 대해 깊이 있게 다뤄보겠습니다.

1. UUID v4의 구조와 엔트로피

UUID는 128비트(16바이트)의 숫자로 구성됩니다.

이를 16진수 문자열로 표현하면 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx와 같은 36자(하이픈 포함) 형식이 됩니다.

UUID v4의 경우, 128비트 중 일부는 버전과 변형(variant) 정보를 담는 데 사용됩니다.

  • Version (4비트): UUID의 버전을 나타냅니다. v4의 경우 0100으로 고정됩니다.
  • Variant (2비트): 레이아웃 변형을 나타냅니다. RFC 4122 표준의 경우 10으로 시작합니다.

따라서 전체 128비트 중 고정된 6비트를 제외한 122비트가 순수한 무작위성(Entropy)을 가집니다.

2. 충돌 확률의 수학적 증명

122비트로 표현할 수 있는 경우의 수는 21222^{122}입니다.

21225.3×10362^{122} \approx 5.3 \times 10^{36}

정확히는 5,316,911,983,139,663,491,615,228,241,121,378,304개입니다.

이 숫자가 얼마나 큰지 체감하기 위해 몇 가지 비교를 해보겠습니다.

생일 문제 (Birthday Paradox)

확률론의 '생일 문제'를 적용하여 충돌 확률을 계산해 볼 수 있습니다.

nn개의 UUID를 생성했을 때 충돌이 발생할 확률 pp는 다음과 같이 근사할 수 있습니다.

p(n)1en22×2122p(n) \approx 1 - e^{-\frac{n^2}{2 \times 2^{122}}}

이 식에 따르면:

  • 10억 개의 UUID를 매초 생성한다고 가정했을 때,
  • 85년 동안 계속해서 생성해야 충돌 확률이 **50%**에 도달합니다.
  • 지구상의 모든 사람이 각자 6억 개의 UUID를 가지고 있어도 중복될 확률은 극히 희박합니다.

결론적으로, 우주적인 스케일이 아닌 이상 UUID v4의 충돌을 걱정하는 것은 기우에 가깝습니다. 로또 1등에 연속으로 수십 번 당첨될 확률보다도 낮기 때문입니다.

3. 중요한 전제 조건: CSPRNG

수학적 확률이 아무리 낮아도, 전제 조건이 지켜지지 않으면 무용지물입니다.

그 전제 조건이란 바로 **"예측 불가능한 난수"**를 사용해야 한다는 것입니다.

일반적인 프로그래밍 언어의 난수 생성 함수(예: C의 rand(), Java의 Random, JavaScript의 Math.random())는 **의사 난수 생성기(PRNG)**를 사용합니다.

이들은 시드(Seed) 값에 따라 결정적인 결과를 내놓으며, 주기가 짧거나 패턴이 드러날 수 있습니다.

만약 PRNG로 UUID를 생성한다면, 충돌 확률은 비약적으로 상승하며 보안 취약점이 됩니다.

암호학적으로 안전한 난수 생성기 (CSPRNG)

안전한 UUID를 생성하기 위해서는 반드시 **CSPRNG(Cryptographically Secure Pseudo-Random Number Generator)**를 사용해야 합니다.

CSPRNG는 다음과 같은 특성을 가집니다:

  1. 예측 불가능성: 이전의 난수들을 통해 다음 난수를 예측할 수 없어야 합니다.
  2. 비재현성: 내부 상태가 유출되지 않는 한 난수열을 재현할 수 없어야 합니다.

현대적인 운영체제와 브라우저는 이를 위해 하드웨어 노이즈(키보드 입력, 마우스 움직임, 디스크 I/O 등)를 엔트로피 소스로 사용합니다.

  • Web Browser: crypto.randomUUID() 또는 crypto.getRandomValues()
  • Node.js: crypto.randomUUID()
  • Python: uuid.uuid4() (내부적으로 os.urandom() 사용)

결론

UUID v4는 현대 컴퓨팅 환경에서 분산 시스템의 식별자 문제를 해결하는 가장 우아하고 강력한 솔루션 중 하나입니다.

21222^{122}이라는 압도적인 경우의 수는 우리에게 수학적 안도감을 줍니다.

단, 이 모든 것은 "올바른 도구(CSPRNG)를 사용했을 때" 성립한다는 점을 명심해야 합니다.

개발자로서 우리는 편리함 뒤에 숨겨진 이러한 원리를 이해하고, 적절한 보안 API를 활용하여 시스템의 신뢰성을 지켜야 할 것입니다.

TechUUIDSecurityCryptography

관련 도구 둘러보기

Pockit의 무료 개발자 도구를 사용해 보세요