btoa()

btoa() 함수는 이진 문자열 (en-US)(String 객체 내 모든 문자가 이진 데이터의 바이트 한 개)로부터 Base64 (en-US) 인코딩된 ASCII 문자열을 생성해 반환합니다.

ASCII 값 0부터 31까지의 제어 문자처럼 통신에 사용하면 문제가 발생할 수 있는 데이터를 btoa()로 인코딩해 전송하고, 받는 쪽에서는 atob()로 디코딩하면 문제 없이 원래 데이터를 가져올 수 있습니다.

구문

btoa(stringToEncode)

매개변수

stringToEncode

인코딩할 이진 문자열 (en-US)입니다.

반환 값

stringToEncode를 Base64로 표현한 ASCII 문자열.

예외

InvalidCharacterError DOMException (en-US)

문자열이 바이트 한 개로 표현할 수 없는 문자를 포함하고 있으면 발생합니다. 자세한 정보는 아래의 "유니코드 문자열"을 참고하세요.

예제

const encodedData = btoa('Hello, world'); // 문자열 인코딩
const decodedData = atob(encodedData); // 문자열 디코딩

유니코드 문자열

btoa() 함수는 매개변수로 JavaScript 문자열을 받습니다. JavaScript에서는 문자열을 UTF-16 인코딩으로 표현하는데, UTF-16은 문자열을 16비트 (2바이트) 단위의 시퀀스로 나타냅니다. 모든 ASCII 문자는 단위 하나의 앞쪽 바이트만으로 표현할 수 있지만, 많은 수의 다른 문자들은 두 바이트를 모두 사용해야 합니다.

Base64는 이진 데이터를 입력으로 받도록 설계됐습니다. JavaScript 문자열로 얘기하자면 모든 문자가 바이트를 하나씩만 차지하는 경우를 의미합니다. 따라서 btoa()에 2바이트 문자를 포함한 문자열을 제공하면 오류가 발생합니다. 그런 문자열은 이진 데이터라고 하지 않기 때문입니다.

const ok = "a";
console.log(ok.codePointAt(0).toString(16)); // 61: 1바이트 미만

const notOK = "✓"
console.log(notOK.codePointAt(0).toString(16)); // 2713: 1바이트 초과

console.log(btoa(ok));    // YQ==
console.log(btoa(notOK)); // 오휴

btoa()를 사용해서 유니코드 텍스트를 ASCII로 인코딩해야 할 때 사용할 수 있는 방법 한 가지는, 문자열의 각 16비트 단위가 한 바이트씩 차지하도록 먼저 변환하는 것입니다.

// Unicode 문자열의 16비트 단위가 한 바이트씩 차지하도록 변환
function toBinary(string) {
  const codeUnits = new Uint16Array(string.length);
  for (let i = 0; i < codeUnits.length; i++) {
    codeUnits[i] = string.charCodeAt(i);
  }
  const charCodes = new Uint8Array(codeUnits.buffer);
  let result = '';
  for (let i = 0; i < charCodes.byteLength; i++) {
    result += String.fromCharCode(charCodes[i]);
  }
  return result;
}

// 1바이트를 초과하는 문자를 포함하는 문자열
const myString = "☸☹☺☻☼☾☿";

const converted = toBinary(myString);
const encoded = btoa(converted);
console.log(encoded);                 // OCY5JjomOyY8Jj4mPyY=

물론 이렇게 되면 디코딩한 문자열에 역변환까지 해야 원래의 문자열을 구할 수 있습니다.

function fromBinary(binary) {
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < bytes.length; i++) {
    bytes[i] = binary.charCodeAt(i);
  }
  const charCodes = new Uint16Array(bytes.buffer);
  let result = '';
  for (let i = 0; i < charCodes.length; i++) {
    result += String.fromCharCode(charCodes[i]);
  }
  return result;
}

const decoded = atob(encoded);
const original = fromBinary(decoded);
console.log(original);                // ☸☹☺☻☼☾☿

용어집 Base64 (en-US) 항목, 해결책 #1 – 인코딩 전에 문자열 이스케이핑 (en-US)의 예제 코드 utf8_to_b64b64_to_utf8 함수도 참고하세요.

명세

Specification
HTML Standard
# dom-btoa-dev

브라우저 호환성

BCD tables only load in the browser

같이 보기