반응형
해당 글에서는 UUID에 대해서 이해하며 구조를 파악하여 이를 활용할 수 있는 방법에 대해서 이해를 돕기 위해 작성한 글입니다.
1) UUID(Universally Unique Identifier) 정의 및 구조
1. UUID 정의
💡 UUID(Universally Unique Identifier)란?
- 범용 고유 식별자를 의미하며 중복이 되지 않는 유일한 값을 구성하고자 할때 주로 사용이 되는
고유 식별자를 의미합니다.
- 주로 세션 식별자, 쿠키 값, 무작위 데이터베이스 키 등에 사용이 됩니다.
2. UUID 구조
💡 UUID는 16바이트(128비트) 형태의 구조를 가지며 하나의 UUID 길이는 36자리이며 “4개의 하이픈(-)”과 “32개의 16진수 문자열”로 구성이 되어있습니다.
구조 | 길이 (바이트 /비트) | 내용 |
Low Time | 4 / 8 (8자리) | 시간의 low 32비트를 부여하는 정수 |
Mid time | 2 / 4 (4자리) | 시간의 middle 16비트를 부여하는 정수 |
Mid time + version | 2 / 4 (4자리) | 최상위 비트에서 4비트 "version", 그리고 시간의 high 12비트 |
Clock sequence and variant | 2 / 4 (4자리) | 최상위 비트에서 1-3비트는 UUID의 레이아웃형식, 그리고 13-15비트 클럭 시퀀스 |
Node | 6 / 12 (12자리) | 48비트 노드 id |
[ 더 알아보기 ]
💡 UUID를 구성하였을 경우 중복이 발생하는 경우는?
- 340,282,366,920,938,463,463,374,607,431,768,211,456개의 다양한 UUID를 사용하기에 한 개의 시스템의 고유 식별자로 중복이 발생하는 경우는 이와 같습니다. 이는 100년 동안 생성했을 때 최소 1개가 중복 및 충돌될 확률이라고 합니다. 🥶
2) UUID의 버전
💡 UUID는 각각의 버전을 가지고 있고 랜덤한 문자열을 출력할 때 어떠한 기준으로 구성이 되었습니다.
1. 요약
💡 UUID를 이용한 버전은 총 5개가 존재합니다. 각각 출시년도에 따라서 버전이 존재합니다.
버전 | 설명 | 특징 |
UUID Version1 | 해당 버전은 “현재 시간”과 “랜덤한 MAC 주소”를 기반으로 생성됩니다. | 유일성이 보장되지만 보안에 취약함. |
UUID Version2 | 해당 버전은 이전 버전 1과 유사하지만 시퀀스 번호 대신 POSIX UID(사용자 ID)를 사용하여 생성됩니다. | 현재는 거의 사용하지 않음. |
UUID Version3 | 해당 버전은 해시 함수인 “MD5 해시”를 기반으로 이름과 네임스페이스에 대한 조합으로 생성됩니다. | 암호화 해시 함수를 사용하여 생성하므로 보안성이 높음. 이름과 네임스페이스가 같으면 같은 UUID가 생성됩니다. |
UUID Version4 | 해당 버전은 “랜덤한 값”을 기반으로 생성됩니다. | 보안성이 높고 생성속도가 빠릅니다. |
UUID Version5 | 해당 버전은 이전 버전 3과 유사하지만 “SHA-1 해시”를 사용하여 생성됩니다. | 보안에 취약하다는 단점이 있습니다. |
2. import java.util.UUID 메서드 종류
메서드 | 설명 |
static UUID randomUUID() | 무작위 UUID를 생성합니다. |
static UUID fromString(String uuid) | 주어진 UUID 문자열로부터 UUID를 생성합니다. |
long getLeastSignificantBits() | 이 UUID의 가장 낮은 64비트를 반환합니다. |
long getMostSignificantBits() | UUID의 가장 높은 64비트를 반환합니다. |
int compareTo(UUID val) | UUID와 주어진 UUID를 비교합니다. |
boolean equals(Object obj) | UUID와 주어진 객체가 같은지 여부를 반환합니다. |
String toString() | UUID를 문자열로 반환합니다. |
3. UUID Version 1
💡 해당 버전은 “현재 시간”과 “랜덤한 MAC 주소”를 기반으로 생성됩니다.
💡 유일성이 보장되지만 보안에 취약하다는 단점이 있습니다.
import java.util.UUID;
/**
* [공통함수] UUID v1을 생성하여 반환합니다.(MAC Address, TimeStamp 조합)
*
* @return
*/
public static UUID generateType1UUID() {
long most64SigBits = get64MostSignificantBitsForVersion1();
long least64SigBits = get64LeastSignificantBitsForVersion1();
return new UUID(most64SigBits, least64SigBits); // 62dd98f0-bd8e-11ed-93ab-325096b39f47
}
/**
* [MAC Address] MAC 주소 대신에 임의의 48비트 숫자를 생성합니다.(보안 우려로 이를 대체합니다)
*
* @return
*/
private static long get64LeastSignificantBitsForVersion1() {
Random random = new Random();
long random63BitLong = random.nextLong() & 0x3FFFFFFFFFFFFFFFL;
long variant3BitFlag = 0x8000000000000000L;
return random63BitLong | variant3BitFlag;
}
/*
* [TimeStamp] 타임스템프를 이용하여 64개의 최상위 비트를 생성합니다.
*/
private static long get64MostSignificantBitsForVersion1() {
final long currentTimeMillis = System.currentTimeMillis();
final long time_low = (currentTimeMillis & 0x0000_0000_FFFF_FFFFL) << 32;
final long time_mid = ((currentTimeMillis >> 32) & 0xFFFF) << 16;
final long version = 1 << 12;
final long time_hi = ((currentTimeMillis >> 48) & 0x0FFF);
return time_low | time_mid | version | time_hi;
}
[ 더 알아보기 ]
💡 MAC Address(Media Access Control)
- 네트워크 인터페이스를 식별하기 위한 고유한 주소입니다. 이는 전 세계에서 유일하며, 일반적으로 12자리 16진수로 나타납니다.
4. UUID Version 2
💡 해당 버전은 이전 버전 1과 유사하지만 시퀀스 번호 대신 POSIX UID(사용자 식별자)를 사용하여 생성됩니다.
💡 현재는 거의 사용하지 않는 버전입니다.
5. UUID Version 3
💡 해당 버전은 해시 함수인 “MD5 해시”를 기반으로 이름과 네임스페이스에 대한 조합으로 생성됩니다.
💡 암호화 해시 함수를 사용하여 생성하므로 보안성이 높습니다.
💡 단, 이름과 네임스페이스가 같으면 동일한 UUID가 생성됩니다.
import java.util.UUID;
/**
* [공통함수] UUID v3를 생성합니다.
*
* @return
*/
public static UUID generateType3UUID() {
String name = "example name";
UUID uuid3 = UUID.nameUUIDFromBytes(name.getBytes());
System.out.println("Version 3 UUID: " + uuid3); // Version 3 UUID: 4dfc6b14-7213-3363-8009-b2
return uuid3;
}
[참고] MD5 해시
6. UUID Version 4
💡 해당 버전은 “랜덤한 값”을 기반으로 생성됩니다.
💡 보안성이 높고 생성속도가 빠르다는 장점을 가지고 있으며 대중적으로 많이 사용되는 UUID 버전입니다.
import java.util.UUID;
/**
* [공통함수] UUID v4를 생성합니다.
*
* @return
*/
public static UUID generateType4UUID() {
// 버전 4 UUID 생성하기
UUID uuid4 = UUID.randomUUID();
System.out.println("Version 4 UUID: " + uuid4); // Version 4 UUID: c48b2aef-9d79-44fe-bd97-46fd31361069
return uuid4;
}
7. UUID Version 5
💡 해당 버전은 이전 버전 3과 유사하지만 “SHA-1 해시”를 사용하여 생성됩니다.
💡 SHA-1 해시에 대해서 보안 취약점이 발견이 되었다는 단점이 있습니다.
import java.util.UUID;
String name = "example_name";
UUID namespace = UUID.fromString("00000000-0000-0000-0000-000000000000");
UUID uuid = createUUIDv5(name, namespace); // 함수를 호출합니다
/**
* [공통함수] UUID v5를 사용하여 UUID를 생성합니다.
*
* @param name
* @param namespace
* @return
*/
public static UUID createUUIDv5(String name, UUID namespace) {
UUID uuid = createUUIDv5(name, namespace); // 함수를 호출합니다
byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
byte[] namespaceBytes = namespace.toString().getBytes(StandardCharsets.UTF_8);
byte[] bytesToHash = new byte[nameBytes.length + namespaceBytes.length];
System.arraycopy(nameBytes, 0, bytesToHash, 0, nameBytes.length);
System.arraycopy(namespaceBytes, 0, bytesToHash, nameBytes.length, namespaceBytes.length);
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] hash = md.digest(bytesToHash);
hash[6] &= 0x0f;
hash[6] |= 0x50;
hash[8] &= 0x3f;
hash[8] |= 0x80;
return UUID.nameUUIDFromBytes(hash);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Error creating UUID v5", e);
}
}
[참고] SHA-1 보안 취약점 관련 기사
2) UUID 활용
💡 일반적으로 보안성이 높고 생성속도가 빠른 “UUID Version 4”를 가장 많이 사용하기에 이를 기반으로 구성하는 방법 및 응용방법에 대해 공유합니다.
1. UUID Version 4 기본적인 타입
💡 일반적으로 UUID v4를 문자열로 사용하는 방법입니다.
import java.util.UUID;
String uuid = UUID.randomUUID().toString();
2. UUID Version 4 하이픈(-)을 제거한 구성
💡 UUID 총 길이는 36개이며, 하이픈을 제거하면 총 4개의 하이픈이 제거되고 32개의 랜덤 한 문자열로 구성이 됩니다.
💡단, 이 하이픈을 제거하면 국제 기준의 표준이 되는 UUID에 대해 유일성을 보장받을 수 없는 부분이 있습니다. 그래도 상당히 낮은 확률입니다.
import java.util.UUID;
/**
* [공통함수] UUID 생성 함수
*
* @MethodName : makeUuid
* @param isHyphen : 하이픈 포함 여부
* @return String
*/
public static String makeUuid(boolean isHyphen) {
String result = "";
if (isHyphen) {
result = UUID.randomUUID().toString();
} else {
result = UUID.randomUUID().toString().replace("-", "");
}
return result;
}
[참고] 랜덤하게 번호를 구성하는 방법에 대해 궁금하시면 이전에 작성하신 글을 참고하시면 됩니다
[참고] 기타 블로그를 작성하면서 참고한 사이트입니다.
https://www.baeldung.com/java-uuid
💡 [참고] 해당 소스코드는 아래 Repository의 UuidUtils.java 내에서 확인이 가능합니다.
반응형
'Java > 이론 및 문법' 카테고리의 다른 글
[Java] 다양한 형 변환(Type Conversion) 방법 이해하기 : 캐스팅(Casting) (0) | 2023.08.26 |
---|---|
[Java] JDK(Java Development Kit), Open JDK 이해하기 (0) | 2023.06.25 |
[Java] Collection Framework(Queue, Stack, Deque)의 인터페이스와 구현체 이해하기 -2 : 정의 및 예시 (1) | 2023.03.08 |
[Java] Collection Framework(List, Map, Set)의 인터페이스와 구현체 이해하기 - 1 : 정의 및 예시 (0) | 2023.03.06 |
[Java] 자료형(Data Type) 이해하기 : 기본 / 참조 자료형, 래퍼 클래스 (0) | 2023.02.21 |