티스토리 뷰

CS

Base64 인코딩

기억용블로그 2022. 11. 3. 23:52
728x90

Base64는 바이너리 데이터 (주로 이미지)를 인코딩하는데 사용되는 알고리즘이다.

8bit로 표현되던 ASCII 코드를 6bit로 끊어 표현하게 되는데 이때 8:6의 비율로 변환되고 이는 4:3 == 1.3333..., 즉 33% (~ 37%까지. 줄바꿈에 의해 4%의 추가 오버헤드 발생)의 오버헤드를 발생시키게 된다. 

 

이러한 오버헤드에도 불과하고 아직까지 Base64를 널리 사용하고 있기에 이를 이해하기 위해서는 역사를 먼저 알아야 할 필요가 있다.

 

Base64 인코딩이 나타나기까지

태초에 0과 1이 있었다. 그때의 컴퓨터는 0과 1 밖에 이해하지 못 하는 계산기에 불과했고 (물론 지금도 그렇다) 인간은 0과 1로 표현할 수 있는 바이너리를 넘어선 무언가를 계산기끼리 주고받게 하기를 원했다.

0과 1만 가지고 인간에게 의미있는 무언가를 표현하고자 할때 필요한 것은 "사람간의 규칙"이다. 예를 들어 11101은 Q, 11001은 W, 10000은 E로 표현하자고 약속하는 것이다. 이렇게 두루뭉술하게 설명하는 이유는 바로 ASCII라는 표준이 등장하게 된 배경을 설명하기 위해서이다. (위의 예시는 1800년대에 사용되었던 Baudot code.)

지금은 너무 당연하게 표준으로 받아들이는 ASCII가 표준으로 받아들여지지 않던 시절이 있었고 그당시 존재하던 문제를 해결하기 위해 탄생되었다는 의미이다.

 

하지만 ASCII에게는 서로 다른 머신끼리 커뮤니케이션하기 위해 사용하기에는 몇 개의 결점이 있었는데 이 중 하나는 ASCII가 7bit로 하나의 캐릭터를 표현했다는 것이다. 대부분의 머신에서는 8bit로 하나의 캐릭터를 나타냈으므로 ASCII는 8-bit-clean하지 않은 문제를 가지고 있었다.

그 당시의 dial-up internet은 태생적인 한계(SNR, 신호 대비 잡음비)로 인해 바이너리 데이터를 주고받기에 적합하지 않았다.# 이를 해결하기 위해 나머지 1bit를 LSB나 MSB (Parity bit)로 이용하였지만 그당시의 통일되지 않은 시스템으로 인해 어떤 머신에서는 이런 parity bit를 완전히 지워버리는 일이 발생하기도 했으며 ASCII의 10번 (Line Feed, LF)과 13번 (Carriage Return, CR)이 서로 다른 머신에서 다르게 해석되어버리는 문제가 발생했다. (Unix에서는 LF로 개행, Windows에서는 CRLF로 개행)

 

이런 상황에서 서로 다른 머신에서 어떤 경우에도 변질되지 않았음을 보장할 수 있는 어떤 알고리즘이 필요했고 이때 Base64 인코딩이 등장하게 되었다.

 

Base64

Base64 인코딩은 정말 "거의 대부분의 경우에 안전하게 사용 가능한 64개의 캐릭터"를 모아놓은 테이블에 불과하다. 

 

"abcd"의 예시를 통해 Base64 인코딩하는 과정에 대해 알아보자.

 

1. 각 캐릭터에 할당된 ASCII의 decimal로 변환한다.

a = 97, b = 98, c = 99, d = 100

2. decimal을 8bit binary로 변환한다.

97= 01100001, 98= 01100010, 99= 01100011, 100= 01100100

3. 6bit로 자른다.

011000, 010110, 001001, 100011, 011001, 00

이때 마지막 6bit가 완전한 형태가 아니므로 padding, =을 추가한다.

011000, 010110, 001001, 100011, 011001, 000000 ==

4. binary를 다시 decimal로 변환한다.

011000= 24, 010110= 22, 001001= 9, 100011= 35, 011001= 25, 000000= 0 ==

5. Base64 테이블을 보고 decimal을 인코딩한다.

24= Y, 22= W, 9= j, 35= j, 25= Z, 0= A ==

 

결과적으로 “abcd”를 인코딩하여 더 긴 “YWJjZA==”를 얻게 되었다. 

왜 Base"64"를 선택했을까?

역사를 통해 왜 Base64 인코딩이 필요한지 알아봤고 정말 33% ~ 37%의 오버헤드가 발생하는 것을 확인했다. 이제 다시 처음으로 되돌아가서 근본적으로 왜 Base64를 선택했는지 알아보고자 한다.

 

원인을 확인해보면 Base64가 아닌 다른 어떤 것을 사용하더라도 모든 캐릭터가 안전하기만 하다면 사용이 가능하다는 것을 알 수 있고 이론적으로도 충분히 가능하다.

 

만약 10진수를 이용해서 ASCII를 표현해야한다고 생각해보자. ASCII는 총 128개이므로 3개의 자리수가 필요하고 이는 1개의 캐릭터를 표현하기 위해 3개의 바이트를 사용해야 되고 300%로 데이터가 증가하게 된다.

비슷한 이유로 16진수를 이용하면 1개의 캐릭터를 2개의 자리수로 표현하고 이는 200%로 증가한다.

이는 현실에서 사용하기엔 너무 나이브한 접근 방식이지만 Base64가 사용하기 안전하면서 동시에 그렇게까지 나쁜 성능을 가진 것은 아니라는 것을 의미한다.

 

그렇다면 마지막으로 왜 하필이면 64개의 캐릭터를 이용하는걸까? 왜 Base128은 안 되고 왜 Base256은 안 되는걸까?

이에 대한 해답은 상당히 간단한데 94개의 프린트 가능한 문자(0x21 ~ 0x7E)를 제외하고 나머지 문자들(0x00 ~ 0x20)은 프린트가 불가능하기 때문이다.

이점에 착안해서 94개 중 3개의 문자를 제외한 91개를 이용하여 오버헤드를 최대한 줄인 basE91 인코딩이 존재한다. (14% ~ 23%의 오버헤드를 가진다.)

 

 

레퍼런스

https://stackoverflow.com/questions/201479/what-is-base-64-encoding-used-for

 

What is base 64 encoding used for?

I've heard people talking about "base 64 encoding" here and there. What is it used for?

stackoverflow.com

https://stackoverflow.com/questions/3538021/why-do-we-use-base64

 

Why do we use Base64?

Wikipedia says Base64 encoding schemes are commonly used when there is a need to encode binary data that needs be stored and transferred over media that are designed to deal with textual data. T...

stackoverflow.com

https://stackoverflow.com/questions/6008047/why-is-base128-not-used

 

Why is base128 not used?

Why is only base64 instead of base128 used to transmit binary data on the web? The ASCII character set has 128 characters which in theory could represent base 128, but only base64 but not base128 i...

stackoverflow.com

 

'CS' 카테고리의 다른 글

CRDT의 기본 개념과 원리 그리고 구현체인 Yjs의 원리  (0) 2023.01.06
현대 암호학의 역사  (0) 2022.11.08
Stub, Fake, Mock, Dummy, Spy  (2) 2022.09.19
직렬화(Serialization)  (0) 2022.08.26
URI, URL, URN의 차이점  (0) 2022.08.25
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함