우주적 스케일의 고유 ID 설계: UUID가 결국 정답인 이유
엔지니어링을 하다 보면 ‘고유성(Uniqueness)‘에 대해 병적으로 집착하게 되는 순간이 옵니다. 분산 시스템에서 동시성 이슈를 해결하기 위해 Snowflake ID를 도입하거나, 마이크로서비스 간의 추적을 위해 Trace ID를 설계할 때 말이죠. 그런데 최근 Hacker News에서 ‘전 우주적 스케일에서의 고유 ID(Cosmologically Unique IDs)’ 라는 아주 흥미로운 글이 화제가 되었습니다.
단순히 서버 클러스터 수준이 아니라, 인류가 은하계로 뻗어나가고 우주의 열적 죽음(Heat Death)이 올 때까지 모든 원자나 나노봇에 ID를 부여한다면 어떻게 해야 할까요? 오늘은 이 ‘쓸데없이 진지하고 깊이 있는’ 탐구 과정을 통해 분산 시스템 식별자의 본질을 들여다보겠습니다.
문제는 ‘충돌 확률’이 아니라 ‘물리학’이다
우리가 흔히 쓰는 UUID(v4)는 122비트의 랜덤성을 가집니다. 생일 역설(Birthday Paradox)에 따르면 약 $2^{61}$개의 ID를 생성했을 때 충돌이 발생할 확률이 50% 정도 됩니다. 지구상에서는 사실상 ‘0’에 수렴하는 확률이죠.
하지만 이 글의 저자 Jason Fantl은 여기서 멈추지 않습니다. 우주 전체를 컴퓨터(Computronium)로 가정하고, 우주의 수명이 다할 때까지 연산 가능한 최대 횟수($10^{120}$)를 기준으로 잡습니다. 이 경우 충돌을 피하려면 약 798비트 가 필요하다고 계산합니다. 만약 관측 가능한 우주의 모든 원자($10^{80}$)에 ID를 붙인다면 532비트 가 필요하고요.
여기까지는 “아, 그냥 비트 수 늘리면 되는구나” 싶습니다. 진짜 문제는 ‘랜덤이 아닌 확정적(Deterministic) ID’ 를 만들려고 할 때 발생합니다.
확정적 ID와 빛의 속도
랜덤 생성은 충돌 확률이 ‘0’은 아닙니다. 엔지니어로서 우리는 ‘확실성’을 원하죠. 그래서 중앙화된 카운터(Counter) 방식을 떠올립니다. 하지만 우주 스케일에서는 빛의 속도(Latency) 가 문제입니다. 안드로메다 은하에서 지구의 중앙 서버로 ID를 요청하고 응답받는 데 수백만 년이 걸릴 테니까요.
그래서 저자는 ‘Dewey’ 방식이라 불리는 계층적 ID 할당 방식을 제안합니다. 도서관 분류 기호처럼요.
- 위성 A: ID
1 - 위성 A가 만든 식민지 B: ID
1.5 - 식민지 B가 만든 로봇 C: ID
1.5.20
이 방식은 중앙 서버 없이도 로컬에서 즉시 ID 발급이 가능합니다(Accessibility). 하지만 치명적인 단점이 있습니다. 바로 ID 길이의 선형적 증가 입니다.
시뮬레이션 결과, 인류가 행성을 건너뛰며 확장할 때마다 ID 길이는 걷잡을 수 없이 길어집니다. 은하 하나를 채우는 데 필요한 홉(Hop) 수를 계산하고, 다시 은하 간 이동을 계산하면, ID 하나가 280MB 가 넘어가 버리는 사태가 발생합니다. 메모리에 ID 하나 올리기도 벅찬 수준이 되는 거죠.
엔지니어링의 딜레마: 공간 vs 조정(Coordination)
이 글에서 가장 인상 깊었던 부분은 ‘모든 확정적 ID 할당 방식은 최악의 경우 선형적($O(N)$)으로 증가한다’ 는 수학적 증명입니다.
- Counter: $log N$으로 증가하지만 중앙화 필수 (Latency 문제)
- Distributed (Dewey 등): Latency는 해결되지만, 경로(History)를 ID에 포함해야 하므로 ID 사이즈가 폭발
결국 우리는 ‘조정(Coordination) 비용’ 과 ‘저장 공간(Memory)’ 사이의 트레이드오프에서 벗어날 수 없다는 결론에 도달합니다.
Principal Engineer의 시선: 결국 정답은 Random이다
저자는 긴 탐험 끝에 “그냥 충분히 큰 랜덤 ID(Random Numbers)를 써라” 라고 결론 내립니다. 798비트 정도면 우주 멸망까지 모든 입자에 ID를 붙여도 안전하니까요.
현업에서 15년 넘게 구르며 느낀 점도 이와 비슷합니다. 주니어 시절엔 완벽하게 정렬되고(Sequential), 빈틈없고, 의미를 담은(Meaningful) ID 체계를 만들려고 애썼습니다. 하지만 시스템이 분산되고 스케일이 커질수록 그런 ‘예쁜’ ID는 병목(Bottleneck)이 됩니다.
- Snowflake ID (Twitter): 타임스탬프 + 머신ID + 시퀀스. 정렬 가능성과 분산 발급의 타협점입니다.
- ULID: UUID의 랜덤성에 정렬 가능성(Sortability)을 더했습니다.
이런 실용적인 솔루션들도 결국은 ‘약간의 조정(머신 ID 할당)‘이나 ‘약간의 충돌 가능성(랜덤)‘을 수용한 결과입니다. 우주적 스케일에서도 ‘확률적 보장(Probabilistic Guarantee)’ 이 ‘확정적 보장(Deterministic Guarantee)’ 보다 훨씬 효율적이라는 점은 시사하는 바가 큽니다.
Hacker News의 반응: 물리학과 철학의 향연
이 글에 달린 HN 댓글들은 기술 블로그의 백미입니다. 개발자들이 물리학자와 철학자로 변신하는 순간이죠.
- 상대성 이론: “충돌 확률 계산할 때도 빛의 속도를 고려해야지. 두 ID가 충돌하더라도 서로의 ‘빛 원뿔(Light Cone)’ 밖이라 만날 일이 없다면 충돌이 무슨 상관이야?”
- 양자역학: “양성자 붕괴(Proton Decay)까지 고려하면 $10^{56}$ 나노초밖에 안 남았어. 시간 범위를 너무 넓게 잡았음.”
- 실용주의: “Snowflake ID나 BSON ID 같은 거 쓰면 되지 않아? 타임스탬프만 잘 써도 비트 수 확 줄일 수 있는데.”
개인적으로는 “만약 다중 우주(Many Worlds) 해석이 맞다면, ID를 만들 때마다 새로운 우주가 분기되는 건가?” 라는 댓글이 가장 기억에 남습니다. (다행히 네임스페이스만 분리된다고 합니다.)
결론: 복잡함의 늪에 빠지지 말자
이 긴 여정의 교훈은 명확합니다.
- 완벽한 고유성을 위한 비용은 너무 비싸다. (280MB짜리 ID를 쓰고 싶진 않겠죠?)
- 확률(Probability)은 엔지니어의 가장 좋은 친구다. $10^{-30}$ 정도의 확률은 그냥 ‘0’으로 취급하고 넘어가는 게 정신 건강과 시스템 성능에 좋습니다.
- UUID는 생각보다 위대하다.
혹시 지금 “우리 서비스의 모든 로그에 순차적인 번호를 매겨야 해”라고 주장하는 기획자나 동료가 있다면, 이 글을 조용히 공유해 주시기 바랍니다. 우주 정복을 할 게 아니라면, 그냥 UUID v4 (혹은 DB 인덱싱을 위해 v7) 쓰세요.
참고 자료: