CUID v1 생성기
Generate collision-resistant unique IDs (CUID v1)
생성된 CUID
CUID v1은 레거시 형식입니다. 새 프로젝트에는 CUID2를 사용하세요.
CUID란 무엇인가요?
CUID(충돌 저항 고유 식별자)는 중앙 코디네이터 없이 분산 시스템에서 잘 작동하는 고유 ID를 생성하는 오픈소스 알고리즘입니다. 단순한 UUID와 달리 CUID는 수평 확장 가능하게 설계되었습니다 — 여러 서버 또는 브라우저 탭이 각자 독립적으로 ID를 생성할 수 있으며 충돌 위험이 최소화됩니다.
모든 CUID는 소문자 c로 시작하여 형식을 한눈에 알아볼 수 있습니다. 나머지 문자는 모두 소문자 영숫자(base36)이므로 CUID는 URL 안전하며 추가 인코딩 없이 URL 경로 세그먼트나 데이터베이스 기본 키로 직접 사용할 수 있습니다.
원래 CUID 사양(v1)은 Eric Elliott이 만들었으며 npm 패키지 cuid를 통해 대중화되었습니다. 이제 암호화 보안을 제공하는 CUID v2로 대체되었습니다. 이 페이지와 위의 생성기는 프로덕션 코드베이스에서 여전히 널리 사용되는 클래식 형식인 CUID v1 ID를 생성합니다.
CUID 구조
CUID v1은 약 25자 길이이며 서로 다른 유형의 엔트로피를 가진 5개의 연결 세그먼트로 구성됩니다:
세그먼트는 단순히 연결됩니다 — 구분자가 없습니다. 총 길이는 현재 타임스탬프 값에 따라 약간 다르지만 약 25자를 유지합니다.
CUID가 충돌을 방지하는 방법
충돌 저항은 독립적인 엔트로피 소스를 중첩함으로써 달성됩니다. 최악의 시나리오(많은 머신에서 밀리초당 수천 개의 ID 생성)에서도 두 개의 동일한 ID의 확률이 극히 낮게 유지됩니다.
CUID vs UUID v4
CUID와 UUID v4는 모두 클라이언트 측 ID 생성에 널리 사용됩니다. 동일한 문제에 다른 접근 방식을 취합니다:
| 특징 | CUID v1 | UUID v4 |
|---|---|---|
| 형식 | c + base36 (~25자) | 16진수 그룹 (하이픈 포함 36자) |
| 정렬 가능 | 대략적으로 (타임스탬프 접두사) | 아니오 |
| URL 안전 | 예 (영숫자만) | 대부분 (하이픈은 URL에서 유효) |
| 충돌 저항 | 높음 — 타임스탬프 + 카운터 + 지문 + 무작위 | 높음 — 122비트 무작위 |
| 예측 가능성 | 부분적 (타임스탬프 보임) | 없음 (순수 무작위) |
| 길이 | ~25자 | 36자 |
| 조정 필요 | 아니오 | 아니오 |
UUID v4는 타이밍 정보를 드러내지 않기 때문에 보안에 민감한 시나리오에서 더 안전한 선택입니다. CUID는 대략 정렬 가능하고 더 짧으며 하이픈이 없는 ID가 필요할 때 유리합니다 — 레코드가 언제 생성되었는지 빠르게 식별하고 싶은 URL, 파일명, 로그에서 편리합니다.
CUID v1 vs CUID2
CUID 사양은 상당히 개정되었습니다. 차이점을 이해하면 프로젝트에 맞는 버전을 선택하는 데 도움이 됩니다:
| 측면 | CUID v1 | CUID v2 |
|---|---|---|
| 알고리즘 | 결정론적 컴포넌트 | SHA-3 기반, 완전히 불투명 |
| 암호화 | 아니오 | 예 |
| 타임스탬프 가시성 | 예 | 아니오 |
| 형식 | "c"로 시작 | "c"로 시작 (설정 가능) |
| npm 패키지 | @paralleldrive/cuid (더 이상 사용 안 함) | @paralleldrive/cuid2 |
| 길이 | ~25자 | 24자 (기본값, 설정 가능) |
새 프로젝트에는 CUID v2가 권장 선택입니다. SHA-3 기반 구성은 출력이 불투명함을 의미합니다 — ID에서 타임스탬프, 카운터, 지문을 역공학할 수 없습니다. 기존 데이터셋과의 하위 호환성이 필요하거나 의존성 없는 구현이 필요한 경우에만 CUID v1을 사용하세요.
사용 사례
@id 전략으로 CUID를 사용합니다 — @default(cuid()) — JavaScript 생태계에서 가장 널리 배포된 ID 형식 중 하나입니다.코드 예시
공식 CUID v2 패키지(권장) 설치 또는 의존성 없는 최소 v1 구현 작성:
// npm install @paralleldrive/cuid2 (recommended — CUID v2)
import { createId } from '@paralleldrive/cuid2'
const id = createId()
// → 'tz4a98xxat96iws9zmbrgj3a'
// Custom length
import { init } from '@paralleldrive/cuid2'
const createShortId = init({ length: 10 })
createShortId() // → 'zxp1l6mf4c'v1 알고리즘의 의존성 없는 Node.js 구현을 선호하는 경우:
// Pure Node.js — CUID v1 style (no dependencies)
let counter = 0
function pad(str, size) {
return str.padStart(size, '0').slice(-size)
}
function fingerprint() {
const os = require('os')
const source = [process.pid, os.hostname().length].join('')
let hash = 0
for (const c of source) {
hash = ((hash << 5) - hash) + c.charCodeAt(0)
hash |= 0
}
return pad(Math.abs(hash).toString(36), 4)
}
function cuid() {
const timestamp = Date.now().toString(36)
const cnt = pad((counter++ & 0xffff).toString(36), 4)
const fp = fingerprint()
const rnd = pad(Math.floor(Math.random() * 0xffffffff).toString(36), 4)
+ pad(Math.floor(Math.random() * 0xffffffff).toString(36), 4)
return 'c' + timestamp + cnt + fp + rnd
}
console.log(cuid()) // → 'clrc4gkwz001ag2hs3k7f9m2q'Prisma와 PostgreSQL로 CUID를 데이터베이스 기본 키로 사용:
-- Use CUID as a primary key in PostgreSQL
CREATE TABLE users (
id TEXT PRIMARY KEY DEFAULT gen_cuid(),
name TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
-- Prisma schema (auto-generates CUID by default)
model User {
id String @id @default(cuid())
name String
createdAt DateTime @default(now())
}