CUID2 생성기

Generate secure next-generation CUID2 identifiers

개수
길이

생성된 CUID2

생성 버튼을 클릭하여 CUID2를 만드세요

CUID2란 무엇인가요?

CUID2(충돌 저항 고유 ID, 버전 2)는 데이터베이스, URL, 분산 시스템에서 기본 키로 안전하게 사용할 수 있는 짧고, 암호학적으로 안전하며 불투명한 ID를 생성하도록 설계된 CUID v1의 차세대 후계자입니다.

이전 버전과 달리 CUID2는 생성 시간, 호스트 머신 또는 생성한 프로세스에 대한 정보를 일절 드러내지 않습니다. 각 ID는 무작위 소문자로 시작하고 SHA-512에서 파생된 base-36 해시가 뒤따르는 겉보기에 무작위인 문자열입니다. 기본 길이는 24자이지만 저장소 제약에 맞게 2~32자로 설정할 수 있습니다.

CUID2는 현대적인 데이터베이스 툴킷에서 널리 권장됩니다. Prisma는 @default(cuid()) 스칼라의 기본 ID 전략으로 채택했으며, PlanetScale, Neon 및 기타 서버리스 데이터베이스 공급자는 CUID2를 선호 ID 형식으로 명시적으로 나열합니다.

CUID2가 CUID v1을 대체한 이유

2012년 Eric Elliott이 출시한 CUID v1은 클라이언트 측 ID 생성에서 일반 UUID에 비해 큰 개선이었습니다. 그러나 보안 연구자들이 설계의 두 가지 근본적인 문제를 발견했습니다:

  • 핑거프린팅: 모든 CUID v1 값에 내장된 호스트 지문을 사용하여 ID를 생성한 머신이나 프로세스를 식별할 수 있었으며, ID를 관찰할 수 있는 누구에게나 운영 메타데이터를 누출했습니다.
  • 예측 가능성: CUID v1이 단조 증가 카운터와 타임스탬프 세그먼트를 포함했기 때문에, 여러 ID를 관찰한 공격자가 미래 ID의 대략적인 범위를 예측하여 ID를 유일한 인증 검사로 사용하는 API에 대한 열거 공격을 가능하게 했습니다.
  • 비암호화 해시: CUID v1은 현대 보안 표준을 충족하지 못하는 간단한 비암호화 해싱 단계를 사용했습니다.

원래 저자 Eric Elliott은 CUID v1을 공식적으로 더 이상 사용하지 않음으로 표시하고 이러한 모든 문제를 해결하기 위해 CUID2를 처음부터 작성했습니다. 새 알고리즘은 Web Crypto API(SHA-512)를 사용하고 모든 결정론적 컴포넌트를 제거합니다.

CUID2 설계 원칙

예측 불가능
타임스탬프, 카운터, 호스트 지문이 내장되지 않습니다. 각 ID는 SHA-512와 결합된 새로운 암호화 무작위 솔트에서 생성됩니다.
평탄한 분포
SHA-512 다이제스트의 base-36 인코딩은 거의 균일한 문자 분포를 생성하여 B-트리 데이터베이스의 인덱싱 핫스팟을 줄입니다.
기본적으로 URL 안전
알파벳은 소문자 a–z와 숫자 0–9로 제한됩니다 — 하이픈, 밑줄, 대소문자 혼합 없음 — URL에서 퍼센트 인코딩 없이 안전한 ID입니다.
설정 가능한 길이
길이(2–32)를 선택합니다. 더 짧은 ID는 충돌 확률이 더 높음을 의미합니다; 권장 기본값 24는 ~4 × 10³⁷의 고유 값을 제공합니다.
항상 문자로 시작
첫 번째 문자는 항상 무작위 소문자로, CUID2 값이 이스케이프 없이 유효한 HTML 요소 ID 및 CSS 선택자임을 보장합니다.
서버 필요 없음
CUID2는 모든 최신 브라우저와 Node.js 15+에서 사용 가능한 Web Crypto API에만 의존하므로 서버와 동일한 보안 보장으로 클라이언트에서 ID를 생성할 수 있습니다.

CUID2 vs CUID v1 — 비교

