개발자 도구 · Base64 인코더 및 디코더
Mojibake 없이 Base64를 UTF-8로 디코딩: atob 및 TextDecoder
· 작동 방식
베이스64 인코딩 유니코드
atob()은 문자로 위장한 바이트를 반환하므로, 강조 표시된 텍스트가 디코딩 후 깨져 보이는 이유입니다. 이 게시물은 Base64에서 바이트, UTF-8 텍스트까지의 올바른 파이프라인과 실패 패턴을 인식하는 방법을 보여줍니다.
'Café'로 디코딩되는 API 응답 — 구체적인 mojibake 증상과 두 개의 잘못된 문자 뒤에 있는 2바이트
Base64 문자열 Q2Fmw6k=은 UTF-8 텍스트 카페인 바이트(67, 97, 102, 195, 169)로 디코딩됩니다. 순진한 디코더에 붙여넣고(atob 및 문자열 변환만) 출력은 종종 Café이며 각 악센트는 두 개의 잘못된 문자로 대체됩니다. 이 mojibake는 atob이 UTF-8 텍스트가 아닌 바이트 문자열(코드 단위 0–255)을 반환하기 때문에 발생합니다. 195 및 169 바이트는 UTF-8에서 악센트가 있는 é를 인코딩합니다.
별도의 라틴어 1 문자인 것처럼 처리하면 모지베이크 패턴이 제공됩니다. 올바른 파이프라인은 atob(바이트를 문자열로), 그 다음 TextDecoder(바이트를 UTF-8로 해석)이고 원본 텍스트가 다시 나타납니다. atob 함수는 손상되지 않았습니다. 이진 데이터용으로 설계되었습니다. 그 이름은 ASCII에서 바이너리로, 생성되는 바이너리 문자열은 각각 1바이트를 나타내는 일련의 코드 단위 0–255입니다.
atob()이 실제로 반환하는 것 — 디코딩된 텍스트가 아닌 바이트를 나타내는 코드 단위 0–255 문자열
Q2Fmw6k=(표준 Base64)을 입력하면 각 문자가 1바이트인 문자열을 출력합니다. 코드 단위는 67, 97, 102, 195, 169입니다. 해당 문자열을 직접 표시하거나 라틴어-1 텍스트로 해석하면 잘못된 출력이 표시됩니다. 누락된 단계는 코드 단위를 바이트 배열로 변환한 다음 배열을 UTF-8로 디코딩하는 것입니다.
charCodeAt 루프는 바이트 값을 복구합니다. atob 출력의 각 문자에 대해 charCodeAt를 호출하여 코드 단위(번호 0–255)를 가져와 Uint8Array에 저장합니다. 바이트 배열이 존재하면 charset utf-8를 사용하여 TextDecoder에 전달합니다. TextDecoder는 바이트 시퀀스를 읽고 UTF-8 텍스트로 해석하여 (195, 169)와 같은 바이트 시퀀스를 é와 같은 단일 문자로 결합합니다. 바이트(67, 97, 102, 195, 169)는 4자리 문자열 Café가 됩니다. 루프는 의도적으로 지루합니다. charCodeAt를 사용하여 반환된 각 코드 단위를 읽고 이를 일치하는 Uint8Array 위치에 할당합니다. 여기서는 문자 집합 결정이 발생하지 않습니다. 유일한 해석은 TextDecoder가 해당 배열을 수신하고 치명적인 오류 처리와 함께 UTF-8을 적용할 때 도착합니다.
해당 문자열을 Uint8Array로 변환 — charCodeAt 루프 및 변환이 아닌 바이트 복사인 이유
바이트 복구, UTF-8 해석이라는 2단계 프로세스가 Base64 인코더 및 디코더가 내부적으로 수행하는 작업입니다. mojibake 패턴은 이 오류를 알려주는 신호입니다. Café가 Café로 표시되면 UTF-8 바이트의 라틴어-1 해석이 표시됩니다. é의 UTF-8 바이트는 0xC3 0xA9(십진수 195, 169)입니다. 라틴어-1에서 코드 단위 195은 Ã이고 코드 단위 169은 ©입니다.
UTF-8 바이트 시퀀스를 각 바이트가 별도의 라틴어-1 문자인 것처럼 읽는 경우 모든 멀티바이트 UTF-8 시퀀스는 잘못된 대체 문자를 생성합니다. Café가 Caf 다음에 대체 문자로 나타나는 경우, 아니면 Caf로 나타나는 경우? 또는 Caf + U+FFFD를 사용하면 다른 오류가 발생합니다. 디코더가 바이트 시퀀스를 유효한 UTF-8으로 인식하지 못했습니다. 구체적인 예: Base64 SGVsbG8sIOS4lueVjCEg8J-Zgg==는 다음과 같이 디코딩됩니다.
TextDecoder 및 문자 집합 결정 - UTF-8로 디코딩하고 문자 집합이 왜 별도의 사실인지 알아야 합니다.
atob은 바이트(72, 101, 108, 108, 111, 44, 32, 228, 184, 180, 149, 140, 33, 32, 240, 159, 152, 130). 처음 6바이트는 ASCII입니다. Hello가 됩니다. 바이트 228, 184, 180는 CJK 문자를 나타내는 3바이트 UTF-8 시퀀스입니다. 149, 140 바이트는 다음 시퀀스의 일부입니다. 전체 시퀀스에는 마지막 문자에 대한 4바이트 이모티콘 시퀀스(240, 159, 152, 130)가 포함됩니다.
TextDecoder를 통해 올바르게 처리되면 모든 바이트가 결합되어 원본 혼합 스크립트 텍스트를 생성합니다. UTF-8 바이트 시퀀스에는 예측 가능한 길이가 있습니다. 0xxxxxxx로 시작하는 바이트는 단일 바이트 ASCII입니다. 110xxxxxx로 시작하는 바이트는 10xxxxxx로 시작하는 다음 바이트(총 2바이트)를 예상합니다. 1110xxxx로 시작하는 바이트에는 다음 2바이트(총 3바이트)가 필요합니다. 11110xxx로 시작하는 바이트에는 다음 3바이트(총 4바이트)가 필요합니다. CJK와 이모티콘이 혼합된 샘플의 경우 ASCII 직관이 더 이상 도움이 되지 않기 때문에 바이트 보기가 특히 진단적입니다. 여러 바이트가 표시되는 각 기호에 속하며 1바이트를 삭제하면 나머지 시퀀스가 잘못된 UTF-8로 이동됩니다. 엄격한 디코딩은 이러한 변화를 그럴듯해 보이는 손상 대신 명명된 실패로 바꿉니다.
작업된 예: CJK와 이모티콘이 포함된 Base64 문자열 디코딩 — 원본과 비교한 바이트, 코드 포인트 및 최종 문자열
1111110x로 시작하는 시퀀스는 UTF-8에서 유효하지 않습니다(미래를 위해 예약되어 있으며 사용되지 않음). 10xxxxxx로 시작하는 바이트는 리드 바이트로 표시되어서는 안 됩니다. 그것은 계속이다. 바이트 스트림이 규칙을 위반하면 유효하지 않습니다 UTF-8. charset utf-8를 사용하는 TextDecoder는 이러한 규칙에 따라 배열을 해석하고 유효한 시퀀스에 성공합니다. 유효하지 않은 경우 오류를 보고합니다.
Base64 인코더 및 디코더는 엄격 모드 플래그가 true인 TextDecoder를 사용합니다. 이는 잘못된 UTF-8이 대체 문자(U+FFFD)를 자동으로 삽입하는 대신 오류를 발생시킨다는 것을 의미합니다. Base64 문자열이 유효하지 않은 바이트로 디코딩되는 경우(UTF-8), 잘못된 텍스트를 계속하는 대신 엄격 모드가 발생합니다. 이는 디자인 선택입니다. 바이너리 페이로드(이미지, 키, 압축 데이터)는 텍스트가 아니므로 텍스트로 디코딩해서는 안 됩니다.
패턴 인식: Ã, †및 � — 문자 세트 문제에서 Base64 문제를 구별하는 방법
JPEG을 Base64로 디코딩하려고 하면 바이트 스트림이 유효한 UTF-8을 나타내지 않으며 엄격한 디코딩은 이를 거부합니다. 도구는 이러한 페이로드에 대해 16진수 보기를 제공합니다. 텍스트인 척하지 않고도 원시 바이트를 볼 수 있습니다. UTF-8 디코드 오류를 인식하려면 컨텍스트에서 바이트를 살펴봐야 합니다. 멀티바이트 시퀀스가 예상되는 홀수입니까?
잠재적 시퀀스의 첫 번째 바이트가 잘못되었습니까(10xxxxxx로 시작)? 연속 바이트가 누락되었나요? 바이트 출력 버튼은 조사에서 가장 깨끗한 포크를 제공합니다. 16진수로 표시되지만 텍스트 디코딩이 실패하면 Base64 구문 분석은 성공한 것이며 페이로드는 바이너리이거나 손상되었거나 다른 문자 집합으로 인코딩된 것입니다. Base64 구두점을 변경하면 올바른 바이트가 이미 나타난 후에는 문자 집합 불일치를 복구할 수 없습니다.
여기에 포함되지 않는 내용 — UTF-16 페이로드, 이미지와 같은 바이너리 출력 및 잘못된 바이트 처리
패턴이 일관됩니다. 단일 바이트 0xFF는 UTF-8에서 결코 유효하지 않습니다. 이는 ASCII 바이트일 수 없으며(0–127만 ASCII임) 선행 바이트일 수 없습니다(리드 바이트는 0xC0–0xFD, 0xFF는 예약됨). 단독 서로게이트(UTF-16 개념)는 UTF-8에 나타날 수 없습니다. 바이트 시퀀스 0xED 0xA0 0x80(대리 U+D800을 UTF-8 스타일로 인코딩)을 보면 유효한 UTF-8이 아닙니다.
한 가지 역사적 해결 방법은 btoa(unescape(encodeURIComponent(text)))입니다. encodeURIComponent는 카페를 %C3%A9(퍼센트 인코딩 UTF-8 바이트)로 바꾸고, 이스케이프를 코드 단위로 다시 압축하고, btoa는 코드 단위를 인코딩합니다. 이는 대부분의 텍스트에 작동하지만 단일 대리자에서는 취약하고 읽기 어렵습니다. 최신 파이프라인(TextEncoder에서 바이트로, 그 다음에는 base64로)이 더 명확하고 표준입니다. TextEncoder는 모든 최신 브라우저와 Node.js에 내장되어 있어 올바른 선택을 할 수 있습니다. UTF-16, 레거시 단일 바이트 인코딩 및 임의 파일 콘텐츠에는 해당 바이트에 대해 선택된 디코더 또는 바이너리 인식 뷰어가 필요합니다. ToolAcre는 의도적으로 이들 사이에서 추측하지 않습니다. 추측은 유효하지 않은 시퀀스를 오해의 소지가 있는 텍스트로 바꿀 수 있는 반면, 16진수 덤프는 나중에 정보를 바탕으로 해석할 수 있도록 모든 바이트를 보존합니다.
요약: Base64는 바이트를 제공하고 UTF-8은 텍스트를 제공합니다. Base64 인코더 및 디코더가 두 단계를 모두 수행하여 디코딩된 텍스트가 입력과 정확히 일치하도록 하는 방법
Base64 문자열이 있고 UTF-8 텍스트를 원하는 경우 전체 단계는 다음과 같습니다. Base64를 바이트로 디코딩(atob 또는 base64 디코딩 라이브러리 사용), 바이트에서 Uint8Array 생성, charset utf-8을 사용하여 배열을 TextDecoder에 전달, 결과를 문자열로 읽습니다.
입력이 텍스트가 아닌 이진 데이터인 경우 TextDecoder를 건너뛰고 바이트를 직접 검사합니다. Base64 인코더 및 디코더는 엄격한 UTF-8 디코딩이 거부하는 값을 보존하는 16진수 바이트 보기를 제공합니다. 해당 포크는 진단입니다. 성공적인 바이트와 실패한 텍스트는 Base64 구문 분석이 작동했음을 의미하지만 페이로드는 바이너리이거나 손상되었거나 이 도구가 추측하지 못하는 문자 세트로 인코딩되었습니다.