Base64 인코딩으로 파일 크기가 33% 증가하는 이유
「Base64로 인코딩하면 파일 크기가 약 33% 증가한다」는 말을 들어본 적이 있나요? 왜 그럴까요? 이 글에서는 Base64 인코딩의 작동 원리, 파일 크기가 증가하는 수학적 이유, 그리고 개발 현장에서의 영향을 설명합니다.
Base64이란 무엇인가
Base64는 바이너리 데이터를 ASCII 문자만으로 표현하는 인코딩 방식입니다. 이메일 첨부 파일(MIME), 데이터 URI 스킴, JWT 토큰, Basic 인증 헤더 등 텍스트만 처리할 수 있는 프로토콜에서 바이너리 데이터를 송수신하기 위해 사용됩니다.
사용되는 문자는 <code>A–Z</code>(26자), <code>a–z</code>(26자), <code>0–9</code>(10자), <code>+</code>, <code>/</code> 총 64자(= Base<strong>64</strong>)와 패딩용 <code>=</code>입니다.
왜 33% 증가하나요
Base64는 <strong>3바이트의 바이너리를 4개의 ASCII 문자로 변환</strong>합니다.
- 3바이트 = 24비트
- 24비트 ÷ 6비트 = 4개의 Base64 문자 (각 문자는 6비트를 나타냄)
즉, 원본 데이터가 <strong>3바이트 → 4문자</strong>가 됩니다. 크기 비율은 <code>4 ÷ 3 ≈ 1.333...</code>이므로 <strong>약 33.3% 증가</strong>합니다.
元バイナリ: | 0x4D | 0x61 | 0x6E | ← 3バイト
01001101 01100001 01101110
↓ 6ビットずつに分割
010011 010110 000101 101110
↓ Base64文字に変換
T W F u ← 4文字(= 4バイト)
구체적인 크기 증가 계산
| 원본 파일 크기 | Base64 후의 크기 | 증가량 |
|---|---|---|
| 1 MB(1,000,000 B) | 약 1.333 MB | +333 KB |
| 10 MB | 약 13.33 MB | +3.33 MB |
| 25 MB (Gmail 한도) | 약 33.3 MB | +8.33 MB |
| 100 MB | 약 133.3 MB | +33.3 MB |
정확한 계산식은 다음과 같습니다.
import math
def base64_size(original_bytes: int) -> int:
"""Base64エンコード後のバイト数を計算"""
# 3バイトを4文字に変換、4の倍数にパディング
return math.ceil(original_bytes / 3) * 4
original = 10_000_000 # 10 MB
encoded = base64_size(original)
print(f"元: {original:,} B")
print(f"後: {encoded:,} B")
print(f"増加率: {encoded/original*100:.1f}%")
# → 元: 10,000,000 B
# → 後: 13,333,336 B
# → 増加率: 133.3%
줄 바꿈 문자로 인한 추가 증가
MIME 규격(이메일)에서는 Base64 데이터를 76문자마다 <code>\r\n</code>(CRLF)로 줄을 나누어야 합니다. 이 줄바꿈도 추가 바이트가 되어 크기가 약간 더 증가합니다.
def base64_mime_size(original_bytes: int, line_length: int = 76) -> int:
"""MIME形式(76文字改行)のBase64サイズを計算"""
b64_chars = math.ceil(original_bytes / 3) * 4
line_count = math.ceil(b64_chars / line_length)
return b64_chars + line_count * 2 # CRLF = 2バイト/行
개발에 미치는 영향
API를 통한 파일 전송
REST API를 통해 JSON 본문에 파일을 포함하여 보낼 때 Base64 인코딩이 필요합니다.
// ファイルをBase64に変換してJSONで送る
const file = document.getElementById('file').files[0];
const reader = new FileReader();
reader.onload = (e) => {
const base64 = e.target.result; // "data:image/png;base64,iVBORw0KGgo..."
fetch('/api/upload', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ file: base64, name: file.name })
});
};
이 경우 API의 요청 크기 제한은 Base64 인코딩 <em>후</em>의 크기로 판단됩니다. 10MB 파일을 전송할 때 JSON 본문이 약 13.3MB 이상이 될 수 있음을 주의하세요.
이메일 첨부 (SMTP)
SMTP 프로토콜은 ASCII 텍스트 기반이기 때문에 첨부 파일은 Base64로 인코딩됩니다. Gmail의 첨부 파일 크기 제한은 25MB이지만, 이는 인코딩 전의 파일 크기를 기준으로 합니다(Gmail이 내부 인코딩을 처리). 다만 SMTP를 통해 직접 전송하는 경우 인코딩된 크기가 제한의 대상이 되므로 주의가 필요합니다.
img 태그의 데이터 URI
<!-- Base64埋め込み画像 -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." />
HTML에 이미지를 인라인 임베드하는 경우도 이미지의 Base64 크기만큼 HTML 파일이 커집니다. 큰 이미지의 인라인 임베드는 페이지 로드 속도에 영향을 미치므로 피하는 것이 일반적입니다.
Base64를 디코드하여 원래 크기로 복원
요약
- Base64는 <strong>3바이트 → 4문자</strong>로 변환하기 때문에 크기가 <strong>약 33.3% 증가</strong>한다
- MIME 줄바꿈(76자마다)이 있으면 약간 더 증가합니다
- JSON 본문으로 파일을 전송하는 API의 경우, 요청 제한은 Base64 후 크기로 결정됩니다
- HTML 폼의 <code>multipart/form-data</code>에서는 Base64 인코딩이 불필요 (바이너리 그대로 전송)
이 기사에서 사용할 수 있는 테스트 파일
- → <a href="/ja/files/images/png/" class="text-primary-600 dark:text-primary-400 hover:underline">PNG 이미지 테스트 파일 목록</a>
- → <a href="/ja/files/pdf/" class="text-primary-600 dark:text-primary-400 hover:underline">PDF 테스트 파일 목록</a>
관련 기사
- → <a href="/ja/blog/multipart-form-data-overhead/" class="text-primary-600 dark:text-primary-400 hover:underline">multipart/form-data의 오버헤드를 정확하게 계산하기</a>
- → <a href="/ja/blog/file-format-quick-reference/" class="text-primary-600 dark:text-primary-400 hover:underline">개발자를 위한 파일 형식 빠른 참조</a>