I. ID 생성기
1. UUID
가. ID 생성 원리: UUID는 버전에 따라 ID 생성 원리가 다릅니다.
•
version 4의 경우, 무작위의 값으로 채워진 16 바이트 배열을 생성합니다. Java의 경우, SecureRandom 클래스로 무작위의 값을 생성합니다. 결과적으로 128비트 중 122비트(10의 36승)가 무작위의 랜덤값이기 때문에 동일한 값이 생성될 가능성은 매우 낮습니다.
•
version 3, 5의 경우, 인자로 전달된 값을 각각의 해싱 알고리즘으로 해시값을 생성한 후 UUID 형식으로 포맷팅합니다. version 3의 경우 MD5, version 5의 경우 SHA-1으로 해싱합니다. 앞의 두 버전의 방식은 동일한 인자를 전달하면 동일한 UUID를 반환한다는 특징이 있습니다.
•
version 2의 경우, 사용자 또는 그룹의 ID를 기반으로 UUID를 생성합니다. UUID 생성 방식이 다른 버전과 비교했을 때, 무겁다는 특징이 있습니다.
•
version 1의 경우, 로컬 머신의 MAC 주소와 생성 시간을 토대로 무작위의 값을 생성합니다. 하지만 앞의 두 가지 정보를 노출합니다.
나. 제약사항: version 4를 기준으로 아래와 같은 제약사항이 존재합니다.
•
숫자만으로 값을 생성할 수 없습니다. 만약 RDB의 키로 사용할 경우, 문자열의 값을 숫자로 변환하는 작업이 추가적으로 발생하기 때문에, 조인 연산과 같은 CPU 바운드 작업에서 성능 상 불리합니다.
•
정렬된 값을 생성할 수 없습니다. 클러스터링 인덱스 구조에서 정렬되지 않은 값은 흩어져서 저장되기 때문에 조회 시 Random I/O가 자주 발생하여 성능 상 불리할 수 있습니다.
•
시간 순으로 값을 생성할 수 없습니다.
•
상대적으로 긴 값(16자리)이 생성됩니다.
다. 구현
코드 참고
2. Twitter Snowflake
가. ID 생성 원리: Twitter의 Snowflake 방식은 ID를 여러 구성 요소로 나눠서 순차적이면서 고유하게 생성합니다.
•
시간 값 (Timestamp): 일반적으로 41비트를 사용하여, 밀리초 단위로 ID가 생성되는 시간을 표현합니다. 참고로 41비트로 표현할 수 있는 시간 범위는 대략 69년입니다.
•
데이터 센터 식별자 (Datacenter ID): 분산 시스템 내에서 데이터 센터를 구별하기 위한 값을 할당합니다. 예를 들어, 5비트를 할당할 경우 최대 32개의 데이터 센터를 구분할 수 있습니다.
•
머신/노드 식별자 (Worker ID): 동일한 데이터 센터 내의 서버 또는 노드를 구분하기 위한 값을 할당합니다. 데이터 센터 ID와 마찬가지로, 5비트를 할당할 경우 최대 32개의 노드를 구분할 수 있습니다.
•
시퀀스 번호 (Sequence Number): 같은 밀리초 내에 여러 ID를 생성할 수 있도록 하는 카운터입니다. 일반적으로 12비트를 사용하며, 이를 통해 밀리초당 최대 4096개의 고유 ID를 생성할 수 있습니다. 이론적으로, Snowflake 알고리즘은 하루에 최소 86,400,000×4096≈354×10^9개의 고유한 ID를 생성할 수 있습니다.
나. 제약사항
•
시간 의존성: 시스템 시간을 기반으로 ID를 생성하기 때문에, 시간 설정이 잘못되었을 경우 ID 생성에 영향을 줄 수 있습니다. 특히 시계가 뒤로 조정되면 ID 충돌이 발생할 수 있습니다. 만약 AWS 클라우드 인프라를 사용한다면 Amazon Time Sync Service를 이용하여 AWS 내 시간 동기화를 간단하게 처리할 수 있습니다.
•
데이터 센터와 노드 식별자의 한계: 데이터 센터 ID와 노드 ID에 할당된 비트 수에 따라, 관리할 수 있는 데이터 센터와 노드의 최대 수가 제한됩니다.
다. 구현
코드 참고
II. URL 단축기
1. 동작 일반
가. 단축 URL 생성
// HTTP 요청
POST http://localhost:55123/short-links
{
"url": "https://test.io"
}
// HTTP 응답
201 CREATED
{
"data": {
"shortId": "e3LuqD4nlg",
"url": "https://test.io",
"createdAt": "2024-02-05T14:31:28.349436"
}
}
JSON
복사
Controller & Domain 코드 참고
Service 코드 참고
나. 원본 URL 리다이렉트
// HTTP 요청
GET http://localhost:8080/redirect/e3LuqD4nlg
// HTTP 응답
302 FOUND
Headers
Location="https://test.io"
Kotlin
복사
Controller 코드 참고
Service 코드 참고
2. URL 단축값 생성 - Twitter Snowflake + Base62
가. 제약사항
•
알파벳과 숫자로 구성되어야 한다
•
유일해야 한다
•
가능한 짧아야 한다
•
하루에 1억개 이상 생성되어야 한다
나. 구현
{
"data": {
"shortId": "e3LuqD4nlg",
"url": "https://test.io",
"createdAt": "2024-02-05T14:31:28.349436"
}
}
Kotlin
복사
class IdGenerator {
private val generatorId = 0
private val generator = SnowflakeIdGenerator.createDefault(generatorId)
private val base62Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
fun generateUniqueId(): ShortId {
val snowflakeId = generator.next()
val base62Id = encodeBase62(snowflakeId)
return ShortId(base62Id)
}
private fun encodeBase62(number: Long): String {
var num = BigInteger.valueOf(number)
val base = BigInteger.valueOf(62)
val encoded = StringBuilder()
while (num > BigInteger.ZERO) {
val remainder = num.mod(base).toInt()
encoded.insert(0, base62Chars[remainder])
num = num.divide(base)
}
return encoded.toString()
}
}
Kotlin
복사
3. URL 단축값 생성 - UUID
가. 제약사항
•
위의 방식 URL 보다 더 짧아야 한다
나. 구현
{
"data": {
"shortId": "1c09d4d3",
"url": "https://test.io",
"createdAt": "2024-02-05T14:34:48.336071"
}
}
Kotlin
복사
class IdGenerator {
fun generateUniqueId(): ShortId {
val id = UUID.randomUUID().toString()
.replace("-", "")
.substring(startIndex = 2, endIndex = 10)
return ShortId(id)
}
}
Kotlin
복사