한국어

개발자 도구 · Base64 인코더 및 디코더

btoa()가 이모티콘을 사용하는 이유와 JavaScript에서 UTF-8을 Base64로 인코딩하는 방법

· 작동 원리

베이스64 유니코드 인코딩

Base64 인코딩 전에 UTF-8 bytes으로 변환된 유니코드 문자
원본 ToolAcre 벡터 일러스트

btoa()는 최대 U+00FF까지의 문자만 허용하므로 악센트가 있는 텍스트, CJK 및 이모티콘이 표시됩니다. 이 게시물에서는 함수가 실제로 기대하는 것과 TextEncoder가 올바른 UTF-8 Base64 문자열을 얻는 방법을 보여줍니다.

btoa가 유니코드를 사용하고 악센트를 자동으로 잘못 인코딩할 수 있는 이유

btoa("😀")를 호출하면 이모티콘이 단일 바이트 크기의 코드 단위에 맞지 않기 때문에 InvalidCharacterError가 발생합니다. 더 미묘한 오류는 btoa("é")입니다. 사전 구성된 é는 256 미만의 U+00E9이므로 btoa는 이를 허용하지만 UTF-8 bytes C3 A9가 아닌 라틴어-1 byte E9를 인코딩합니다. e와 결합 표시로 작성된 동일한 표시 악센트는 표시가 허용 범위를 벗어났기 때문에 발생할 수 있습니다. 통합 문서의 약칭인 "악센트 던지기"에는 다음 조건이 필요합니다. 문자열은 큰 소리로 실패하거나 조용히 잘못된 바이트를 생성할 수 있습니다.

btoa()가 실제로 인코딩하는 것: 코드 단위 0-255의 이진 문자열 — 함수가 유니코드 텍스트가 아닌 라틴어-1 bytes을 중심으로 설계된 이유

btoa는 "이진 문자열"을 사용합니다. 각 JavaScript 문자 코드 단위는 0~255 범위에 있어야 하며 1바이트를 나타냅니다. 유니코드 텍스트 인코딩, 언어 또는 정규화를 이해하지 못합니다. 아스트랄 이모티콘은 두 개의 UTF-16 대체 코드 단위로 표시되며 둘 다 255보다 훨씬 크므로 원시 JavaScript 문자열을 직접 보내는 것은 작동하지 않습니다. 출력을 추상 문자가 아닌 바이트 인코딩으로 처리합니다.

UTF-8이 먼저, Base64가 두 번째 — Base64 알파벳이 적용되기 전에 텍스트가 바이트가 되어야 하는 이유

TextEncoder는 먼저 JavaScript 문자열을 UTF-8 byte 시퀀스로 변환합니다. 그런 다음 각 바이트를 이진 문자열 문자로 변환하고 해당 이진 문자열을 btoa에 전달하거나 바이트를 직접 허용하는 다른 API를 사용합니다. 디코딩의 경우 atob은 이진 문자열을 반환합니다. 바이트 값을 복구하여 TextDecoder("utf-8")에 제공합니다. ToolAcre는 대체 문자를 자동으로 삽입하는 대신 잘못된 형식의 UTF-8을 거부하는 엄격한 디코더를 사용합니다.

작업된 예: TextEncoder 및 btoa를 사용하여 'café 😀' 인코딩 — 바이트 시퀀스, 중간 바이너리 문자열 및 최종 출력

리터럴 텍스트 카페 😀의 경우 UTF-8 bytes은 16진수로 63 61 66 C3 A9 20 F0 9F 98 80입니다. ASCII c-a-f, é는 2바이트, 공백은 4바이트, 이모티콘은 4바이트입니다. 이 10바이트 중 Base64는 Y2Fmw6kg8J+YgA==입니다. 패딩과 알파벳은 바이트만 설명합니다. 그들은 언어에 라벨을 붙이지 않습니다. 직접적인 btoa("café 😀") 실패를 ToolAcre의 UTF-8 모드와 비교한 다음 결과를 디코딩하고 동일한 눈에 보이는 악센트와 이모티콘이 유지되는지 확인합니다.

오래된 unescape(encodeURIComponent()) 트릭과 그것이 해킹인 이유 — 내부적으로 수행되는 작업과 권장되지 않는 이유

기존 해결 방법은 btoa(unescape(encodeURIComponent(text)))입니다. encodeURIComponent는 UTF-8을 퍼센트 인코딩하고 unescape는 퍼센트 삼중항을 단일 코드 단위로 다시 압축하지만 unescape는 더 이상 사용되지 않으며 읽기 어렵고 잘못된 형식의 단일 서로게이트에 대해 어색합니다. URL이 존재하지 않는 경우에도 변환이 URL 처리처럼 보입니다. TextEncoder는 의도된 경계를 명확하게 명시합니다. 텍스트는 한 번 바이트가 되고 Base64는 그 후에만 작동합니다.

반대편에서 디코딩 — 왕복이 무손실되도록 atob을 TextDecoder와 페어링

atob 이후에는 임의의 바이너리 바이트에 대해 decodeURIComponent를 호출하지 말고 텍스트가 되기를 바랍니다. 문자 코드를 Uint8Array로 변환하고 TextDecoder를 통해 전달합니다. 카페 😀 예에서 결과는 원래 10바이트 UTF-8 시퀀스이고 그 다음에는 원래 문자열입니다. Base64가 이미지 또는 압축 파일 바이트로 디코딩하는 경우 유효한 UTF-8 텍스트를 전혀 나타내지 않을 수 있습니다. ToolAcre는 이진 데이터를 가장하는 것이 아니라 읽을 수 있는 산문이라고 보고합니다.

여기서 다루지 않는 내용 - 파일 및 바이너리 Blob 인코딩, base64url 변형 및 대규모 입력 스트리밍

이 설명은 UTF-8로 인코딩된 텍스트에 관한 것입니다. 파일 및 Blob Base64, JWT 세그먼트용 Base64url 및 멀티 기가바이트 데이터의 증분 인코딩에는 인터페이스나 메모리 요구 사항이 다릅니다. Base64는 또한 토큰을 암호화하지 않습니다. 토큰을 보유한 사람은 누구나 바이트를 디코딩할 수 있습니다. 디코더는 일반적인 누락된 패딩 및 공백을 허용할 수 있지만 상호 운용성은 여전히 ​​페이로드가 텍스트인지 아니면 임의의 이진 데이터인지 여부에 따라 달라집니다.

요점: 문자열이 아닌 바이트를 인코딩하고 왕복을 확인합니다. Base64 인코더 및 디코더가 UTF-8 단계를 수행하여 악센트, CJK 및 이모티콘이 유지되는 방법

원시 JavaScript 문자열이 아닌 바이트를 인코딩한 다음 왕복을 확인합니다. Base64 인코더 및 디코더는 붙여넣은 텍스트를 브라우저에 유지하면서 TextEncoder 및 TextDecoder 단계를 수행합니다. RFC 4648은 알파벳과 패딩을 지정합니다. UTF-8은 별도의 문자-바이트 계약을 제공합니다. 이 두 레이어를 혼합하는 것은 InvalidCharacterError와 조용한 Latin-1 손상의 근원입니다.