요약
UUID를 Base64url로 인코딩하여 사용한다면 기존 UUID 길이 36 바이트에서 22 바이트로 UUID를 짧게 사용할 수 있습니다.
UUID의 길이
본래 UUID는 128 비트 즉 16 바이트로 구성되어 있습니다. 하지만 흔히 보는 UUID(예: 1a1f7114-a9a5-4c90-a952-5be14615650d)는 36 바이트의 길이를 가지고 있습니다. 왜 일까요? 파이썬으로 생성된 UUID를 bytes형으로 바꾼 후 문자로 바로 읽어 보겠습니다.
import uuid id = uuid.uuid4().bytes print(id.decode('utf-8'))
Traceback (most recent call last):
File "test.py", line 5, in <module>
print(id.decode('utf-8'))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xad in position 0: invalid start byte
생성된 UUID에 따라 에러는 다르겠지만, 에러가 발생 할 것입니다. 생성 된 UUID는 utf-8로 해석할 수 있는 문자열의 형태를 갖지 못하기 때문에, 문자열로 바로 변경 될 수 없습니다. rfc-4122 UUID 표준 문서에 따르면, UUID를 사람이 읽기 쉬운 형태로 변경하기 위해 각 4비트를 하나의 16진수로 표현합니다. 그리고 각 16진수들을 8-4-4-4-12 포멧으로 8개의 16진수, 4개의 16진수, 4개의 16진수, 4개의 16진수 12개의 16진수를 위치 시킵니다. 4비트를 16진수로 바꾸다 보니 4비트가 1바이트로 늘어나고, 4개의 하이픈(-)이 추가되어, UUID는 총 36 바이트의 길이를 갖게 되었습니다.
UUID 인코딩 방법
앞서 UUID를 사람이 읽기 쉬운 형태로 표현하기 위해, 각 4비트를 16 진수로 바꾸었습니다. 이러한 방법을 Base 16 인코딩이라고 합니다. Base16 인코딩은 4비트를 1바이트로 표현하는데, 사실 1바이트는 8비트(256개)의 정보를 표현 할 수 있습니다.
UUID 길이를 짧게 사용하는 인코딩 방법
Base64
5비트를 1바이트로 표현할 수 있지 않을까요? Base32는 5개의 비트를 1바이트로 인코딩 할 수 있습니다. 그렇다면 Base64, Base128 더 나아가 Base256을 쓴다면 8개의 비트를 1바이트로 표현하니, 원래 UUID의 128 비트를 온전히 128비트로 사용할 수 있을까요? 여기에는 문제점이 있습니다. Base128, Base256들로 인코딩하면 특정 비트들은 특수 기호로 인코딩 됩니다. 이러한 특수기호로 표현된 정보들은 사람이 읽기 불편해집니다. Base64는 사용해 볼 수 있을까요? Base64는 알파벳 대문자 26개, 소문자 26개, 숫자 10개 그리고 특수기호 2개(+, /) 로 이루어집니다. Base64에 사용되는 특수기호 2개는 사람이 익숙한 특수 기호이기 때문에 Base64를 UUID 인코딩에 사용할 수 있습니다. 그러면 UUID를 Base64로 인코딩 한다면 22 바이트와 마지막 끝을 알리는 패딩 기호 2 바이트(==)가 추가되어 24바이트의 길이로 줄일 수 있습니다. 경우에 따라 마지막 패딩 기호를 생략한다면 UUID를 22 바이트로 표현할 수 있을 것 입니다.
Base64url
Base64로 인코딩된 UUID를 HTTP 통신을 위해 URI에 포함시킨다면, 특수 기호들(/, =) 때문에 문제가 발생할 것입니다. 때문에 rfc-4648에서는 특수 기호들을 마이너스(-)와 언더라인(_)으로 변경하여 사용합니다. 패딩 기호(=)는 URI에 사용 시, 퍼센트 인코딩을 하거나 데이터의 길이를 알고 있다면 생략 할 수 있다고 서술 되어 있습니다. 파이썬 base64 라이브러리에서는 Base64url 인코딩 방법을 제공합니다.
import uuid import base64 id = uuid.uuid4().bytes print(base64.urlsafe_b64encode(id))
b'v3o8hi_TRZCkEZ66H-V98g=='
결과에 마이너스(-)와 언더라인(_)이 포함되어 URI에 사용할 수 있는 형태가 되었습니다.
Ascii85
Ascii85 또는 Base85라고 불리는 인코딩 방법이 있습니다. Ascii85는 바이너리 4바이트를 5바이트의 아스키 문자로 표현합니다. 따라서 UUID를 Ascii85로 인코딩 한다면 20 바이트로 표현할 수 있습니다. 다만 Ascii85에 포함된 23개의 특수 문자(!#$%&()*+-;<=>?@^_`{|}~)는 url-safe하지 못합니다.
결론
UUID의 표준 표현방법은 36바이트의 길이지만, 인코딩을 다르게 한다면 UUID 길이를 짧게 할 수 있습니다. 여러 인코딩 중 url-safe한 Base64url 인코딩을 사용한다면 UUID를 24바이트로 줄일 수 있습니다. 여기에 UUID는 길이가 예측 가능하기 때문에 마지막 패딩 기호를 생략하면 22 바이트로 길이를 줄일 수 있을 것입니다.