Files

110 lines
9.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "official-doc / NanoID — A tiny, secure, URL-friendly unique string ID generator"
source_type: official-doc
url: https://github.com/ai/nanoid
archive_url:
vendor: ai (Andrey Sitnik)
related_branches: [feature-resource-identifier-contract]
related_projects: [ca-skeleton]
tags: [official-doc, ca-skeleton, api-design, fetch-spec, clean-architecture]
created: 2026-05-31
last_reviewed: 2026-05-31
status: raw
confidence: medium
---
# official-doc / NanoID — A tiny, secure, URL-friendly unique string ID generator
> Layer: `raw/official-docs/` — NanoID 프로젝트 README 원문 발췌·출처 기록.
> 검증된 요약은 `/ingest` 후 `wiki/concepts/`에 별도 작성. 원본은 raw에 영구 보관.
> **주의**: 이 자료는 GitHub 프로젝트 README (project-level documentation) 이며 IETF 표준이나 공식 벤더 spec 이 아니다. 규범적 강제력은 없으나 de facto 채택 수준은 높다.
## Parent / 활용 branch (필수, 최소 1개+)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-resource-identifier-contract]] | D1 (resource ID default 형식 후보로서 NanoID 근거), D2 (64자 URL-safe 알파벳 `A-Za-z0-9_-` charset 근거), D3 (URL-safe-by-default 속성 근거), D9 (crypto module / hardware random generator 사용 = SecureRandom 의무 근거) |
## 출처 / Source
- 원본 URL: https://github.com/ai/nanoid
- 아카이브 URL: (미확인 — archive.org 스냅샷 별도 확보 권장)
- 저자 / 조직: Andrey Sitnik (ai) — Evil Martians
- 발행일: 프로젝트 첫 릴리즈 2017년경, README 지속 업데이트 중
- 마지막 확인일: 2026-05-31
## 왜 저장했는지 / Why archived
`feature-resource-identifier-contract` 의 D1 ~ D9 결정에서 NanoID 는 UUID v4 / UUID v7 / ULID 와 함께 resource ID 후보로 검토된다.
NanoID 의 21자 기본 길이·URL-safe 알파벳·crypto 기반 SecureRandom·UUID v4 와의 충돌 확률 동등성을 이 README 가 직접 명시하므로, 해당 결정의 Evidence quote 원천으로 보관한다.
## 핵심 인용 / Key quotes (verbatim, 5문장)
> [§ 프로젝트 설명 — README line 8] "A tiny, secure, URL-friendly, unique string ID generator for JavaScript."
> [§ Comparison with UUID — README lines 6768] "For there to be a one in a billion chance of duplication,
> 103 trillion version 4 IDs must be generated."
> [§ Comparison with UUID — README lines 7273] "Nano ID uses a bigger alphabet, so a similar number of random bits
> are packed in just 21 symbols instead of 36."
> [§ API / Blocking — README lines 195196] "By default, Nano ID uses URL-friendly symbols (`A-Za-z0-9_-`) and returns an ID
> with 21 characters (to have a collision probability similar to UUID v4)."
> [§ Security — README lines 107109] "**Unpredictability.** Instead of using the unsafe `Math.random()`, Nano ID
> uses the `crypto` module in Node.js and the Web Crypto API in browsers.
> These modules use unpredictable hardware random generator."
## Claims Extracted / 추출된 주장
> 이 자료가 **직접 말하는 것만** claim 으로 분리한다. 내 프로젝트에 적용한 결론은 여기 쓰지 않는다.
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| NANOID-C1 | NanoID 의 기본 ID 길이는 21자이며, UUID v4 와 유사한 충돌 확률을 가지도록 설계되었다 | [§ API/Blocking, line 195196] "By default, Nano ID uses URL-friendly symbols (`A-Za-z0-9_-`) and returns an ID with 21 characters (to have a collision probability similar to UUID v4)." | `official-reference` | NanoID 라이브러리의 기본 설정 (모든 지원 언어 포트에서는 포트별 검증 필요) | 특정 애플리케이션에서의 충돌 확률이 UUID v4 와 실제로 동일하다는 것 (비트 분포 동일성만 주장, 구현 품질 동일성 아님) |
| NANOID-C2 | NanoID 의 기본 알파벳은 `A-Za-z0-9_-` (64자 URL-safe 문자)이다 | [§ API/Blocking, line 195] "By default, Nano ID uses URL-friendly symbols (`A-Za-z0-9_-`)" | `official-reference` | NanoID JS 라이브러리 기본 설정 | 모든 포트 언어의 기본 알파벳이 동일하다는 것; RFC 3986 `unreserved` 문자셋 전체와 동일하지는 않음 (`~` 제외) |
| NANOID-C3 | NanoID 는 UUID v4 와 유사한 126 random bits 를 포함하며, 10억 분의 1 충돌 확률을 달성하려면 103조 개의 UUID v4 ID 가 필요하다 | [§ Comparison with UUID, line 6768] "For there to be a one in a billion chance of duplication, 103 trillion version 4 IDs must be generated." | `official-reference` | NanoID JS (동일 비트 수 기반의 비교) | NanoID 와 UUID v4 의 충돌 확률이 수학적으로 동일하다는 것 (NanoID 126bit, UUID v4 122bit — README 본문 명시); 모든 사용 환경에서 동일한 분포 보장 |
| NANOID-C4 | NanoID 는 `Math.random()` 대신 Node.js `crypto` 모듈 또는 Web Crypto API (브라우저) 를 사용하여 예측 불가능한 하드웨어 난수를 생성한다 | [§ Security, line 107109] "Instead of using the unsafe `Math.random()`, Nano ID uses the `crypto` module in Node.js and the Web Crypto API in browsers. These modules use unpredictable hardware random generator." | `official-reference` | NanoID JS 의 기본 (`nanoid` import) 사용 시 | `nanoid/non-secure` 변형에는 적용되지 않음; JVM / Go 등 다른 언어 포트의 구현 동일성 보장 안 됨 |
| NANOID-C5 | NanoID 는 `customAlphabet(alphabet, size)` API 로 알파벳과 ID 길이를 커스터마이징할 수 있으며, 알파벳은 최대 256자까지 허용된다 | [§ Custom Alphabet or Size, line 238239] "`customAlphabet` returns a function that allows you to create `nanoid` with your own alphabet and ID size." | `official-reference` | NanoID JS 5.x (ESM) 기준 | 커스텀 알파벳 사용 시 충돌 확률이 기본값과 동일하다는 것; 256자 초과 알파벳 사용 시 내부 알고리즘 보안 보장 없음 (README 명시) |
### Strength 허용값
- `official-reference` — 공식 reference/API 문서 (본 자료는 GitHub 프로젝트 README — 벤더 공식 문서 수준)
## Usage Boundaries / 적용 경계
- 이 자료가 직접 증명하는 것:
- `NANOID-C1`: NanoID JS 기본 길이가 21자임
- `NANOID-C2`: NanoID JS 기본 알파벳이 `A-Za-z0-9_-` (64자 URL-safe) 임
- `NANOID-C3`: 기본 설정에서 UUID v4 와 유사한 충돌 확률 (10억 분의 1 달성에 103조 개 필요) 을 가짐
- `NANOID-C4`: NanoID JS 기본 import 는 `Math.random()` 이 아닌 `crypto` 모듈 / Web Crypto API 를 사용함
- `NANOID-C5`: `customAlphabet(alphabet, size)` API 로 알파벳과 길이를 커스터마이징 가능
- 이 자료가 증명하지 않는 것:
- NanoID 가 특정 Java / Kotlin / Go 포트에서도 동일한 보안 특성을 가진다는 것 (포트별 독립 검증 필요)
- `nanoid/non-secure` 변형이 SecureRandom 의무를 만족한다는 것 (만족하지 않음 — README 명시)
- NanoID 알파벳 (`A-Za-z0-9_-`) 이 RFC 3986 `unreserved` 전체와 동일하다는 것 (`~` 문자가 `unreserved` 에 포함되나 NanoID 기본 알파벳에는 없음)
- NanoID 가 time-ordered ID 를 생성한다는 것 (생성하지 않음 — UUID v4 와 동일한 랜덤, DB index 성능은 UUID v4 수준)
- 이 README 가 IETF 표준 또는 공식 vendor spec 수준의 규범적 강제력을 가진다는 것
- 내 프로젝트 (ca-skeleton) 에 적용하려면 추가 확인이 필요한 것:
- Java / Kotlin 포트 (`nanoid-java` 등) 의 `SecureRandom` 사용 여부 — JVM 포트 README 별도 확인 필수
- PostgreSQL / MySQL 에서 NanoID varchar(21) 의 B-tree index 성능 — UUID v4 와 동일한 랜덤 분포이므로 page split 위험 존재 (time-ordered ID 와 달리)
- OpenAPI 3.1 에서 NanoID 형식 표현 방법 (`format: nanoid` 는 표준 없음 — `pattern` 으로 표현 필요)
- `feature-security-operational-baseline` 에서 `SecureRandom` 의무와 NanoID JS 포트가 정합하는지
## 메모 / Notes
- NanoID 는 time-ordered ID 가 아니므로 D10 (DB primary key 정책) 에서 UUID v4 와 동일한 약점 (B-tree page split) 을 가진다. D1 결정 시 DB 성능 요구사항이 높다면 UUID v7 / ULID 가 더 적합할 수 있다.
- README 에 명시된 벤치마크: `nanoid` JS 기준 ~4.9M ops/sec (Framework 13 7840U, Node.js 21.6). `crypto.randomUUID()` 는 ~14M ops/sec 로 NanoID 보다 빠름 — 성능 우선 시 `crypto.randomUUID()` (UUID v4) 가 유리하나 ID 길이는 36자로 길어짐.
- Claim 강도: 이 자료는 `official-reference` 로 분류했으나, IETF RFC (예: RFC 9562 UUID) 나 NIST 표준이 아닌 GitHub README 이므로 규범적 weight 는 낮다. 충돌 확률 수치 등은 외부 공식 분석으로 보강 권장.
- NanoID 는 20개 이상의 언어로 포팅되어 있으나, 각 포트의 보안 특성은 독립적으로 검증해야 한다.
## Related / 관련
- 같은 주제 다른 official-doc (예정):
- [[raw/official-docs/rfc9562-uuid]] — UUID v4 / v7 공식 표준 (IETF RFC 9562, 2024)
- [[raw/official-docs/ulid-spec]] — ULID 공식 spec (26자 base32, monotonic)
- [[raw/official-docs/cuid2-spec]] — CUID2 (timestamp leak 없는 보안 중심 ID)
- 이 자료를 인용한 wiki 요약: (생성 시 추가)