Base64란 무엇인가?
Base64는 이진 데이터를 인쇄 가능한 ASCII 문자 시퀀스로 표현하는 인코딩 방식입니다. 이미지, PDF, 원시 이진 데이터 등 모든 바이트 시퀀스를 64개의 안전한 문자로만 구성된 문자열로 인코딩합니다. 그 문자들은: A–Z, a–z, 0–9, +, /이며 패딩에는 =을 사용합니다.
"Base64"라는 이름은 이 인코딩이 64진법 수 체계를 사용한다는 사실에서 비롯됩니다.
64개 문자 구성
| 그룹 | 문자 |
|---|---|
| 대문자 | A–Z (26개) |
| 소문자 | a–z (26개) |
| 숫자 | 0–9 (10개) |
| 기호 | +, / (2개) |
| 패딩 | = |
URL 특수 문자와의 충돌을 피하기 위해 +를 -로, /를 _로 대체한 URL 안전 변형도 있습니다.
Base64 인코딩의 동작 원리
Base64는 3바이트의 이진 데이터를 4개의 Base64 문자로 변환하는 방식으로 작동합니다.
- 입력에서 3바이트(24비트)를 가져옴
- 네 개의 6비트 그룹으로 분할
- 각 6비트 값을 Base64 알파벳의 문자에 매핑
예시: "Man" 문자열 인코딩
| 문자 | M | a | n |
|---|---|---|---|
| ASCII | 77 | 97 | 110 |
| 이진수 | 01001101 | 01100001 | 01101110 |
결합: 010011010110000101101110
6비트 그룹으로 분할: 010011 | 010110 | 000101 | 101110
매핑: T | W | F | u → "TWFu"
입력이 3바이트의 배수가 아닌 경우, 마지막 그룹을 완성하기 위해 = 문자로 패딩됩니다.
데이터 크기 오버헤드
Base64 인코딩은 데이터 크기를 약 33% 증가시킵니다(3바이트마다 4문자가 됨). 대용량 데이터에 Base64 사용 여부를 결정할 때 이 점을 고려해야 합니다.
간략한 역사
Base64는 MIME(Multipurpose Internet Mail Extensions)의 맥락에서 개발되어 1992년 RFC 1341로 표준화되었습니다. 이메일 시스템은 원래 7비트 ASCII 텍스트만 전송하도록 설계되었지만, 이미지나 문서 같은 첨부 파일은 이진 데이터입니다. Base64는 이진 데이터를 이메일 인프라를 안전하게 통과할 수 있는 일반 텍스트로 인코딩하여 이 문제를 해결했습니다.
이 이름과 개념은 Unix의 uuencode(다르지만 관련된 방식)에서 더 일찍 등장했지만, MIME의 Base64가 지속적인 표준이 되었습니다.
일반적인 사용 사례
1. HTML/CSS에 이미지 삽입
외부 이미지 파일을 참조하는 대신, Base64 인코딩된 데이터 URI를 사용하여 이미지를 직접 삽입할 수 있습니다:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." />
사용해야 할 때: 핵심 렌더링 경로에서 HTTP 요청을 절약할 수 있는 작은 아이콘이나 이미지.
피해야 할 때: 큰 이미지 — 33%의 크기 오버헤드와 이미지를 별도로 캐시할 수 없다는 단점이 장점을 능가합니다.
2. HTTP 기본 인증
HTTP Basic 인증은 Authorization 헤더에 Base64 인코딩된 문자열로 자격 증명을 전송합니다:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
이것은 Base64로 인코딩된 username:password입니다. 중요: 이것은 암호화가 아닙니다 — 쉽게 디코딩됩니다. Basic 인증 사용 시 항상 HTTPS를 함께 사용하세요.
3. JWT (JSON Web Token)
JWT 토큰은 점으로 구분된 세 개의 Base64URL 인코딩 섹션으로 구성됩니다: 헤더, 페이로드, 서명. 헤더와 페이로드는 읽을 수 있습니다(암호화되지 않음) — 여기서 Base64는 순전히 전송 인코딩 목적입니다.
4. 이메일 첨부 파일 (MIME)
Base64의 원래 사용 사례: 이메일 클라이언트는 이진 첨부 파일(이미지, PDF 등)을 Base64로 인코딩하여 이메일 인프라를 통해 안전하게 전송합니다.
5. JSON 또는 XML에 이진 데이터 저장
JSON과 XML은 텍스트만 지원하므로, 이진 데이터(암호화 키나 작은 이미지 등)는 포함 전에 종종 Base64 인코딩됩니다.
6. CSS의 데이터 URL
CSS에 배경 이미지를 인라인으로 포함할 수 있습니다:
background-image: url('data:image/svg+xml;base64,PHN2ZyB4...');
Base64 변형
| 변형 | 문자 | 사용 사례 |
|---|---|---|
| 표준 Base64 | A–Z a–z 0–9 + / | 일반 목적 |
| URL 안전 Base64 | A–Z a–z 0–9 - _ | URL, 파일명, JWT |
| 패딩 없는 Base64 | = 생략 | 일부 API에서 선호 |
| MIME Base64 | 표준 + 76자마다 줄바꿈 | 이메일 |
보안 고려 사항
Base64는 암호화가 아님
이것이 가장 중요한 점입니다: Base64는 인코딩이지 암호화가 아닙니다. Base64 문자열을 가진 누구나 즉시 디코딩할 수 있습니다 — 키가 필요 없습니다. 민감한 정보를 "숨기기" 위해 Base64를 사용하지 마세요.
echo "dXNlcm5hbWU6cGFzc3dvcmQ=" | base64 --decode
# 출력: username:password
비밀번호를 Base64로 인코딩하지 말 것
비밀번호를 Base64로 저장하는 것은 보안을 전혀 제공하지 않습니다. 대신 bcrypt, Argon2, scrypt 같은 적절한 비밀번호 해싱 알고리즘을 사용하세요.
데이터 URI와 XSS 위험
Base64 데이터 URI 자체는 안전하지만, 일부 브라우저 컨텍스트에서 악의적인 JavaScript가 data:text/html;base64,... URI를 통해 인코딩되고 실행될 수 있습니다. 대부분의 최신 브라우저는 링크 탐색과 iframe 소스에 대해 이를 제한하고 있지만, 항상 사용자가 제공한 데이터 URI를 정화(sanitize)하세요.
프로그래밍 언어에서의 Base64
JavaScript
// 인코딩
const encoded = btoa("Hello, World!"); // "SGVsbG8sIFdvcmxkIQ=="
// 디코딩
const decoded = atob("SGVsbG8sIFdvcmxkIQ=="); // "Hello, World!"
참고: btoa/atob는 브라우저에서 Latin-1 문자열에만 작동합니다. 유니코드의 경우:
// 유니코드 안전 인코딩
const encoded = btoa(unescape(encodeURIComponent("こんにちは")));
또는 Node.js에서 Buffer 사용:
Buffer.from("Hello").toString("base64");
Buffer.from("SGVsbG8=", "base64").toString("utf8");
Python
import base64
# 인코딩
encoded = base64.b64encode(b"Hello, World!").decode("utf-8")
# "SGVsbG8sIFdvcmxkIQ=="
# 디코딩
decoded = base64.b64decode("SGVsbG8sIFdvcmxkIQ==").decode("utf-8")
# "Hello, World!"
# URL 안전 변형
url_safe = base64.urlsafe_b64encode(b"Hello+World/")
성능 고려 사항
- 인코딩/디코딩은 빠름: 대부분의 사용 사례에서 Base64 오버헤드는 무시할 수 있습니다.
- 크기 오버헤드: 이진보다 약 33% 큼. 자주 전송하는 대용량 파일(MB 이상)에는 피하세요.
- CPU 캐시 압력: 메모리에서 큰 이진 파일을 인코딩하면 CPU 캐시에 압력을 줄 수 있습니다.
대용량 이진 전송의 경우, Base64보다 이진 프로토콜(이진 프레이밍이 있는 HTTP/2, WebSocket 이진 프레임, protobuf를 사용한 gRPC)을 우선하세요.
요약
Base64는 대부분의 개발자가 의식하지 못한 채 사용하는, 현대 웹의 기반이 되는 기술 중 하나입니다. 텍스트 기반 시스템에서 전송하기 위해 이진 데이터를 인쇄 가능한 텍스트로 안전하게 인코딩하는 특정 문제를 잘 해결합니다.
Base64를 사용해야 할 때: 텍스트 컨텍스트(HTML, JSON, 이메일, 헤더)에 이진 데이터를 삽입해야 할 때.
Base64를 사용하지 말아야 할 때: 데이터를 암호화하거나 보호하고 싶을 때 — Base64는 키 없이 완전히 역전될 수 있습니다.