Base 64 간단 정리하기

박성룡 ( Andrew park )
8 min readNov 4, 2019

Canvas 를 공부하던중 Base 64 개념을 만나게 되어 이를 간단히 정리해보고자 한다.

Base 64 란 8비트 2진 데이터를 (플랫폼의) 문자 코드에 영향을 받지 않는 공통 ASCII 영역의 문자들로만 이루어진 일련의 문자열로 바꾸는 인코딩 방식을 가리키는 개념이다.

Base 64 는 데이터를 64진법 으로 나타낸다.

이를 0부터 63까지 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 으로 나타낸다.

베이스64의 정확한 규격은 RFC 1421, RFC 2045에 정의된다.

데이터를 Base64로 바꾸는 과정은

  1. 24비트 버퍼에 위쪽(MSB)부터 1바이트 (8비트)씩 3바이트를 채운다.
  2. 3바이트 보다 미만이라면, 버퍼의 남은 부분은 0으로 채워넣는다.
  3. 버퍼의 위쪽부터 6비트씩 잘라 그 값을 읽어, Base 64 의 값으려 변경한다.
  4. 버퍼의 남은 부분을 0으로 채운 값을 1바이트당 = 코드로 변경한다.

예를 들어, 데이터 가 Man 이라고 가정했을때,

이를 8비트로 변환하면,
01001101(M: 77) , 01100001(a: 97) , 01101110(n: 110)
이된다.

이를 6비트 씩 잘라 나열하면,
010011(T: 19) , 010110(W: 22) , 000101(F: 5) , 101110(U: 46)
이 된다.

이를 문자로 표현하면 TWFu 이 된다. 만약 3바이트를 채우기에 부족하다면, 나머지 Bit 영역을 0으로 채우고, 6 Bit 로 변환후, 부족했던 1 바이트(8bit) 당 1개의 = 를 추가한다.

Ma -> TWE=

Javascript 에서의 Base 64 변환

WindowOrWorkerGlobalScope 에 base64 utility method 로 btoa 과 atob 가 구현되어 있다.

  • btoa(DOMString data): DOMString;
  • atob(DOMString data): ByteString;

btoa() 은 입력 문자열을 Base 64 으로 표현되는 문자열을 반환한다.
만약 입력 문자열에 유니 코드 같은 btoa 에서 이해할 수 없는 문자열이 들어오면 InvalidCharacterError 가 발생한다.

atob() 은 인코딩된 Base 64 문자열을 디코드한다.
만약 입력 문자열에 Base 64 에 포함되지 않는 문자 (A-Z,a-z,0–9+/ 이외) 가 입력되면 DOMException 이 발생한다.

window.btoa('Man');
// TWFu
window.btoa('TWFu');
// Man
window.btoa('\u');
// Uncaught SyntaxError: Invalid Unicode escape sequence
window.atob('🙂');
// Uncaught DOMException: Failed to execute 'atob' on 'Window'

유니코드를 Base 64 로 변환해야할 경우, 일반적으로 InvalidCharacterError 예외 가 발생 한다.

하지만 유니코드를Uniform Resource Identifier (URI) 컴포넌트로 변경하고 다시 Base 64 변경한다면, 가능하다.

encodeURIComponent() 와 decodeURIComponent 를 이용하여, 유니코드 를 URI 으로 변경하여 사용할 수 있다.

var uni = '🙂';var data = encodeURIComponent(uni);
// %F0%9F%99%82
var encode = window.btoa(data);
// JUYwJTlGJTk5JTgy
var decode = window.atob(encode);
// %F0%9F%99%82
decodeURIComponent(decode);
// 🙂

Base 64 는 전자 메일을 통한 이진 데이터 전송 등에 많이 쓰인다.

A-Z,a-z,0–9,/+ 만을 사용하기 때문에, 문자 포맷이 달라 데이터를 손상시킬 수있는 시스템 간에 안정적으로 전송 될 수 있다.

Data URI scheme

Data URI scheme 은 웹페이지에 Data 를 인라인으로 포함하는 방법이다.

DataURL 은 작은 이미지 같은 파일을 문서 (Html, JS, CSS) 에 인라인으로 작성할 수 있는데, 작성된 이미지와 같은 정보는 이미 문서에 포함되어 있기때문에, 서버에 요청하지 않고도 이미지를, 사용할 수 있다.

이 구조는 RFC 2397 에 정의 되어 있다.

data:[<mediatype>][;base64],<data>

data: 으로 시작하며, , 으로 실제 데이터와 구분한다.

  • Hello, World! 를 변환하면, 아래와 같다.
  • data:,Hello%2C%20World!
  • data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

DataURL 은 데이터 길이 제한이 있을 수 있으며, 쿼리 문자열은 지원하지 않는다.

이미지를 사용할 때 주로 많이 사용 되는데, 아래와 같이 쓸 수 있다.

<!-- html -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQoU2NkYGD4z0AEYBxViC+UqB88AKk6CgERnGWPAAAAAElFTkSuQmCC" />
<style>
/* css */
body {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQoU2NkYGD4z0AEYBxViC+UqB88AKk6CgERnGWPAAAAAElFTkSuQmCC')
}
</style>
<script>
// js
var img = new Image();
img.addEventListener('load', () => {
// 캔버스에 그리기
var ctx = document.querySelector('canvas').getContext('2d');
ctx.drawImage(img, 0, 0);
});
img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQoU2NkYGD4z0AEYBxViC+UqB88AKk6CgERnGWPAAAAAElFTkSuQmCC"
</script>

하지만 문서에 이미지가 포함되기 때문에 image file 을 cache 할수 없으므로, 어떻게 쓰냐에 따라 성능에 좋을수도, 약영향이 있을수도 있다.

FileReader

FileReader 는 File 혹은 Blob 객체를 이용하여, 파일의 내용을 읽을 수 있게 해주는 Web API 이다.

Input 태그로 FileList 를 얻어 FileReader.readAsDataURL() 으로 Base64 데이터로 변환하고 이를 atob 로 데이터 변환 가능하다.

<!-- html -->
<input type="file" accept=".txt">/>
<script>
// js
document.querySelector('input[type=file]')
.addEventListener('change', (e) => {
var file = e.target.files[0];
var reader = new FileReader();
reader.addEventListener('load', () => {
// , 위치부터 Base 64 정보이다.
var dataIndex = reader.result.indexOf(',') + 1;
var base64 = reader.result.substring(
dataIndex,
reader.result.length
);
// Base 64 를 문자로 변환
var text = window.atob(base64);
console.log(text);
}, false);
reader.readAsDataURL(file);
});
</script>

해당 DataURL 은 이미지나 비디오 등의 DataURL 을 읽을 수 있는 이벤트에 전달이 가능하다.

ArrayBuffer

ArrayBuffer 는 일반 고정 길이의 이진 데이터 버퍼를 나타내는 데 사용되는 데이터 형 이다.

이를 상속받아 구현한 typed array 중 Uint8Array 를 이용하여, 버퍼 데이터를 받아, 8 Bit 데이터 형으로 만들고, 이를 6 Bit 로 쪼개서 Base 64 로 변환하는 형태의 btoa 를 구현할 수 있다.

위 코드는 버퍼정보를 받아서 8bit 형태로 만든뒤, (>> 18 등) 으로 6비트 씩 자르고, 이를 encodings 의 문자로 치환하는 것을 볼 수 있다.

base64ArrayBuffer([77, 97, 110])
// TWFu

--

--