아래 표는 CUID2와 현재 더 이상 사용되지 않는 CUID v1 사이의 주요 차이점을 요약합니다. 현재 CUID v1을 사용 중이라면 CUID2로 마이그레이션하는 것을 강력히 권장합니다.

속성CUID2CUID v1
보안암호화 (SHA-512)비암호화 (지문 기반)
예측 가능성불투명 — 메타데이터 누출 없음ID에서 타임스탬프 + 지문 가시
길이설정 가능 (2–32자)고정 25자
접두사무작위 문자 a–z항상 "c"로 시작
분포평탄 / 균일단조 증가 세그먼트
상태적극적으로 유지 관리원래 저자에 의해 더 이상 사용 안 함

CUID2 vs UUID v4 — 비교

UUID v4는 무작위 고유 ID의 지배적인 표준입니다. CUID2는 보안을 희생하지 않고 UUID v4에 비해 여러 실용적인 이점을 제공합니다.

속성CUID2UUID v4
기본 길이24자36자 (하이픈 포함)
URL 안전예 — 소문자 a–z + 0–9인코딩 필요 (하이픈 포함)
사용자 정의 길이예 (2–32)아니오 — 항상 128비트 / 36자
정렬 가능아니오 (설계상)아니오 (v4는 무작위)
엔트로피 소스SHA-512 + Web CryptoCSPRNG
문자 집합Base-36 (a–z, 0–9)16진수 + 하이픈

주요 트레이드오프는 친숙함입니다: UUID v4는 거의 모든 데이터베이스, 프로그래밍 언어, API 프레임워크에서 즉시 인식되는 IETF 표준(RFC 4122)입니다. CUID2는 성장하고 있지만 보편적이지 않은 지원을 가진 커뮤니티 표준입니다. 외부 시스템과의 상호 운용성이 가장 중요할 때 UUID v4를 선택하고; 양쪽을 제어하고 더 짧고 URL 안전한 ID를 선호할 때 CUID2를 선택하세요.

CUID2를 사용하는 곳

CUID2는 현대적인 JavaScript 및 TypeScript 생태계에서 빠르게 채택되고 있습니다:

  • Prisma — 가장 인기 있는 TypeScript ORM은 Prisma Schema v2+에서 @id 필드와 @default(cuid())에 CUID2를 권장 기본값으로 사용합니다.
  • PlanetScale — 문서와 스타터 템플릿은 분산 MySQL 플랫폼의 순차 스캔 성능 문제를 피하기 위해 애플리케이션 생성 기본 키에 CUID2를 권장합니다.
  • Drizzle ORM — 컬럼 정의를 위한 기본 내장 헬퍼 cuid2()를 제공합니다.
  • tRPC 보일러플레이트 — 많은 커뮤니티 tRPC + Prisma 스타터 템플릿이 기본 키 전략으로 CUID2와 함께 제공됩니다.
  • T3 Stack — create-t3-app 스캐폴딩 도구는 생성된 스키마 파일에서 CUID2 기본값과 함께 Prisma를 사용합니다.

코드 예시

공식 npm 패키지 @paralleldrive/cuid2가 간단한 API를 제공합니다:

JavaScript (npm — @paralleldrive/cuid2)
import { createId } from '@paralleldrive/cuid2'

// Generate a single CUID2 (default length: 24)
const id = createId()
console.log(id) // e.g. "tz4a98xxat96iws9zmbrgj3a"

// Custom length
import { init } from '@paralleldrive/cuid2'
const createShortId = init({ length: 16 })
const shortId = createShortId()
console.log(shortId) // e.g. "tz4a98xxat96iws9"

Prisma 스키마와 함께 CUID2 사용:

Prisma Schema
model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

npm 패키지 없이 Node.js에서 CUID2 생성 (브라우저에서 이 도구가 하는 것처럼 Web Crypto API만 사용):

