Files
2nd/10_Wiki/Topics/Coding/CS_Snowflake_ID_Generation.md
T
2026-05-09 21:08:02 +09:00

5.1 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
cs-snowflake-id-generation ID 생성 — UUID v7 / Snowflake / KSUID Coding draft B conceptual 2026-05-09 2026-05-09
cs
id
uuid
snowflake
vibe-coding
language applicable_to
TS
Backend
UUID v7
Snowflake
KSUID
ULID
NanoID
time-ordered ID
sortable

ID Generation

AUTO_INCREMENT = 한계 (분산 X). UUID v4 = 안 정렬. UUID v7 / Snowflake / KSUID = 시간 정렬 + 분산 OK + 인덱스 friendly.

📖 핵심 개념

  • 시간 정렬: 최신 INSERT 가 인덱스 끝 (페이지 수 적게).
  • 분산 생성: 중앙 service 없이 다중 노드.
  • 비밀: UUID v4 가 추측 불가 (URL 안전).
  • 길이: 16-26 byte.

💻 코드 패턴

UUID v7 (modern, 표준 RFC 9562)

import { v7 as uuidv7 } from 'uuid';
const id = uuidv7();
// "01918fec-d2c5-7000-8aab-1234abcd"
// 첫 48 bit = unix ms timestamp → 시간 정렬
-- Postgres 17+
SELECT uuidv7();

→ UUID v4 호환 + 시간 정렬. 2026 권장 디폴트.

Snowflake (Twitter)

64-bit:
  41 bit: timestamp (ms since epoch)
  10 bit: machine ID
  12 bit: sequence (per ms)

→ ms 당 4096 ID, 1024 machines.
class Snowflake {
  private seq = 0;
  private lastMs = 0;
  
  constructor(private machineId: number) {}
  
  next(): bigint {
    const now = Date.now();
    if (now === this.lastMs) {
      this.seq++;
      if (this.seq >= 4096) {
        // wait for next ms
        while (Date.now() === this.lastMs);
        return this.next();
      }
    } else {
      this.seq = 0;
    }
    this.lastMs = now;
    
    return (BigInt(now) << 22n) | (BigInt(this.machineId) << 12n) | BigInt(this.seq);
  }
}

→ 64-bit (BigInt). 빠르고 정렬. machine ID 충돌 위험.

KSUID (Segment)

import { KSUID } from 'ksuid';
const id = KSUID.randomSync().string;
// "0ujsswThIGTUYm2K8FjOOfXtY1K"
// 27 글자, 첫 4 byte = 32-bit unix seconds, 16 byte random

→ 27 char, sortable, URL-safe.

ULID

import { ulid } from 'ulid';
const id = ulid();
// "01ARZ3NDEKTSV4RRFFQ69G5FAV"
// 26 글자, 첫 10 = ms timestamp, 16 = random

→ KSUID 비슷, 더 짧음.

NanoID (random, secure)

import { nanoid } from 'nanoid';
const id = nanoid();          // 21 char
const short = nanoid(10);     // 10 char

→ URL-safe, 빠름. 단 시간 정렬 X.

CUID2

import { createId } from '@paralleldrive/cuid2';
const id = createId();

→ Collision-resistant + URL-safe + 시간 정렬.

Postgres column type

-- UUID
CREATE TABLE orders (
  id UUID PRIMARY KEY DEFAULT uuidv7()  -- PG 17+
);

-- 또는 string
CREATE TABLE orders (
  id TEXT PRIMARY KEY  -- KSUID / ULID / NanoID
);

-- BIGINT (Snowflake)
CREATE TABLE orders (
  id BIGINT PRIMARY KEY
);

인덱스 영향

v4 UUID: random → 매 INSERT 가 인덱스 random page → 큰 cache miss.
v7 UUID: 시간 정렬 → 항상 끝 page → 빠름.
AUTO_INCREMENT: 같지만 분산 X.

→ 큰 테이블 = v7 가 v4 보다 INSERT 5-10x 빠름.

보안

v4: 122-bit random → 추측 불가. URL 안전.
v7: 첫 48 bit = 시간 노출 → 정확 시각 추적 가능.
   (random 80-bit 도 함께 — collision 안전)

→ Public ID = v4 또는 짧은 nanoid. Internal = v7.

// 두 단계 — internal sortable + public random
{ id: 'uuid-v7', publicId: 'nanoid' }

분산 서비스 (Sonyflake / IdGen)

  • Snowflake 변형, machine ID 자동 할당.
  • Redis SETNX 또는 etcd.
class Sonyflake {
  // sub-second precision, larger machine bits
  // machine ID = MAC 주소 last 16 bit
}

Sequence database (PG / MySQL)

-- PG sequence
CREATE SEQUENCE orders_id_seq START 1;
SELECT nextval('orders_id_seq');

-- 단일 PG = bottleneck. 분산 X.

Encrypted ID (Hashids / Sqids)

import Sqids from 'sqids';
const sqids = new Sqids({ minLength: 8 });
const encoded = sqids.encode([userId]); // "yWBV0AVL"
const decoded = sqids.decode(encoded);  // [userId]

→ Auto-increment 숨기기. URL 짧음 + 의미 있는 short link.

🤔 의사결정 기준

상황 추천
새 프로젝트 디폴트 UUID v7
Public URL ID NanoID / KSUID
분산 서비스 (Twitter scale) Snowflake
Schema 호환 (UUID 컬럼) UUID v7
짧은 ID 필요 NanoID 10-12
정렬 + 짧음 KSUID / ULID

안티패턴

  • UUID v4 + 큰 테이블: 인덱스 성능 추락.
  • AUTO_INCREMENT 분산 환경: collision / sync.
  • Snowflake machine ID hard-code: 충돌. 자동 할당.
  • System clock backwards (NTP): ID 충돌. monotonic clock.
  • 추측 가능 ID public 노출 (1, 2, 3): enumeration 공격.
  • ID = 비즈니스 의미: ABC-2026-0001 같은 — 변경 어려움.
  • 여러 system 다른 형식: 통일 (모두 UUID 또는 모두 KSUID).

🤖 LLM 활용 힌트

  • 새 = UUID v7 (PG 17+ 또는 라이브러리).
  • Public URL = NanoID.
  • Distributed scale = Snowflake.
  • 시간 정렬 + URL-safe = KSUID / ULID.

🔗 관련 문서