Base 64 인코딩에 대해 설명하실 수 있나요?

데이터를 주고 받기 위해 널리 사용되는 기술이다. 더 자세한 설명을 못한다면 이글을 읽어보길 추천한다.

Filoscoder
aaant
7 min readFeb 27, 2023

--

탄생 배경

인터넷 초기에는 거의 모든 커뮤니케이션이 텍스트로 기반이였다. 당시에는 이메일이 주 통신 수단이었기 때문에 데이터 전송에는 SMTP (Simple Mail Transfer Protocol) 프로토콜 기반이였다. SMTP는 모든 메시지를 7-bit의 ASCII로 제한되어 있었다. 하지만 이미지, 영상 또는 오디오와 같은 데이터를 메일 첨부 파일로 보내려면 8-bit ASCII가 필요했다. 데이터 교환을 위한 8-bit 패턴은 훨씬 나중에 표준화되었기 때문에 불가능했었다.

MIME: the game changer

7-bit 만 수용하는 채널에서 8-bit 데이터(Octet)를 전송하려면 약간의 변환이 필요했다. 이때 MIME (Multipurpose Internet Mail Extension)과 같은 새로운 인터넷 표준이 등장했다. MIME은 더욱 확장된 기능들이 있었기 때문에 이메일 첨부 파일로 멀티미디어 데이터를 주고 받을 수 있게 해줬다. 사용자는 SMTP 채널을 통해 8-bit 이상의 데이터를 주고 받을 수 있게 된것이다.

MIME 왜 중요한가?

MIME은 Base64 인코딩이라는 기본 인코딩 체계를 사용한다. 일반적으로 데이터 전송 중 인쇄 가능한 문자만 허용하는데 Base 64 인코딩을 구현함으로써 SMTP와 같은 7비트 형식만 허용하는 채널에서 8비트 ASCII 및 Non-ASCII 데이터를 전송할 수 있게 된것이다.

Base 64 인코딩이란?

Base 64 인코딩은 이진-텍스트(binary-to-text) 체계로, 이진 데이터를 64진법으로 표현된 ASCII 코드 문자열 형태로 나타낸다.

기본적으로 6-bit 마다 64자 기호로 인코딩된다. Base 64 기호 중에는: `A-Z`, `a-z`, `0–9`, `+`, `/`.

마지막에 비트가 모자르다면 `=` 패딩(padding) 문자를 사용하여 채운다.

이는 64개의 서로 다른 문자를 사용하여 이진 데이터를 표현하기 때문에 “Base 64”라는 이름이 붙여졌다.

왜 Base64인가? 63이나 65가 아닌 이유는?

인코딩은 여러개의 기호가 있을 수 있지만 기호의 수가 특정 비트에 맞춰지면 컴퓨터가 처리하기에 더 적합하게 사용될 수 있다.

예를 들어 16진수(hex)는 4-bit로 표현할 수 있는 값의 수인 16개의 기호를 가지고 있다. 같은 맥락에서 6-bit는, 63이나 65보다도, 64개의 숫자로 기호를 표현할 수 있다.

Base 64 인코딩은 어떻게 작동하나요?

8-bit로 표현된 이진 데이터 스키마를 6-bit chunk로 그룹화 한 다음, 각 chunk를 Base 64 문자 테이블에서 매핑하는 것으로 처리된다. 그 결과 생성된 ASCII 문자열은 텍스트 기반 채널을 통해 전송 가능한 인코딩된 데이터를 나타낸다.

조금 과정이 많으니까 차근 차근 예시를 살펴보자 🧐

“Hey” 텍스트 인코딩 예시

터미널에서 Base64 알고리즘을 사용하여 “Hey”이라는 텍스트를 인코딩해봤다.

결과값을 확인하면 일반 텍스트를 다른 무작위 문자열로 바꿔놓은것 같다. 어떻게 “Hey”SGV5Cg==가 되었는지 궁금하다.

1. 먼저 컴퓨터가 알아 들을 수 있게, “Hey” 테스트를 이진 데이터로 변환하자.

ASCII 테이블

일반 텍스트는 ASCII 코드로 표현한 10진수이기 때문에 반대 과정을 거쳐간다. 테이블에서 H e y 문자열의 decimal(10진수) 값을 찾아 binary(이진수) 8-bit로 변환하면 아래와 같다 👇