Node.js (Web Crypto — no dependencies)
async function generateCuid2(length = 24) {
  const alphabet = 'abcdefghijklmnopqrstuvwxyz'

  // Random prefix letter
  const firstByte = crypto.getRandomValues(new Uint8Array(1))[0]
  const firstChar = alphabet[firstByte % 26]

  // Random 32-byte salt
  const salt = crypto.getRandomValues(new Uint8Array(32))
  const saltHex = [...salt].map(b => b.toString(16).padStart(2, '0')).join('')

  // SHA-512 of timestamp + salt
  const input = Date.now().toString(36) + saltHex
  const hashBuffer = await crypto.subtle.digest(
    'SHA-512',
    new TextEncoder().encode(input)
  )

  // Encode hash bytes as base-36 string
  const bytes = new Uint8Array(hashBuffer)
  let hash = ''
  for (let i = 0; i < bytes.length; i += 8) {
    let chunk = 0n
    for (let j = 0; j < 8 && i + j < bytes.length; j++) {
      chunk = (chunk << 8n) | BigInt(bytes[i + j])
    }
    hash += chunk.toString(36)
  }

  return (firstChar + hash).slice(0, length)
}

// Usage
const id = await generateCuid2()
console.log(id) // e.g. "m7k3r9p2nxq8zt5a6cwj4bvd"

자주 묻는 질문

CUID2는 CUID v1과 하위 호환되나요?
아니오. CUID2 ID는 CUID v1 ID와 완전히 다르게 보입니다. CUID v1은 항상 문자 "c"로 시작하며 고정 길이 25자입니다. CUID2는 무작위 문자로 시작하며 설정 가능한 길이(기본 24)를 가집니다. 기존 데이터베이스를 마이그레이션하는 경우 두 형식을 모두 처리하거나 모든 CUID v1 값을 교체하는 마이그레이션을 실행해야 합니다.
어떤 길이를 사용해야 하나요?
기본 24자가 대부분의 애플리케이션에서 권장되는 선택입니다. 대규모에서도 통계적으로 불가능한 충돌을 만드는 약 4 × 10³⁷의 고유 값을 제공합니다. 저장소가 중요하고 데이터셋이 수십억 레코드 이하인 경우 16자를 사용하세요. 최대 보안 마진을 위해 32자를 사용하세요.
CUID2는 생성 시간으로 정렬할 수 있나요?
아니오 — 이는 의도적입니다. CUID2는 열거 공격과 핑거프린팅을 방지하기 위해 모든 시간 정보를 의도적으로 버립니다. 시간 순서 ID가 필요하다면 ULID 또는 UUID v7을 고려하세요. CUID2는 보안과 불투명성을 위해 정렬 가능성을 포기합니다.
CUID2 vs NanoID — 무엇을 선택해야 하나요?
둘 다 안전하고 URL 안전합니다. NanoID는 기본적으로 21자로 약간 더 짧고 더 큰 알파벳(A–Za–z0–9_-)을 사용하여 문자당 더 많은 엔트로피를 제공합니다. CUID2는 CSS 선택자에서 더 안전한 제한된 알파벳(a–z, 0–9)을 사용하며 항상 문자로 시작합니다. 최대 엔트로피 밀도를 원한다면 NanoID를 선택하고; Prisma/ORM 통합이나 CSS 안전 ID가 중요하다면 CUID2를 선택하세요.
CUID2는 URL 안전한가요?
예. CUID2는 소문자(a–z)와 숫자(0–9)만 사용합니다. 하이픈, 밑줄, 더하기 기호, 슬래시, 등호가 포함되지 않으므로 인코딩 없이 URL, HTML id 속성, CSS 선택자, 파일 이름에 직접 포함할 수 있습니다.
CUID2를 데이터베이스 기본 키로 사용할 수 있나요?
예, 이는 주요 사용 사례 중 하나입니다. CUID2는 자동 증가 정수의 순차 패턴(행 수를 누출하고 열거를 가능하게 할 수 있음)을 피하고, UUID보다 짧으며(인덱스 공간 절약), URL 안전합니다. 대부분의 데이터베이스는 VARCHAR(24) 또는 TEXT 열로 저장합니다. ULID 또는 UUID v7과 달리 CUID2 값은 시간순이 아니므로 삽입 순서 스캔에 크게 의존하는 쿼리가 있다면 정렬 가능한 대안을 선호할 수 있습니다.