Base64 인코딩: 왜 사용하고 어떻게 작동하는가

서론: 바이너리 데이터 전송의 딜레마

웹 개발을 하다 보면 이상한 문자열을 본 적이 있을 겁니다: 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% 증가합니다. 이는 수학적으로 필연적입니다.

계산 과정

  1. 입력: 3바이트 = 24비트
  2. 출력: 4문자 = 4바이트 = 32비트
  3. 증가율: (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부분)

  1. Header: {"alg":"HS256","typ":"JWT"} → Base64
  2. Payload: {"sub":"1234567890","name":"John Doe",...} → Base64
  3. 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를 사용하면 안 되는 경우

  1. 큰 파일 전송: 1MB 이상 이미지/동영상은 별도 파일로 제공 (HTTP/2 멀티플렉싱 사용)
  2. 보안이 필요한 경우: Base64는 암호화가 아님! 누구나 디코딩 가능
  3. SEO 중요한 이미지: Data URI는 검색엔진이 인덱싱 불가
  4. 자주 변경되는 리소스: HTML 전체를 재다운로드하게 만듦

✅ Base64가 효과적인 경우

  1. 작은 아이콘/로고: 5-10KB 이하, HTTP 요청 절감 효과
  2. 인라인 SVG 대신: 복잡한 SVG보다 작은 PNG Base64가 나을 때
  3. 이메일 템플릿: 외부 이미지 차단 우회
  4. 토큰/인증 정보: 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는 멀티플렉싱으로 여러 파일 동시 로드 */

보안 주의사항

  1. 절대 암호화로 착각 금지: 비밀번호를 Base64로만 전송하면 평문과 동일
  2. HTTPS 필수: HTTP Basic Auth, JWT는 반드시 HTTPS 위에서만 사용
  3. 민감 정보 로깅 주의: Base64 토큰도 디코딩하면 정보 노출

결론: Base64는 호환성의 다리

Base64는 40년 전 설계되었지만 여전히 현대 웹의 핵심 기술입니다. 바이너리 데이터를 텍스트 시스템에서 안전하게 다룰 수 있게 해주는 “호환성의 다리” 역할을 합니다.

핵심 요약

  1. 원리: 3바이트 → 4문자 변환 (6비트씩 재배열)
  2. 크기: 항상 33% 증가 (수학적 필연)
  3. 용도: Data URI, JWT, 이메일, HTTP Auth
  4. 변형: URL-safe Base64는 JWT, URL에 사용
  5. 주의: 암호화 아님! 작은 파일에만 사용

선택 가이드

목적 권장 방법
작은 아이콘 임베딩 (<10KB) Data URI (Base64)
큰 이미지 전송 별도 파일 + HTTP/2
인증 토큰 JWT (URL-safe Base64)
이메일 첨부 MIME (표준 Base64)
민감 정보 전송 암호화 + Base64 (순서 중요!)

Base64는 도구일 뿐 만능 해결책이 아닙니다. 상황에 맞게 올바르게 사용하면 강력하지만, 남용하면 성능 저하의 원인이 됩니다. “언제 사용할 것인가”보다 “언제 사용하지 말아야 하는가”를 아는 것이 더 중요합니다.

ToolZipper로 직접 해보기

Base64 인코딩을 직접 실습하며 이해를 깊게 만드세요. ToolZipper는 100% 무료, 브라우저에서 바로 사용 가능합니다.

문의하기