
웹 개발을 하다 보면 고유한 ID를 생성해야 하는 경우가 정말 많다.
특히 이번 로그인 없이(개인 계정에 저장하는 데이터 없이) 진행하기 때문에 url구조가 복잡하다.
원래 항상 UUID만 생성해서 써왔는데 NanoID라는 걸 알게 되어서 고민이 되길래 찾아보았습니당.
| 항목 | UUID | NanoID |
|---|---|---|
| 길이 | 36자 (하이픈 포함) | 21~24자 (가변) |
| 예시 | 550e8400-e29b-41d4-a716-446655440000 | V1StGXR8_Z5jdHi6B-myT |
| 문자 구성 | 하이픈 포함, 영문자 + 숫자 | URL-safe 문자만 사용 |
| 표준화 | RFC 4122 공식 표준 | 비표준 (라이브러리 기반) |
| 지원 언어/프레임워크 | 거의 모든 언어에서 기본 제공 | 다양한 언어에서 라이브러리 제공, 다소 제한적 |
| DB 지원 | PostgreSQL, MySQL 등에서 네이티브 지원 | 문자열로 저장, 별도 최적화 없음 |
| 전역 고유성 | 전 세계적으로 고유성 보장 | 충분히 고유하지만 충돌 확률 존재 |
| 가독성 | 하이픈으로 인해 낮음 | 짧고 깔끔, 하이픈 없음 |
| URL 사용 | 길고 복잡해 부적합 | URL-safe, 바로 사용 가능 |
| 저장 효율성 | 길고 인덱스 크기 큼 | UUID보다 약 40% 짧아 저장 공간 효율적 |
| 레거시 지원 | 뛰어남 | 일부 오래된 시스템에서는 미지원 |
| 커스터마이징 | 불가능 (고정 형식) | 길이, 문자 집합 등 커스터마이징 가능 |
레거시 호환성, 표준성 중시 → UUID
가볍고 URL에 쓰기 좋은 ID → NanoID
"UUID v4와 NanoID의 충돌 확률을 비교하고, 어떤 경우에 충돌 확률이 더 적은지를 정량적으로 판단하기"를 GPT한테 시켜봤습니다.
결론부터 말하자면, NanoID는 기본 설정 기준에서 UUID보다 더 높은 엔트로피(126비트)를 가지므로, 같은 수의 ID를 생성하는 경우 충돌 확률이 더 낮다. 하지만 대량 생성 시에도 충돌을 완전히 피하려면, 엔트로피와 생성량에 따라 수학적으로 충돌 확률을 검토해야한다. 특히 NanoID의 길이나 문자 집합을 줄일 경우 이점이 사라질 수 있다.
| 항목 | UUID v4 | NanoID (기본 설정) |
|---|---|---|
| 엔트로피 | 122비트 | 약 126비트 |
| 가능한 조합 수 | ||
| 생성 개수 | 초당 1조 개 × 100년 = |
https://velog.io/@yujin_jeong/Birthday-Problem
참고하시길
충돌 확률은 다음 공식으로 근사됩니다.
⚠️ 이 값은 1보다 훨씬 큼 → 즉, 100년 동안 1조 개/초 생성하면 거의 확실히 충돌합니다....하하
여전히 충돌이 거의 확실하지만, UUID보다 약 16배 낮은 확률입니다.
예시로, NanoID의 d = 8.5 × 10³⁷를 넣으면
즉, NanoID로 충돌 확률이 10⁻⁹ 미만이 되려면 총 생성 수가 약 100조 개 이하여야 함
| 조건 | UUID v4 | NanoID (21자, 64문자) |
|---|---|---|
| 생성량이 매우 많을 때 (초당 1조 × 수십 년) | ✅ NanoID가 더 안전 (엔트로피 높음) | ✅ 충돌 확률은 더 낮지만 여전히 충돌 가능 |
| 생성량이 적거나 중간 수준일 때 | 둘 다 안전 | 둘 다 안전 |
| 커스터마이징된 NanoID (짧은 길이 등) | 🚫 충돌 확률 증가 가능 | 🚫 길이가 짧으면 위험 증가 |
| 엔트로피 보장된 상태에서 비교할 때 | UUID: 122비트 | ✅ NanoID: 126비트 → 더 안전 |
;; 그정도로 충돌하는 케이스면.. 음... 본인 불운이라고 생각하세요;
URL에서 ID를 전달하는 방식은 크게 두 가지가 있다.
| 구분 | Path Parameter | Query Parameter |
|---|---|---|
| URL 형태 | /posts/abc123xyz | /product?id=abc123 |
| 목적 | 리소스 자체를 식별 | 리소스에 대한 옵션/필터 |
| SEO | 유리 (각각 다른 페이지로 인식) | 불리 (같은 페이지의 변형으로 인식) |
| 가독성 | 깔끔하고 직관적 | 복잡할 수 있음 |
| 파라미터 개수 | 보통 1개 | 여러 개 조합 가능 |
| 캐싱 | 쉬움 | 복잡함 (파라미터 조합별) |
| API 스타일 | RESTful에서 선호 | 전통적 웹에서 선호 |
Path Parameter 방식:
✅ https://blog.com/posts/abc123xyz
✅ https://github.com/user/repo/issues/123
✅ https://youtube.com/watch/dQw4w9WgXcQ
Query Parameter 방식:
✅ https://aladin.co.kr/shop/wproduct.aspx?ItemId=343631553
✅ https://amazon.com/product?asin=B08N5WRWNW
✅ https://google.com/search?q=nanoid&hl=ko&type=web
// ASP.NET Web Forms 스타일
https://site.com/ProductDetail.aspx?ProductId=12345&CategoryId=567
특징:
💼 왜 이런 방식을 쓰나!
ASP.NET Web Forms는 Windows Forms 개발 경험을 웹으로 가져오려 했다. 그래서 페이지 단위로 생각하고, 파라미터를 통해 상태를 전달하는 방식이 자연스러웠다.
// React/Vue/Angular 스타일
https://site.com/products/abc123xyz
https://site.com/users/def456uvw/posts/ghi789rst
특징:
| 구분 | ASP.NET 전통 | 모던 웹 |
|---|---|---|
| 라우팅 | Query 중심 | Path 중심 |
| ID 형태 | 숫자 ID 선호 | UUID/NanoID 선호 |
| URL 예시 | /page.aspx?id=123 | /items/abc123 |
| SEO | 상대적으로 불리 | 유리 |
| 가독성 | 복잡함 | 직관적 |
🏦 엔터프라이즈 시스템
- 금융, 의료, 정부 시스템
- 절대적 고유성이 생명인 경우
- 레거시 시스템과 연동 많음
구체적 시나리오:
🚀 사용자 중심 서비스
- 공유 기능이 중요한 서비스
- 모바일 앱, 소셜 서비스
- URL 길이가 민감한 경우
구체적 시나리오:
ABC123으로 입장하세요!)| 데이터베이스 | UUID | NanoID |
|---|---|---|
| PostgreSQL | uuid 타입 네이티브 | varchar(24) |
| MySQL | CHAR(36) 또는 BINARY(16) | VARCHAR(24) |
| MongoDB | ObjectId 대신 사용 가능 | 더 간결해서 선호 |
| SQLite | TEXT | TEXT |
실제 개발할 때 Cursor나 다른 AI 도구에서 사용할 수 있는 프롬프트를 정리해봤다.
PostgreSQL과 Node.js Express를 사용해서 게시글 CRUD API를 만들어줘.
다음 조건을 만족해야 해:
1. 게시글 ID는 UUID v4를 사용
2. 데이터베이스에서 uuid 타입으로 저장
3. RESTful API 설계 (GET /posts/:id 형식)
4. TypeScript 사용
5. 에러 처리 포함
스키마부터 라우터까지 전체 코드를 작성해줘.
🎯 결론
UUID: 엔터프라이즈, 데이터베이스 중심, 절대 안전성
NanoID: 사용자 경험, URL 친화적, 모던 웹둘 다 충분히 안전하니까, 프로젝트 성격에 맞게 선택하면 된다!