UUID(Universally Unique Identifier)는 전역적으로 고유한 식별자를 생성하는 방식입니다. Java에서는 java.util.UUID 클래스를 통해 UUID를 쉽게 생성할 수 있습니다.
import java.util.UUID;
public class UUIDExample {
public static void main(String[] args) {
UUID uuid = UUID.randomUUID(); // UUID v4 방식
System.out.println("Generated UUID: " + uuid);
}
}
UUID는 128비트(16바이트) 크기의 값을 가지며, 약 2¹²⁸(≈ 3.4 × 10³⁸) 개의 고유한 값을 생성할 수 있습니다. 이는 현실적으로 중복될 가능성이 거의 없는 수준입니다.
UUID는 중복될 수 있을까?
이론적으로는 UUID도 중복될 가능성이 있습니다. 하지만, 그 확률이 너무 낮아서 현실적으로 걱정할 필요가 없습니다.
1. 무작위(UUID v4) 기반 중복 가능성
UUID.randomUUID()는 UUID v4 방식을 사용하며, 랜덤 값을 기반으로 생성됩니다.
예제: 1조 개(10¹²)의 UUID를 생성했을 때 중복될 확률?
- UUID v4는 122비트 랜덤값을 포함 (나머지 6비트는 버전 정보)
- 생성 가능한 UUID 개수 = 2¹²² ≈ 5.3 × 10³⁶
- 생일 문제(Birthday Problem) 확률 계산에 따르면, 1조 개의 UUID를 생성해도 중복 확률 ≈ 10⁻¹⁸
이는 벼락 맞을 확률(10⁻⁶)보다도 훨씬 낮음
즉, UUID v4 방식은 현실적으로 중복 걱정을 하지 않아도 됩니다.
2. 특정 값을 기반으로 생성(UUID v3, v5)
- UUID.nameUUIDFromBytes(byte[])를 사용하면, 입력값이 같으면 항상 동일한 UUID가 생성됨
- 예를 들어, "example.com"을 기반으로 UUID를 만들면 누구든 같은 UUID를 얻게 됨
- 해결 방법: 랜덤 UUID(v4) 또는 추가적인 고유값과 함께 사용
3. 잘못된 UUID 사용 사례
UUID 중복이 발생하는 주요 원인은 잘못된 코드 구현 때문입니다.
- UUID 일부만 사용 → UUID.toString().substring(0, 8)처럼 일부만 사용하면 중복 위험 증가
- 잘못된 난수 생성기 사용 → SecureRandom 대신 단순 PRNG 사용 시 위험
- DB에서 UUID를 Shortened ID로 변환 → 해시 충돌 가능성 존재
UUID 중복 방지 방법
1. UUID v4 대신 UUID v1 사용
UUID v1은 현재 시간(타임스탬프)과 MAC 주소를 사용하여 생성됩니다.
✅ UUID v1 직접 구현 예시:
import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.util.Enumeration;
import java.util.Random;
import java.util.UUID;
public class UUIDv1Generator {
private static long lastTimestamp = -1;
private static final Random random = new Random();
public static UUID generateUUIDv1() {
long timestamp = System.currentTimeMillis();
long macAddress = getMacAddress();
if (timestamp <= lastTimestamp) {
timestamp = ++lastTimestamp;
} else {
lastTimestamp = timestamp;
}
long mostSigBits = (timestamp << 32) | (macAddress & 0xFFFFFFFFL);
long leastSigBits = random.nextLong();
return new UUID(mostSigBits, leastSigBits);
}
private static long getMacAddress() {
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
byte[] mac = interfaces.nextElement().getHardwareAddress();
if (mac != null) {
ByteBuffer buffer = ByteBuffer.wrap(mac);
return buffer.getLong();
}
}
} catch (Exception ignored) { }
return new Random().nextLong();
}
public static void main(String[] args) {
UUID uuid1 = generateUUIDv1();
System.out.println("UUID v1: " + uuid1);
}
}
✅ UUID v1은 시스템 시간과 MAC 주소를 사용하므로 중복 가능성이 더 낮음
2. UUID + 추가 정보 조합
UUID 자체도 고유하지만, 추가적인 정보와 함께 사용하면 중복을 더욱 방지할 수 있습니다.
UUID uuid = UUID.randomUUID();
String userSpecificUUID = uuid.toString() + "-" + System.currentTimeMillis();
System.out.println(userSpecificUUID);
📌 UUID + 타임스탬프 조합을 사용하면 사실상 중복이 불가능해짐.
3. 데이터베이스에서 UUID 중복 방지
UUID가 중복될 가능성은 매우 낮지만, 데이터베이스에서는 유니크(UNIQUE) 제약 조건을 추가하는 것이 좋습니다.
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100) NOT NULL
);
📌 PostgreSQL에서는 gen_random_uuid() 함수를 사용하여 중복을 방지할 수 있습니다.
결론
중복 가능성 비고
| UUID 버전 | 중복 가능성 | 비고 |
| UUID v1 | 매우 낮음 | MAC 주소 + 타임스탬프 사용 |
| UUID v3 | 있음 | 동일한 입력값이면 같은 UUID |
| UUID v4 | 극히 낮음 | 랜덤값 기반 (중복 확률 사실상 0) |
| UUID v5 | 있음 | 동일한 입력값이면 같은 UUID |
✅ 현실적으로 UUID v4를 사용하면 중복 걱정 없이 사용할 수 있음
✅ 중복이 걱정된다면 UUID v1을 직접 구현하거나, 추가적인 정보(Timestamp 등)를 결합
✅ 데이터베이스에서는 UNIQUE 제약 조건을 사용하여 안전성을 확보
🎯 결론: UUID 중복 가능성은 현실적으로 무시해도 될 정도로 낮다!
'개발 > 자바' 카테고리의 다른 글
| Java 10의 var 타입 정리 (0) | 2025.02.10 |
|---|---|
| UUID v7: 시간 기반의 차세대 UUID (0) | 2025.02.10 |
| Java 8 Optional 개요 (0) | 2025.02.01 |
| Java의 private, private static, private static final 차이점 (0) | 2025.01.29 |
| Java 1.7과 Java 1.8의 주요 변경 사항 비교 정리 (1) | 2025.01.21 |