개발을 하다보면 가끔 정확한 이유를 모른채 하는 행위들이 있다.

나는 Base64 Encoding이 그랬다.

이미지를 웹페이지에 Embed 할 때도 했고, OAuth 인증을 할 때도 했고, AWS와 Azure의 Access Permission을 생성할 때도 했다. 생각해보면 HTTP로 데이터를 주고 받을 때 많이 사용했던 것 같은데 도무지 왜 하는지 이유도 몰랐고, 알려고 하지도 않았다.  그리고 이 링크의 댓글만 대충 읽어봐도 나 말고도 많은 개발자들이 Base64를 왜? 사용해야 되는지 정확히 모르고 있는 건 확실한 것 같다.

마치 제대 후 마시던 술과 같이 왜? 가 없다.

Base64?

왜? 를 알아보기 전 Wiki를 참고하여 Base64 Encoding이 뭔지 알아보자.

Base64란 Binary Data를 Text로 바꾸는 Encoding(binary-to-text encoding schemes)의 하나로써 Binary Data를 Character set에 영향을 받지 않는 공통 ASCII 영역의 문자로만 이루어진 문자열로 바꾸는 Encoding이다.

Base64를 글자 그대로 직역하면 64진법이라는 뜻이다. 64진법은 컴퓨터한테 특별한데 그 이유는 64가 2의 제곱수64=26이며 2의 제곱수에 기반한 진법 중 화면에 표시되는 ASCII 문자들로 표시할 수 있는 가장 큰 진법이기 때문이다. (ASCII에는 제어문자가 다수 포함되어 있기 때문에 화면에 표시되는 ASCII 문자는 128개가 되지 않는다.)

설명이 확 와 닿지도 않고 복잡한 것 같은데, 핵심은 Base64 Encoding은 Binary Data를 Text로 변경하는 Encoding이다.

변경하는 방식을 간략하게 설명하면 Binary Data를 6 bit 씩 자른 뒤 6 bit에 해당하는 문자를 아래 Base64 색인표에서 찾아 치환한다. (실제로는 Padding을 더해주는 과정이 추가된다.)

아래와 같이 6개의 bit를 10진수로 변환한 뒤, 해당 10진수에 해당하는 값을 Base64 색인표에서 찾아 치환한다.

1) 000001000010011000 (binary data)

2) 000001, 000010, 011000 (6 bit 단위로 구분)

3) 우리는 사람이기 때문에 각각의 6bit를 10진수로 변환 후, Base64 색인표에서 찾아 치환하면 편하다.
000001 -> 1 -> B
000010 -> 2 -> C
011000 -> 24 -> Y

Base64 색인표

0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

 

Why Base64?

이제 이 글을 쓰게된 동기로 돌아가, 왜 Base64 Encoding을 하는지 알아보자.
눈치가 빠른 사람은 눈치 챘겠지만 Base64 Encoding을 하게되면 전송해야 될 데이터의 양도 약 33% 정도 늘어난다. 6bit당 2bit의 Overhead가 발생하기 때문이다.  http://www.base64encode.org/에서 직접 테스트해보면 어렵지 않게 확인 할 수 있다.

Encoding전 대비 33%나 데이터의 크기가 증가하고, Encoding과 Decoding에 추가 CPU 연산까지 필요한데 우리는 왜 Base64 Encoding을 하는가?

지식인들의 해우소 WikiStackoverflow에서 그 이유를 찾아봤다.

문자를 전송하기 위해 설계된 Media(Email, HTML)를 이용해 플랫폼 독립적으로 Binary Data(이미지나 오디오)를 전송 할 필요가 있을 때,  ASCII로 Encoding하여 전송하게 되면 여러가지 문제가 발생할 수 있다.  대표적인 문제는

  1. ASCII는 7 bits Encoding인데 나머지 1bit를 처리하는 방식이 시스템 별로 상이하다.
  2. 일부 제어문자 (e.g. Line ending)의 경우 시스템 별로 다른 코드값을 갖는다.

위와 같은 문제로 ASCII는 시스템간 데이터를 전달하기에 안전하지가 않다. Base64는 ASCII 중 제어문자와 일부 특수문자를 제외한 64개의 안전한 출력 문자만 사용한다.
(* 안전한 출력 문자는 문자 코드에 영향을 받지 않는 공통 ASCII를 의미한다).

즉, “Base64는 HTML 또는 Email과 같이 문자를 위한 Media에 Binary Data를 포함해야 될 필요가 있을 때, 포함된 Binary Data가 시스템 독립적으로 동일하게 전송 또는 저장되는걸 보장하기 위해 사용한다” 라고 정리 할 수 있을 것 같다.

How Base64 Encoding works?

다른 Encoding과 다르게 Base64 Encoding은 왜? 가 어렵다. 어떻게는 비교적 쉽다.
1) 나누고, 2) 치환하고, 3) 패딩을 더해주면 끝이다.

Step 1) Binary Data를 6bit씩 나눈다.

Step 2) 나눈 6 bit들을 10진수로 변환한다.

Step 3) 변환된 10진수에 해당하는 값을 Base64 색인표에서 찾아 치환한다.

Step 4) 처음 binary data의 byte length를 3으로 나눈 뒤, 나머지가 0이 아니면, 3에서 나머지를 뺀만큼 패딩(=)을 추가한다.
* 패딩을 추가하는 이유는 원본으로 되돌릴 때 원본에는 없던 비트가 생기는 것을 방지하기 위함이다.

Practice.

Original : 01001000 01000001 01000011 01001011

Step 1) 010010 | 000100 | 000101 | 000011 | 010010 | 110000

Step 2) 18 | 4 | 5 | 3 | 18 | 48

Step 3) S | E | F | D | S | w

Step 4) SEFDSw== (3에서 나머지 4%3=1을 뺀 2개의 패딩(=)을 추가한다.)

 

Reference

https://tools.ietf.org/html/rfc4648
http://en.wikipedia.org/wiki/Base64
http://www.base64encode.org/
http://stackoverflow.com/questions/201479/what-is-base-64-encoding-used-for
http://terms.naver.com/entry.nhn?docId=863240&mobile&cid=2636&categoryId=2636