Search
🆔

URL 단축기와 ID 생성기 구현

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
복사