Base64란 무엇인가? — 바이너리를 텍스트로 변환하는 기술
개발을 하다 보면 이메일 첨부파일, 웹 페이지의 인라인 이미지, JWT 토큰, API 인증 헤더 등에서 SGVsbG8gV29ybGQ=처럼 알 수 없는 문자열을 자주 마주칩니다. 이것이 바로 Base64 인코딩입니다.
Base64는 바이너리(Binary) 데이터를 64개의 ASCII 문자만으로 표현하는 인코딩 방식입니다. 64개의 문자란 영문 대문자(A-Z, 26개), 영문 소문자(a-z, 26개), 숫자(0-9, 10개), 그리고 특수문자 +와 /(2개)를 합친 것입니다. 여기에 패딩 문자 =를 추가로 사용합니다.
Base64가 필요한 이유는 역사적 배경에 있습니다. 이메일 프로토콜(SMTP), HTTP 헤더, XML, JSON 같은 텍스트 기반 시스템들은 원래 순수한 텍스트 데이터만 처리하도록 설계되었습니다. 이미지, 오디오, 바이너리 파일처럼 8비트 데이터를 그대로 전송하면 중간 시스템에서 데이터가 손상될 수 있습니다. Base64는 이 문제를 해결하기 위해 탄생했습니다.
HMApps Base64 인코더/디코더는 복잡한 인코딩/디코딩 작업을 브라우저에서 즉시 처리해주는 무료 도구입니다. 서버로 데이터를 전송하지 않아 보안이 중요한 데이터도 안전하게 처리할 수 있습니다.
Base64 인코딩 원리 — 3바이트를 4문자로
Base64의 핵심 원리는 3바이트(24비트)를 4개의 6비트 그룹으로 분할하고, 각 그룹을 64개의 문자 중 하나로 매핑하는 것입니다. 결과적으로 데이터 크기가 원본보다 약 33% 증가합니다.
단계별 인코딩 과정 예시
Man이라는 세 글자를 Base64로 인코딩해 보겠습니다.
- ASCII 바이트로 변환: M = 77 (0x4D), a = 97 (0x61), n = 110 (0x6E)
- 2진수로 표현:
01001101 01100001 01101110 (24비트) - 6비트씩 4그룹으로 분할:
010011 010110 000101 101110 - 10진수로 변환: 19, 22, 5, 46
- Base64 문자표 매핑: T, W, F, u
결과: Man → TWFu
패딩(=) 처리
3바이트 단위로 처리하기 때문에 원본 데이터가 3의 배수가 아니면 = 패딩 문자로 채웁니다.
| 원본 바이트 수 | 패딩 = 개수 | 예시 |
|---|
| 3의 배수 (예: 3, 6, 9...) | 0개 | Man → TWFu |
| 3의 배수 + 1 (예: 1, 4, 7...) | 2개 | M → TQ== |
| 3의 배수 + 2 (예: 2, 5, 8...) | 1개 | Ma → TWE= |
자주 보이는 Base64 문자열 패턴
- 끝에
==가 붙으면 원본 바이트 수가 3의 배수 + 1 - 끝에
=가 하나 붙으면 원본 바이트 수가 3의 배수 + 2 - 패딩이 없으면 원본 바이트 수가 정확히 3의 배수
- 문자열 길이는 항상 4의 배수
HMApps Base64 인코더/디코더 사용법
HMApps Base64 인코더/디코더는 누구나 직관적으로 사용할 수 있습니다.
텍스트 인코딩
- hmapps.kr/base64에 접속합니다.
- 입력창에 인코딩할 텍스트를 입력합니다. 한글, 영문, 특수문자 모두 가능합니다.
- 인코딩 버튼을 클릭하거나 실시간 모드에서는 입력 즉시 결과가 나타납니다.
- 결과창의 복사 버튼으로 인코딩된 문자열을 클립보드에 저장합니다.
Base64 디코딩
- 입력창에
SGVsbG8gV29ybGQ= 같은 Base64 문자열을 붙여넣습니다. - 디코딩 버튼을 클릭합니다.
- 결과창에 원본 텍스트(
Hello World)가 나타납니다.
한글 처리
한글을 Base64로 인코딩할 때는 내부적으로 UTF-8 인코딩을 거칩니다. 한글 한 글자는 UTF-8에서 3바이트이므로, 두 글자('안녕')는 6바이트 → 8개의 Base64 문자가 됩니다.
안녕 → (UTF-8: EC 95 88 EB 85 95) → 7J2I65WV
실전 활용 사례 — 현업에서 Base64가 사용되는 곳
사례 1: 이미지 Data URI (인라인 이미지)
웹 페이지에서 HTTP 요청 없이 이미지를 직접 HTML이나 CSS에 포함시킬 때 Base64를 사용합니다. 작은 아이콘이나 로딩 플레이스홀더에 특히 유용합니다.
<!-- HTML 인라인 이미지 -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." alt="아이콘">
/* CSS 배경 이미지 */
.icon {
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...');
}
장점: HTTP 요청 수 감소, 소규모 이미지의 로딩 속도 향상
단점: 33% 용량 증가, 캐싱 불가 — 10KB 이상의 이미지에는 비권장
사례 2: JWT 토큰 구조 분석
JWT(JSON Web Token)는 세 부분이 .으로 구분되며, 각 부분이 Base64Url로 인코딩되어 있습니다. HMApps JWT 디코더와 함께 사용하면 토큰 내용을 즉시 확인할 수 있습니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6Iu2Zjeym...
-- Base64 디코딩 --
헤더: {"alg":"HS256","typ":"JWT"}
페이로드: {"sub":"user123","name":"홍길동","role":"admin","iat":1720000000}
주의: JWT의 Base64는 Base64Url 변형으로, +→-, /→_, 패딩 = 생략이 특징입니다. HMApps Base64 디코더는 두 형식을 모두 지원합니다.
사례 3: HTTP Basic 인증 헤더
HTTP Basic Authentication은 사용자명과 비밀번호를 username:password 형식으로 Base64 인코딩하여 Authorization 헤더에 포함합니다.
# 인코딩 과정
"admin:P@ssw0rd123" → "YWRtaW46UEBzc3cwcmQxMjM="
# HTTP 요청 헤더
Authorization: Basic YWRtaW46UEBzc3cwcmQxMjM=
중요: Basic 인증의 Base64는 암호화가 아닙니다. 누구나 디코딩할 수 있으므로 반드시 HTTPS와 함께 사용해야 합니다. HMApps Base64 디코더로 어떤 정보가 노출되는지 직접 확인해보세요.
사례 4: 이메일 첨부파일 (MIME)
이메일 프로토콜(SMTP)은 텍스트만 전송할 수 있도록 설계되었습니다. PDF, 이미지, 엑셀 파일 같은 바이너리 첨부파일은 MIME 규격에 따라 Base64로 인코딩되어 전송됩니다. 이메일 원문(raw source)을 보면 아래와 같은 구조를 볼 수 있습니다:
Content-Type: application/pdf; name="report.pdf"
Content-Transfer-Encoding: base64
JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwKL0xlbmd0aCAzIDAgUgo...
사례 5: API 응답의 바이너리 데이터
일부 REST API는 이미지, 인증서, 암호화 키 등 바이너리 데이터를 JSON 응답에 포함시킬 때 Base64를 사용합니다. JSON은 순수 텍스트 형식이라 바이너리를 직접 담을 수 없기 때문입니다.
{
"user_id": "123",
"avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAA...",
"certificate": "MIICpDCCAYwCCQDU..."
}
Base64 vs 다른 인코딩 비교 — 언제 무엇을 써야 하나
| 인코딩 방식 | 목적 | 크기 변화 | 주요 사용처 |
|---|
| Base64 | 바이너리 → 텍스트 변환 | +33% | 이메일 첨부, JWT, Data URI, API 바이너리 전송 |
| URL 인코딩 | URL 안전 문자열 변환 | +100~200% (한글) | URL 파라미터, HTTP 폼 데이터 |
| HTML 인코딩 | HTML 특수문자 이스케이프 | 미미한 증가 | HTML 문서 내 텍스트, XSS 방지 |
| Hash (SHA, MD5) | 단방향 다이제스트 생성 | 고정 길이 출력 | 비밀번호 저장, 무결성 검증 |
| 암호화 (AES, RSA) | 데이터 기밀화 | 다양 | 민감 데이터 보호 |
자주 혼동하는 질문: Base64는 암호화인가요?
아닙니다. Base64는 인코딩이지 암호화가 아닙니다. 비밀 키 없이 누구나 디코딩할 수 있습니다. 데이터를 숨기거나 보호하는 용도라면 AES, RSA 같은 암호화 알고리즘을 사용해야 합니다. Base64는 단순히 바이너리 데이터를 텍스트로 표현하는 형식 변환 수단입니다.
프로그래밍 언어별 Base64 코드 — 복사해서 바로 사용하기
JavaScript / TypeScript
// 브라우저 환경
const encoded = btoa('Hello World') // "SGVsbG8gV29ybGQ="
const decoded = atob('SGVsbG8gV29ybGQ=') // "Hello World"
// 한글(UTF-8) 인코딩 — btoa()는 ASCII만 지원하므로 변환 필요
const text = '안녕하세요'
const encodedKorean = btoa(unescape(encodeURIComponent(text)))
const decodedKorean = decodeURIComponent(escape(atob(encodedKorean)))
// Node.js 환경
const encoded = Buffer.from('Hello World').toString('base64')
const decoded = Buffer.from('SGVsbG8gV29ybGQ=', 'base64').toString('utf-8')
// Base64Url (JWT용) — + → -, / → _, = 제거
const base64url = encoded.replace(/+/g, '-').replace(///g, '_').replace(/=/g, '')
Python
import base64
# 인코딩
text = "안녕하세요"
encoded = base64.b64encode(text.encode('utf-8')).decode('ascii')
print(encoded) # 7J2I66eI7ZWY7JWI7Jyg
# 디코딩
decoded = base64.b64decode(encoded).decode('utf-8')
print(decoded) # 안녕하세요
# Base64Url (URL-safe)
encoded_url = base64.urlsafe_b64encode(text.encode('utf-8')).decode('ascii')
decoded_url = base64.urlsafe_b64decode(encoded_url + '==').decode('utf-8')
Java
import java.util.Base64;
import java.nio.charset.StandardCharsets;
// 인코딩
String text = "안녕하세요";
String encoded = Base64.getEncoder().encodeToString(
text.getBytes(StandardCharsets.UTF_8)
);
// 디코딩
byte[] decodedBytes = Base64.getDecoder().decode(encoded);
String decoded = new String(decodedBytes, StandardCharsets.UTF_8);
// URL-safe Base64 (JWT용)
String encodedUrl = Base64.getUrlEncoder().withoutPadding().encodeToString(
text.getBytes(StandardCharsets.UTF_8)
);
Go
import (
"encoding/base64"
"fmt"
)
// 인코딩
text := "안녕하세요"
encoded := base64.StdEncoding.EncodeToString([]byte(text))
fmt.Println(encoded)
// 디코딩
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
panic(err)
}
fmt.Println(string(decoded))
자주 발생하는 Base64 실수와 해결법
실수 1: 패딩 오류 (Invalid padding)
Base64 문자열의 길이는 반드시 4의 배수여야 합니다. 전송 과정에서 = 패딩이 잘리거나, Base64Url에서 패딩을 제거한 문자열을 표준 Base64 디코더로 처리하면 오류가 발생합니다.
// 패딩이 없는 Base64Url 문자열을 표준 디코더로 처리할 때
const base64url = 'SGVsbG8' // 패딩 없음
// 해결법: 길이에 따라 패딩 추가
function addPadding(base64url) {
const pad = base64url.length % 4
if (pad === 2) return base64url + '=='
if (pad === 3) return base64url + '='
return base64url
}
const standard = addPadding(base64url).replace(/-/g, '+').replace(/_/g, '/')
atob(standard) // "Hello"
실수 2: 한글 인코딩 오류
브라우저의 btoa()는 Latin-1(ISO-8859-1) 범위 문자만 처리합니다. 한글 같은 멀티바이트 문자를 직접 btoa()에 넣으면 InvalidCharacterError가 발생합니다. HMApps Base64 도구는 UTF-8 변환을 자동으로 처리합니다.
실수 3: Base64와 URL 인코딩 혼용
Base64 문자열을 URL 파라미터로 전달할 때, +와 /와 = 문자가 URL에서 특별한 의미를 가집니다. 이 경우 Base64 결과를 추가로 URL 인코딩하거나, 처음부터 Base64Url 형식을 사용해야 합니다.
// 잘못된 방법 — + 가 공백으로 해석될 수 있음
const url = `https://api.example.com/data?token=${base64encoded}`
// 올바른 방법 1 — URL 인코딩 추가
const url = `https://api.example.com/data?token=${encodeURIComponent(base64encoded)}`
// 올바른 방법 2 — Base64Url 사용
const base64url = base64encoded.replace(/+/g, '-').replace(///g, '_').replace(/=/g, '')
const url = `https://api.example.com/data?token=${base64url}`
실수 4: 큰 파일 인코딩
Base64는 데이터 크기를 33% 증가시킵니다. 대용량 파일(수 MB 이상)을 Base64로 인코딩해서 전송하는 것은 네트워크 대역폭과 메모리 측면에서 매우 비효율적입니다. 이런 경우에는 multipart/form-data 방식으로 파일을 직접 전송하는 것이 훨씬 효율적입니다.
마무리 — Base64를 내 것으로 만들기
Base64는 현대 웹 개발 어디에나 존재하는 핵심 기술입니다. JWT 인증, 이미지 처리, API 설계, 이메일 시스템 모두 Base64를 기반으로 동작합니다. 원리를 제대로 이해하면 디버깅 시간을 크게 줄이고 더 안전한 시스템을 설계할 수 있습니다.
오늘 기억할 핵심 4가지:
- Base64는 암호화가 아닙니다 — 누구나 디코딩 가능합니다.
- 3바이트 → 4문자 변환으로 데이터 크기가 33% 증가합니다.
- URL에서 사용할 때는
+, /, =를 처리하는 Base64Url을 쓰세요. - 한글 인코딩 시 UTF-8 변환을 먼저 처리해야 오류가 없습니다.
HMApps Base64 인코더/디코더를 활용하면 이 모든 복잡한 처리를 클릭 한 번으로 해결할 수 있습니다. 관련 도구로 URL 인코더, HTML 인코더, Hash 생성기, JWT 디코더도 함께 북마크해 두세요. 웹 개발 생산성이 한 단계 올라갈 것입니다.