ASCII text > decimal > binary

2. 각 8-bit 그룹을 6-bit 그룹화

8-bit > chunks of 6-bit

3. 각 6-bit 그룹을 decimal로 변환

4. 각 decimal 값을 Base 64 테이블에 해당하는 ASCII 문자에 매핑

18 > S
6 > G
21 > V
57 > 5

각 6-bit의 decimal 값을 테이블에 매핑한 결과: “SGV5” 값을 얻었다!
Base 64로 인코딩 된 결과값이다.

근데…. 처음 터미널에서 얻은 값을 살펴보니 SGV5Cg== 였다.

Cg==”는 어디에 있지?

5. Base64: “Cg==” 뭔가요?

Base 64 인코딩 알고리즘을 특정 텍스트에 적용하면 “새 줄” (New line)도 고려한다. 아마 string을 다룰때 carriage return 에 대해 들어봤을 것이다. 새 줄을 시작하는데 쓰이는 제어 문자이다. 비영어권의 자판 개선을 위해 캐리지 리턴을 가리키는
(U+21B5) 기호가 도입되기도 했다.

이스케이프 시퀀스인 \r 문자를 가리킨다.

새줄(New line) ASCII 코드 값은 LF며 그리고 decimal 값은 10이다. 즉, 터미널에서 “Hey” 텍스트로 실행한 base64 알고리즘의 결과값을 “HeyLF”로 이해하는게 정답이다.

ASCII ‘LF’ character

“LF”는 알파벳 `L` 과 `F`가 아닌, ASCII 코드의 Line Feed, New Line값을 가리킨다. 이해를 돕기 위해 문자열로 표현했다.

우리가 이해하려는 “Cg==” 값을 얻으려면 위와 같은 변환 과정을 거쳐야한다.
아래 이미지로 확인해볼 수 있다:

a. LF (New Line) 코드의 decimal 값은 10이다.

b. 이를 8-bit 이진수로 변환하면 00001010이다.

c. 또한 6-bit chunk로 그룹화하면 00001010으로 나눌 수 있는데, 두번째 chunk의 6-bit의 모자른 자리수를 채우기 위해 padding 값으로 0000을 채운다.

d. 각 6-bit 이진수 chunk의 decimal 값은 232이다.

e. Base64 Index 테이블에서 ASCII 코드 값과 매핑하면 터미널에서 확인했던 Cg 그리고 채웠던 padding 값 == 문자열이다.

f. 조합하면 “Cg==”를 완성할 수 있다.

조금 긴 과정이였지만, 위에서 1번 부터 5번까지 과정을 모두 거치면, 터미널에서 Base64 알고리즘을 사용하여 “Hey” 텍스트를 인코딩한 결과가 왜 “SGV5Cg==” 인지 이해 할 수 있다.

근데.. 그냥 이진수로 사용하면 안되나?

상황에 따라 다를 수 있다. 예를 들어 이메일에 이미지를 첨부하는 경우 인코딩하는게 의미 없다 그냥 그대로 첨부하면 된다.

하지만 데이터를 텍스트 형태로 사용할 수 있는건 유용한 경우가 많이 있다. 특히 텍스트 데이터 사용만 제한 되어 있거나 텍스트로 사용하는게 편리한 경우이다.

예를 들어 JSON 구조는 순전히 텍스트 형식이므로 텍스트로 인코딩하는게 필요하다. HTML은 또한 텍스트 문서이다, 이미지와 같은 콘텐츠를 포함할 수 있지만 결국엔 텍스트 문서이기 때문에 모든 데이터는 텍스트로 변환해줘야 전송할 수 있다. 개인적으로 수동으로 자주 사용하는 경우는 css에 icon이나 이미지를 base64 텍스트 값으로 사용하는게 용이할때가 있는것 같다.

그리고 가장 자주 사용되는 환경은 네트워크 전송이 아닐까 싶다. 클라이언트와 서버간 http 프로토콜을 통해 리소스를 주고 받을때 텍스트 형식이 가장 빠르고 효과적이여서 아직도 사용되고 있다.

--

--