(번역) 자바스크립트에서 base64 문자열 인코딩의 미묘한 차이
velog.io
자바스크립트의 인코딩에 관련하여 좋은 포스팅이 있어 요약해보았습니다.
(코드 부분을 함께 읽으면 좋기에 아래 첨부한 포스팅을 읽어보시는걸 추천합니다!)
참고문헌
https://velog.io/@superlipbalm/base64-encoding
요약
btoa(), atob()
js 에서 base64 인코딩 및 디코딩을 위한 핵심 함수입니다.
btoa() : 문자열 -> base 64
atob() : base64 -> 문자열
이 기능은 ASCII 문자 또는 단일 바이트로 표현할 수 있는 문자가 포함된 문자열에서만 동작합니다
(유니코드에서는 작동안함)
유니코드와 자바스크립트에서의 문자열
유니코드 : 문자 인코딩의 글로벌 표준이며, 특정 문자에 숫자를 할당합니다
이러한 숫자를 ‘코드 포인트’ 라고 합니다.
코드 포인트를 컴퓨터가 어디서든 일관되게 해석할 수 있도록 바이트 시퀀스로 만드는 두가지 방법이 있는데, 이를 UTF-8, UTF-16 이라 하며,
UTF - 8 : 1바이트~4바이트(바이트당 6비트)를 코드포인트가 사용가능합니다.
UTF - 16: 항상 2바이트(16비트)로 처리합니다.
자바스크립트는 문자열을 UTF-16으로 처리합니다.
즉, btoa()사용을 통해 제대로 인코딩 되지 않다면, 이는 utf-16 의 단일 바이트를 넘어서는 문자를 base64로 인코딩하려고 했기에 생겨난 문제입니다.
TextEncoder, TextDecoder 사용
유니코드를 인코딩할 때 발생하는 문제를 아래와 같은 순서로 해결할 수 있습니다.
(아래 참고문헌 참조) TextEncoder를 통해 UTF-16 -> UTF-8 변경(Uint8Array)합니다.
String.fromCodePoint()를 통해 Uint8Array -> 각 바이트를 코드포인트로 처리하여 모두 단일 바이트로 표현할 수 있는 코드 포인트 문자열 생성합니다.
반대과정인 디코딩도 동일합니다
TextEncoder, TextDecoder 사용시 유의할점 (론 서로게이트 문제)
문제가 있다면, 예를 들어 치즈 이모지의 코드포인트는 129472 인데, 16비트의 최대 숫자는 65535이기에 최대치를 넘겨버렸습니다.
자바스크립트의 UTF-16 에서는 이를 처리할 때 문제가 있습니다. (론 서로게이트 문제)
이에 에러를 표현해주어야 하는데, TextDecoder 에서는 이를 다른 문자열로 자동적으로 대체해버립니다.
이를 확인하기 위해서는 isWellFormed() 라는 함수가 있습니다.
문자열에 론 서로게이트가 포함되어있다면 에러를 발생시키게 됩니다.
브라우저에서 isWellFormed 를 지원하지 않는다면 encodeURIComponent를 사용해도 괜찮습니다.
다음 내용이 궁금하다면?
이미 회원이신가요?
2023년 11월 27일 오전 1:01