[Primary Key 생성 전략] #7. 기타 방식 (Hash ID, Nano ID 등)
# 0. 들어가며
UUID나 Snowflake ID 외에도 고유한 식별자(Unique ID)를 생성하는 다양한 방법이 있습니다. 이번 글에서는 Hash 기반 ID, Nano ID에 대해 알아보았습니다.
# 1. Hash 기반 ID 사용 방법
Hash 기반 ID는 특정 데이터를 고유한 해시 값으로 변환하여 사용합니다. 이 방식은 기존 데이터(예: 이메일, 사용자명 등)를 기반으로 유니크한 ID를 생성할 때 유용합니다.
📌 해시 함수란?
해시(Hash) 함수는 입력 값을 일정한 길이의 고유한 문자열로 변환하는 함수입니다. 같은 입력 값 → 같은 해시 값이 나오며, 출력 값은 충돌 가능성이 매우 낮습니다. 비밀번호 저장, 데이터 무결성 검사, 유니크 ID 생성 등 다양한 용도로 사용됩니다.
📌 예제 코드 ( SHA-256을 사용한 해시 기반 ID 생성 (Java) )
public static String generateSHA256Hash(String input) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
// 바이트 배열을 16진수 문자열로 변환
BigInteger number = new BigInteger(1, hash);
StringBuilder hexString = new StringBuilder(number.toString(16));
// 64자리 길이를 맞추기 위해 앞에 0을 추가
while (hexString.length() < 64) {
hexString.insert(0, '0');
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("해시 알고리즘 오류", e);
}
}
Hash 기반 ID의 장점
✔ 기존 데이터로부터 유니크한 ID 생성 가능합니다
✔ 별도의 ID 생성 시스템이 필요 없습니다
✔ 암호화 수준이 강한 해시(SHA-256 이상)는 보안성이 높습니다
Hash 기반 ID의 단점
✔ 길이가 길어질 수 있습니다 (SHA-256: 64자리, SHA-512: 128자리)
✔ 역추적 가능성 (Rainbow Table 공격)
- 해시 값이 예측 가능하면 공격자가 원래 데이터를 찾을 수 있습니다.
- 해결 방법: Salt(랜덤 값)를 추가하여 보안 강화
# 2. Nano ID와 같은 짧은 ID 사용 방식
Nano ID는 짧고 충돌 가능성이 낮은 유니크한 문자열을 생성하는 방법입니다. UUID보다 더 짧고, 읽기 쉽고, URL-safe한 형식으로 ID를 생성할 수 있습니다
📌 예제 코드 ( Nano ID 생성 코드 (Python) )
from nanoid import generate
nano_id = generate(size=21) # 기본 21자
print(nano_id) # 예: "V1StGXR8_Z5jdHi6B-myT"
Nano ID의 장점
✔ UUID보다 짧고, 사람이 읽기 쉽습니다.
✔ URL-safe (특수 문자 없이 안전한 ID 생성 가능)
✔ 속도가 매우 빠름니다 (UUID보다 60% 이상 빠름)
Nano ID의 단점
✔ 분산 환경에서 충돌 가능성 있습니다
✔ 특정 길이를 유지해야 합니다
✔ 랜덤성이 높아 정렬이 어렵습니
# 3. 특정한 상황에서 유리한 이유
✅ Hash 기반 ID가 유리한 경우
- 기존 데이터(이메일, 사용자명 등)로부터 유니크한 ID를 생성할 때
- 보안이 중요한 환경에서 데이터 무결성을 유지해야 할 때
- 별도의 ID 생성 시스템 없이도 유니크한 값이 필요할 때
✅ Nano ID가 유리한 경우
- 짧고 사람이 읽기 쉬운 ID가 필요할 때
- URL-safe한 ID가 필요할 때
- 빠른 속도로 고유한 ID를 생성해야 할 때
✅ UUID나 Snowflake 대신 사용하면 좋은 경우
- UUID가 너무 길고 가독성이 나쁠 때
- Snowflake 같은 정렬 가능한 ID가 필요 없을 때
# 4. 해결 방법 (Hash ID, Nano ID 등의 단점 보완 방법)
✅ 해결 방법 1: Salt 추가로 보안 강화 (Hash ID의 Rainbow Table 공격 방지)
해커가 미리 계산된 해시 값을 통해 원래 데이터를 역추적하는 것을 방지할 수 있습니다.
import hashlib
import os
def generate_salted_hash(input_value):
salt = os.urandom(16).hex()
hash_value = hashlib.sha256((salt + input_value).encode()).hexdigest()
return f"{salt}:{hash_value}"
print(generate_salted_hash("user@example.com"))
✅ 해결 방법 2: Nano ID의 충돌 문제 해결 (특정 패턴 적용)
특정 길이와 패턴을 유지하면서 충돌 가능성을 줄일 수 있습니다
from nanoid import generate
def generate_custom_nanoid():
return generate(alphabet="0123456789ABCDEF", size=16)
print(generate_custom_nanoid()) # "A1B2C3D4E5F67890"
✅ 해결 방법 3: 짧은 Hash ID 사용 (Base58 인코딩 활용)
Base58을 사용하면 길이를 줄이면서도 유니크한 해시 값을 유지할 수 있습니다.
import base58
import hashlib
def generate_base58_hash(input_value):
hash_value = hashlib.sha256(input_value.encode()).digest()
return base58.b58encode(hash_value).decode()[:16] # 16자리로 축소
print(generate_base58_hash("user@example.com"))
# 5. 결론
✅ 기존 데이터(이메일, 사용자명) 기반으로 유니크한 ID 만들기 → Hash ID
✅ 짧고 URL-safe한 유니크 ID 만들기 → Nano ID
✅ UUID보다 가독성 좋은 ID가 필요 → Base58 변환
✅ 정렬이 필요 없고, 빠른 랜덤 ID가 필요 → Nano ID
🔹 SHA-256 및 MD5 공식 문서 (NIST, RFC 1321)
📌 https://csrc.nist.gov/publications/detail/fips/180-4/final
🔹 Nano ID 공식 문서 (GitHub 프로젝트)
📌 https://github.com/ai/nanoid
🔹 Base58 인코딩 공식 문서
📌 https://en.bitcoin.it/wiki/Base58Check_encoding