서론: 바이너리 데이터 전송의 딜레마
웹 개발을 하다 보면 이상한 문자열을 본 적이 있을 겁니다: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA... 또는 JWT 토큰처럼 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIx... 같은 것들. 이게 바로 Base64 인코딩입니다.
인터넷 초창기, 이메일과 HTTP는 오직 텍스트(7비트 ASCII)만 전송할 수 있었습니다. 이미지, 영상, 실행 파일 같은 바이너리 데이터는 전송 중 깨지거나 시스템마다 다르게 해석되는 문제가 있었습니다. Base64는 이 문제를 해결하기 위해 만들어졌습니다.
이 글에서는 Base64가 정확히 무엇이고, 어떻게 작동하며, 왜 파일 크기가 33% 증가하는지, 그리고 현대 웹 개발에서 어떻게 활용되는지 완벽하게 이해할 수 있도록 안내합니다.
Base64란? 64개 문자로 모든 데이터를 표현
정의
Base64는 바이너리 데이터(8비트 단위)를 64개의 안전한 ASCII 문자만 사용하여 표현하는 인코딩 방식입니다. “암호화”가 아니라 “표현 방식 변환”입니다.
64개 문자 알파벳
| 인덱스 | 문자 | 범위 |
|---|---|---|
| 0-25 | A-Z | 대문자 알파벳 |
| 26-51 | a-z | 소문자 알파벳 |
| 52-61 | 0-9 | 숫자 |
| 62 | + | 플러스 |
| 63 | / | 슬래시 |
| 패딩 | = | 패딩 문자 |
왜 “64”개인가?
64 = 26이므로, 각 Base64 문자는 정확히 6비트의 정보를 담습니다. 이는 8비트 바이너리 데이터를 6비트 단위로 재배열하는 수학적 이유입니다.
작동 원리: 3바이트 → 4문자 변환의 마법
Base64의 핵심은 3바이트(24비트)를 4개의 6비트 단위로 쪼개는 것입니다.
Step-by-Step 변환 과정
예시: “Man” 문자열을 Base64로 인코딩
Step 1: 바이너리 변환
M = 01001101 (77 in ASCII)
a = 01100001 (97 in ASCII)
n = 01101110 (110 in ASCII)
연결: 01001101 01100001 01101110 (24비트)
Step 2: 6비트씩 분할
010011 | 010110 | 000101 | 101110
19 22 5 46
Step 3: Base64 알파벳으로 변환
19 → T
22 → W
5 → F
46 → u
결과: "TWFu"
시각적 다이어그램
원본 (3바이트 = 24비트):
┌────────┬────────┬────────┐
│01001101│01100001│01101110│ M a n
└────────┴────────┴────────┘
6비트씩 재배열 (4개 = 24비트):
┌──────┬──────┬──────┬──────┐
│010011│010110│000101│101110│ T W F u
└──────┴──────┴──────┴──────┘
패딩 처리: 3의 배수가 아닐 때
입력이 3의 배수가 아니면 = 문자로 패딩합니다.
예시 1: “Ma” (2바이트)
M = 01001101
a = 01100001
연결 + 0 패딩: 010011 010110 000100 (마지막 2비트는 0으로 채움)
결과: "TWE=" (4번째 문자는 2비트만 유효하므로 = 추가)
예시 2: “M” (1바이트)
M = 01001101
연결 + 0 패딩: 010011 010000 (마지막 4비트는 0으로 채움)
결과: "TQ==" (3, 4번째 문자는 패딩)
패딩 규칙 요약
| 입력 바이트 수 (mod 3) | 출력 문자 수 | 패딩 |
|---|---|---|
| 3n | 4n | 없음 |
| 3n + 1 | 4n + 2 | == |
| 3n + 2 | 4n + 3 | = |
왜 33% 크기가 증가하는가? 수학적 증명
Base64로 인코딩하면 파일 크기가 정확히 약 33% 증가합니다. 이는 수학적으로 필연적입니다.
계산 과정
- 입력: 3바이트 = 24비트
- 출력: 4문자 = 4바이트 = 32비트
- 증가율: (4 – 3) / 3 = 1/3 ≈ 33.33%
실제 예시
원본 이미지: 150,000 바이트
Base64 인코딩 후: 200,000 바이트
증가: 50,000 바이트 (33.33%)
왜 6비트 → 8비트로 확장되는가?
Base64는 6비트 정보를 8비트 ASCII 문자로 저장합니다. 각 문자마다 2비트가 낭비됩니다.
6비트 정보: 최대 64가지 값 (2^6)
8비트 저장: 최대 256가지 값 (2^8)
→ 2비트(25%)의 낭비가 발생
트레이드오프
| 장점 | 단점 |
|---|---|
| 모든 텍스트 시스템에서 안전 | 파일 크기 33% 증가 |
| 이메일, HTTP 헤더 전송 가능 | CPU 인코딩/디코딩 비용 |
| 줄바꿈, 특수문자 문제 없음 | 가독성 낮음 (사람이 읽기 어려움) |
실제 사용 사례: Base64가 필수인 곳
1. Data URI – HTML/CSS에 이미지 임베딩
외부 이미지 파일 대신 HTML에 직접 포함하여 HTTP 요청을 줄입니다.
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">
장점
- HTTP 요청 0개 (페이지 로딩 속도 향상)
- 파일 관리 불필요 (HTML 하나로 완결)
- 캐싱 정책이 HTML과 동일
단점
- HTML 크기 33% 증가
- 브라우저 캐싱 비효율 (이미지만 변경해도 HTML 전체 재다운로드)
- 10KB 이하 작은 이미지에만 권장
2. JWT (JSON Web Token) – 인증 토큰
웹 인증에서 가장 널리 사용되는 토큰 포맷입니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
구조 (점으로 구분된 3부분)
- Header:
{"alg":"HS256","typ":"JWT"}→ Base64 - Payload:
{"sub":"1234567890","name":"John Doe",...}→ Base64 - Signature: HMAC-SHA256 서명 → Base64
왜 Base64를 사용하는가?
- URL에 안전하게 포함 (쿠키, Query String)
- HTTP 헤더에 전송 가능 (
Authorization: Bearer {token}) - JSON 구조를 평문처럼 전송 (암호화 아님, 서명만 있음)
3. 이메일 첨부파일 – MIME
이메일 시스템(SMTP)은 7비트 ASCII만 지원하므로, 첨부파일은 Base64로 인코딩됩니다.
Content-Type: application/pdf; name="report.pdf"
Content-Transfer-Encoding: base64
JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVu
Z3RoIDQ5Nj4+CnN0cmVhbQp4nJ1WTY/bNhC9+1cM2ksXECVSX+u1sUkXbbsF2l0U...
4. HTTP Basic Authentication
가장 단순한 HTTP 인증 방식입니다.
사용자명: admin
비밀번호: secret123
결합: admin:secret123
Base64: YWRtaW46c2VjcmV0MTIz
HTTP 헤더:
Authorization: Basic YWRtaW46c2VjcmV0MTIz
⚠️ 주의: Base64는 암호화가 아닙니다! 누구나 디코딩 가능하므로 HTTPS 없이는 절대 사용 금지.
5. CSS 파일에 폰트 임베딩
@font-face {
font-family: 'CustomFont';
src: url(data:font/woff2;base64,d09GMgABAAAAAAO4AA0A...) format('woff2');
}
외부 폰트 파일 로딩 없이 CSS에 직접 포함하여 FOUT(Flash of Unstyled Text)를 방지합니다.
6. Canvas toDataURL() – 이미지 다운로드
const canvas = document.getElementById('myCanvas');
const dataURL = canvas.toDataURL('image/png');
// data:image/png;base64,iVBORw0KG...
// 다운로드 링크 생성
const link = document.createElement('a');
link.download = 'canvas-image.png';
link.href = dataURL;
link.click();
Base64 vs URL-safe Base64 – 차이점과 용도
표준 Base64는 URL과 파일명에 안전하지 않은 문자(+, /)를 포함합니다. 이를 해결한 변형이 URL-safe Base64입니다.
문자 대체 규칙
| 위치 | 표준 Base64 | URL-safe Base64 |
|---|---|---|
| 62번째 문자 | + | – (하이픈) |
| 63번째 문자 | / | _ (언더스코어) |
| 패딩 | = | 생략 (선택적) |
변환 예시
원본 데이터: "subjects"
표준 Base64: c3ViamVjdHM=
URL-safe Base64: c3ViamVjdHM (패딩 제거)
원본 데이터: "???"
표준 Base64: Pz8/
URL-safe Base64: Pz8_
언제 어떤 것을 사용하는가?
| 상황 | 사용 포맷 |
|---|---|
| 이메일 첨부파일 | 표준 Base64 |
| Data URI (HTML/CSS) | 표준 Base64 |
| JWT 토큰 | URL-safe Base64 (패딩 제거) |
| URL Query String | URL-safe Base64 |
| 파일명에 포함 | URL-safe Base64 |
프로그래밍 언어별 지원
// JavaScript (표준 Base64)
btoa("Man") // "TWFu"
atob("TWFu") // "Man"
// JavaScript (URL-safe Base64) - 수동 변환 필요
function base64UrlEncode(str) {
return btoa(str)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
// Python
import base64
base64.b64encode(b"Man") # b'TWFu'
base64.urlsafe_b64encode(b"Man") # URL-safe 버전
Base64 사용 시 주의사항과 모범 사례
❌ Base64를 사용하면 안 되는 경우
- 큰 파일 전송: 1MB 이상 이미지/동영상은 별도 파일로 제공 (HTTP/2 멀티플렉싱 사용)
- 보안이 필요한 경우: Base64는 암호화가 아님! 누구나 디코딩 가능
- SEO 중요한 이미지: Data URI는 검색엔진이 인덱싱 불가
- 자주 변경되는 리소스: HTML 전체를 재다운로드하게 만듦
✅ Base64가 효과적인 경우
- 작은 아이콘/로고: 5-10KB 이하, HTTP 요청 절감 효과
- 인라인 SVG 대신: 복잡한 SVG보다 작은 PNG Base64가 나을 때
- 이메일 템플릿: 외부 이미지 차단 우회
- 토큰/인증 정보: URL에 안전하게 전달 필요 시
성능 최적화 팁
/* ❌ 나쁜 예: 큰 이미지를 Data URI로 */
.hero {
background: url(data:image/jpeg;base64,/9j/4AAQ...[200KB]...);
}
/* ✅ 좋은 예: 작은 아이콘만 Data URI */
.icon-check {
background: url(data:image/svg+xml;base64,PHN2Zy...[2KB]...);
}
/* ✅ 더 좋은 예: HTTP/2 사용 시 별도 파일 */
.icon-check {
background: url(/icons/check.svg);
}
/* HTTP/2는 멀티플렉싱으로 여러 파일 동시 로드 */
보안 주의사항
- 절대 암호화로 착각 금지: 비밀번호를 Base64로만 전송하면 평문과 동일
- HTTPS 필수: HTTP Basic Auth, JWT는 반드시 HTTPS 위에서만 사용
- 민감 정보 로깅 주의: Base64 토큰도 디코딩하면 정보 노출
결론: Base64는 호환성의 다리
Base64는 40년 전 설계되었지만 여전히 현대 웹의 핵심 기술입니다. 바이너리 데이터를 텍스트 시스템에서 안전하게 다룰 수 있게 해주는 “호환성의 다리” 역할을 합니다.
핵심 요약
- 원리: 3바이트 → 4문자 변환 (6비트씩 재배열)
- 크기: 항상 33% 증가 (수학적 필연)
- 용도: Data URI, JWT, 이메일, HTTP Auth
- 변형: URL-safe Base64는 JWT, URL에 사용
- 주의: 암호화 아님! 작은 파일에만 사용
선택 가이드
| 목적 | 권장 방법 |
|---|---|
| 작은 아이콘 임베딩 (<10KB) | Data URI (Base64) |
| 큰 이미지 전송 | 별도 파일 + HTTP/2 |
| 인증 토큰 | JWT (URL-safe Base64) |
| 이메일 첨부 | MIME (표준 Base64) |
| 민감 정보 전송 | 암호화 + Base64 (순서 중요!) |
Base64는 도구일 뿐 만능 해결책이 아닙니다. 상황에 맞게 올바르게 사용하면 강력하지만, 남용하면 성능 저하의 원인이 됩니다. “언제 사용할 것인가”보다 “언제 사용하지 말아야 하는가”를 아는 것이 더 중요합니다.
ToolZipper로 직접 해보기
Base64 인코딩을 직접 실습하며 이해를 깊게 만드세요. ToolZipper는 100% 무료, 브라우저에서 바로 사용 가능합니다.