Tistory View

음... 이 글을 끝까지 읽는 것을 추천한다.

세상에 있는 잘못된 Javascript용 base64사용법들

 

UTF-8로 처리되지않는 btoa 함수

javascript에서 base64 인코딩을 하려고 하던 중 좀 어의가 없는 상황을 만났다. 어찌보면 틀렸다고도 할 수 있고, 맞다고도 할 수 있지만...

문제의 발생은 한글은 처리가 안된다는 것이다. 한글을 입력할 경우 다음과 같은 오류[에러]를 console log창에 서 확인 할 수 있다.

let a = 'abcd';
let b = '갓댕치';
console.log( btoa( a ) ); // [YWJjZA==] // 정상
console.log( btoa( b ) ); // < ERROR
// 불여우 : Uncaught DOMException: String contains an invalid character
// 중금속 : Uncaught DOMException: Failed to execute 'btoa' on 'Window' 
//         The string to be encoded contains characters outside of the Latin1 range.

한글을 넣으면 위와 같이 문제가 발생한다. 한글 뿐만아니라 ASCII의 기본 문자를 제외하고는 전부 터지는 오류다. 이 곳에는 당연히 이모티콘도 문제에 포함된다.

 

Base64를 왜 쓰는지 모르는 이가 카피하는 코드

구글을 뒤져보면 다음과 같은 코드가 있다.

// base64 인코딩
s = btoa(encodeURIComponent(str)); 

// base64 디코딩
s = decodeURIComponent(escape(atob( str )));

이 코드를 javascript에서만 사용한다면 문제가 없지만, base64를 쓰는 이유가 text로만 표현이 가능한 문서에 binary데이터를 넣거나, text로만 전송해야하는 곳에 사용하려고 나온 것인데, 인코딩 결과가 UTF-8이 아니라 x-www-form-urlencoded로 나오기 때문에 받는 쪽이나 문서에 삽입하려는 경우, decodeURIComponent같은 작업을 추가로 해줘야 한다.

base64를 쓰는 또다른 이유가 생성된 데이터가 원본에 33%만 커진다는 장점을 이용하는 것인 데, 이 것은 크기가 대따 커진다. base64를 쓰려는 의도와 전혀 맞지 않는 것이다.

 

 

현실적으로 쓰기 좋은 코드

그래서 MDN에서 제시하는 방법은 다음과 같다.(좀더 정확히 Johan Sundström 님하가 올린 것을 MDN에 기재됨)

let str = '갓댕치';
str = btoa(unescape(encodeURIComponent( str )));
console.log( 'result =[' + str + ']'); //  result =[6rCT64yV7LmY]

이 방법도 문제가 있다.. 이 건 뭐 어떻하라는 건지..

문제는 unescape함수가 워낙 예전..javascript가 나올때 거의 최초에 나온 함수라서 이게 "deprecated될까? 말까?"한 상황이다. 하지만 이게 UTF-8을 쓰기에는 가장 잘 만들어진 코드라서 Johan Sundstro[움라우트]m님하의 코드를 올리겠다.

function utf8_to_b64( str ) {
  return window.btoa(unescape(encodeURIComponent( str )));
}

function b64_to_utf8( str ) {
  return decodeURIComponent(escape(window.atob( str )));
}

이 코드는 escape, unescape함수가 사라지지 않는 그 날까지 사용가능기에, 사라질 때쯤 다른 코드를 사용하기를 바란다.

일단은 이 코드를 퍼다 쓰는 것을 필자는 권장한다.

 

추가로 알아두면 좋은 것이 js의 string타입은 UTF-16을 쓰고 있다.

 

레퍼런쑤

다음은 이 글을 작성하기위한 레퍼런스들 인데, 원래 필자는 위의 코드들이 맘에 안들어 새로 짜서 올리려고 했지만, Johan님하의 코드가 현실적으로 가장 깔끔하기 때문에 그냥 쓰기로 했다.

 

https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_1_%E2%80%93_escaping_the_string_before_encoding_it

 

Base64 - MDN Web Docs Glossary: Definitions of Web-related terms | MDN

Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. The term Base64 originates from a specific MIME content transfer encoding.

developer.mozilla.org

UTF-8용으로 가장 정확한 코드의 설명과 링크, 이 링크의 하단에 escape를 쓰지않고 일일이 작성한 코드가 있다. 그 코드를 escape함수가 사라지는 그날 적용을 해야한다.

 

 

https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder

https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder

 

TextDecoder - Web APIs | MDN

The TextDecoder interface represents a decoder for a specific text encoding, such as UTF-8, ISO-8859-2, KOI8-R, GBK, etc. A decoder takes a stream of bytes as input and emits a stream of code points.

developer.mozilla.org

이 링크는 utf-8과 javascript의 string을 서로 변환하는 오브젝트에 대한 링크다.

아직 실험실 버전이지만, 브라우저들이 잘 지원하니 문제 없이 쓸 수 있다.

 

 

 

 

 

Replies
Reply Write