UTF-8 텍스트를 Base64로 인코딩하는 방법
- 입력 · 텍스트에 텍스트를 입력하거나 붙여넣으세요. 문자 인코딩은 이미 UTF-8로 설정되어 있습니다.
- Base64는 출력 · Base64에 나타납니다. 도구 아래의 입력 수치는 UTF-8 바이트 수입니다. 상자 위의 카운터는 JavaScript 방식으로 문자를 세므로 이모지 하나가 2로 셉니다.
- URL과 토큰에는 URL-safe (- _) 와 패딩 없음 (=) 을 켜고, 이메일이나 PEM에는 줄 바꿈을 고르세요.
- 출력을 복사하거나
base64.txt로 다운로드하세요.
Base64를 UTF-8로는 결과를 다시 텍스트로 바꿉니다.
UTF-8이 문자를 바이트로 바꾸는 방식
UTF-8은 코드 포인트마다 1~4바이트를 씁니다. ASCII는 1바이트 그대로이므로 영문 텍스트는 UTF-8과 ASCII에서 똑같이 인코딩됩니다. 나머지는 더 많은 바이트를 차지합니다.
| 문자 | 코드 포인트 | UTF-8 바이트 | Base64 |
|---|---|---|---|
A | U+0041 | 41 | QQ== |
é | U+00E9 | C3 A9 | w6k= |
€ | U+20AC | E2 82 AC | 4oKs |
日本語 | U+65E5 U+672C U+8A9E | 9바이트, 각 3바이트 | 5pel5pys6Kqe |
😀 | U+1F600 | F0 9F 98 80 | 8J+YgA== |
Base64는 바이트 위에 3분의 1을 더하므로, 중국어나 일본어 문장은 글자 수에서 Base64 문자 수로 대략 네 배가 되고, 이모지 하나는 8자가 됩니다. 한글 음절도 UTF-8에서 3바이트이므로 마찬가지입니다. 길이 제한이 있는 필드라면 이 점을 염두에 두세요. 크기 계산기가 도움이 됩니다.
이모지 시퀀스와 피부색
이모지 하나로 보이는 것이 사실은 여러 코드 포인트를 붙인 것인 경우가 많습니다. 피부색은 별도의 수정자이고, 가족이나 직업 이모지는 보이지 않는 폭 없는 결합자(ZWJ, U+200D)로 여러 사람을 이어 붙입니다.
| 이모지 | 코드 포인트 | UTF-8 바이트 | Base64 |
|---|---|---|---|
| 😀 | 1 | 4 | 8J+YgA== |
| 👍🏽 | 2 (엄지 척 + 중간 피부색) | 8 | 8J+RjfCfj70= |
| 👨👩👧 | 5 (사람 셋 + 결합자 둘) | 18 | 8J+RqOKAjfCfkanigI3wn5Gn |
이런 시퀀스 중간에서 Base64 문자열이나 디코딩한 바이트를 자르면 문자가 깨지므로, 인코딩된 UTF-8을 임의의 바이트에서 자르지 마세요.
같은 텍스트, 다른 바이트: 유니코드 정규화
일부 문자는 유니코드에서 올바른 표기가 두 가지입니다. é는 코드 포인트 하나인 U+00E9(조합형, NFC)일 수도 있고, e 뒤에 U+0301 COMBINING ACUTE ACCENT가 오는 것(분해형, NFD)일 수도 있습니다. 둘은 똑같이 보이지만 바이트가 다릅니다.
| 텍스트 | 형식 | 바이트 | Base64 |
|---|---|---|---|
é | NFC | C3 A9 | w6k= |
é | NFD | 65 CC 81 | ZcyB |
naïve | NFC | 6 | bmHDr3Zl |
naïve | NFD | 7 | bmFpzIh2ZQ== |
Apple의 예전 HFS+ 파일 시스템은 파일 이름을 분해형으로 저장하지만, 대부분의 키보드는 조합형 텍스트를 입력합니다. macOS에서 한글 파일 이름의 자모가 분리되어 보이는 현상도 같은 원인입니다. Base64 값을 비교하거나, 서명하거나, 키로 쓴다면 먼저 정규화하세요. 이 도구는 붙여넣은 코드 포인트를 그대로 인코딩하며 정규화하지 않습니다.
코드에서 UTF-8을 Base64로
JavaScript의 TextEncoder는 항상 UTF-8을 만듭니다. 입력이 여러 출처에서 올 수 있다면 먼저 정규화하세요.
const text = "e\u0301".normalize("NFC");
Buffer.from(text, "utf8").toString("base64"); // "w6k=" (Node.js)
new TextEncoder().encode(text); // Uint8Array [195, 169]
브라우저에서는 지원되는 경우 TextEncoder의 바이트를 bytes.toBase64()로 넘길 수 있고(Uint8Array.toBase64), 아니면 JavaScript 페이지의 btoa 헬퍼를 거치면 됩니다.
import base64, unicodedata
s = unicodedata.normalize("NFC", "nai\u0308ve")
base64.b64encode(s.encode("utf-8")).decode() # 'bmHDr3Zl'
파일과 스트리밍은 Python에서 Base64를 참고하세요.
자주 묻는 질문
UTF-8의 Base64는 일반 Base64와 같은가요?
네. Base64는 항상 바이트를 인코딩하며, “UTF-8을 Base64로"는 어떤 바이트인지를 말해 줄 뿐입니다. 일반 ASCII 텍스트는 UTF-8 바이트와 ASCII 바이트가 같으므로 어느 쪽이든 출력이 같습니다.
똑같아 보이는 두 문자열의 Base64가 다른 이유는 무엇인가요?
유니코드는 일부 문자를 여러 방식으로 쓸 수 있습니다. 코드 포인트 하나인 é는 w6k=이고, e에 결합 악센트를 붙인 것은 ZcyB입니다. 값이 일치해야 한다면 인코딩 전에 NFC로 정규화하세요.
인코더가 UTF-8 바이트 순서 표시(BOM)를 붙이나요?
아니요. 출력은 바로 텍스트의 바이트로 시작합니다. 받는 쪽이 BOM을 꼭 요구한다면 Base64는 바이트 EF BB BF의 인코딩인 77u/로 시작해야 합니다.
이모지 하나는 몇 바이트인가요?
이모지 코드 포인트 하나는 UTF-8에서 4바이트입니다. 피부색이 있는 이모지나 가족 이모지는 여러 코드 포인트로 이루어집니다. 👍🏽는 8바이트, 가족 👨👩👧는 18바이트입니다.