긴 문자열과 숫자가 ==로 끝나는 것을 보고 그것이 무엇인지 궁금해합니다. JWT를 도구에 붙여넣으면 중간 부분이 대부분 읽을 수 있습니다. HTML 이메일에 이미지를 삽입하면 src 속성이 문자로 가득 차 있습니다. PDF를 API에 업로드하면 문서에 'Base64로 보내십시오'라고 나와 있습니다. 모두 동일한 인코딩이며, 대부분의 개발자는 실제로 무엇을 하는지 제대로 이해하지 못한 채 사용합니다.
이 가이드는 Base64가 실제로 무엇인지, 언제 사용해야 하는지, 일반적인 실수(가장 큰 실수인 암호화로 착각하는 것을 포함), URL 안전 변형, 패딩 규칙, 그리고 모든 주요 언어에서 인코딩 및 디코딩하는 방법을 다룹니다.
Base64가 실제로 무엇인가
Base64는 64개의 특정 문자를 사용하여 이진 데이터를 ASCII 텍스트로 변환하는 인코딩입니다: A-Z, a-z,0-9, + 및 /이(가) 추가됩니다. = 문자는 끝에 패딩하는 데 사용됩니다. 입력의 3바이트마다 정확히 4개의 Base64 문자가 출력되므로, Base64는 데이터 크기를 약 33% 증가시킵니다.
Input bytes: "Hi" (2 bytes: 0x48 0x69)
Binary: 01001000 01101001
Group in 6s: 010010 000110 1001(00) ← last group padded with zeros
Base64 chars: S G k = ← '=' = padding
Result: "SGk="
수학: 64개의 문자는 각 문자가 6비트를 나타냄을 의미합니다. 6비트(하나의 Base64 문자)와 8비트(1바이트)의 최소공배수는 24비트이며, 이는 3바이트 또는 4개의 Base64 문자에 해당합니다. 이것이 Base64가 항상 4개의 출력 문자 그룹으로 작동하고 패딩이 존재하는 이유입니다.
가장 큰 오해: Base64는 암호화가 아닙니다.
이것은 개발자와 비개발자 모두를 사로잡습니다. Base64는 횡설수설처럼 보이기 때문에 비밀처럼 느껴집니다. 하지만 그렇지 않습니다. 누구나 Base64를 즉시 디코딩할 수 있습니다. 키, 비밀번호, 크랙할 알고리즘도 없습니다. 이는 투명한 변환으로, 다른 알파벳으로 쓰는 것과 같습니다.
// "Encrypted" password?
"cGFzc3dvcmQxMjM="
// Decoded in one line
atob("cGFzc3dvcmQxMjM=")
// → "password123"
Base64는 인코딩이지 암호화가 아닙니다. 그것을 사용하여 운송하다 데이터를 텍스트 전용 채널을 통해 안전하게 전송 — 숨기다 데이터에 절대 사용하지 마세요. 기밀성이 필요하다면 실제 암호화를 사용하세요: 전송 중인 데이터에 AES, NaCl/libsodium 또는 TLS.
Base64 사용 시기
Base64는 텍스트를 예상하는 시스템을 통해 바이너리 데이터를 이동하기 위해 존재합니다. 가장 일반적인 경우:
JSON 또는 XML에 바이너리 포함 — 어느 형식도 원시 바이트를 지원하지 않습니다. JSON 페이로드의 일부로 파일 업로드를 허용하는 API는 파일을 나타내기 위해 Base64를 사용합니다.
데이터 URL(Data URLs) — data:image/png;base64,iVBORw0KGgo...는 별도의 HTTP 요청 없이 이미지를 인라인으로 삽입할 수 있습니다. 작은 아이콘과 이메일 서명에 유용합니다.
HTTP 기본 인증(HTTP Basic Auth) — Authorization 헤더는 자격 증명을 다음으로 보냅니다.Basic <base64-of-username:password>. 이것은 Base64가 암호화가 아닌 이유에 대한 완벽한 예이기도 합니다. Basic Auth는 HTTPS와 함께 사용될 때만 안전합니다.
JWT — JSON Web Token은 점으로 구분된 세 개의 Base64URL 인코딩 섹션으로 구성됩니다. 헤더와 페이로드는 읽을 수 있는 JSON이며, 서명만 불투명합니다.
이메일 첨부 파일 — SMTP는 기술적으로 7비트 텍스트 프로토콜이므로 MIME 표준 이후로 첨부 파일은 기본적으로 Base64로 인코딩됩니다.
암호화 키 및 인증서 — PEM 파일(-----BEGIN CERTIFICATE----- 블록)은 Base64로 인코딩된 바이너리 키를 래핑합니다.
패딩 — 일부 Base64가 =로 끝나는 이유와 그렇지 않은 이유
그= Base64 문자열의 끝에 있는 것은 패딩입니다. 이는 Base64가 3개의 입력 바이트 단위로 작동하며, 모든 입력이 3바이트의 배수가 아니기 때문입니다. 입력이 1 또는 2바이트 부족할 경우, 인코더는 출력을 = 문자로 패딩하여 결과가 항상 4문자의 배수가 되도록 합니다.
Input length (mod 3) Padding Example
─────────────────────────────────────────
0 (multiple of 3) none "Man" → "TWFu"
1 == "M" → "TQ=="
2 = "Ma" → "TWE="
일부 인코더와 프로토콜은 바이트를 절약하기 위해 패딩을 제거합니다. JWT가 그렇습니다. JWT 내부의 Base64URL 인코딩에는 패딩이 전혀 없습니다. JWT에서 Base64를 수동으로 디코딩하는 경우 일부 디코더가 이를 받아들이기 전에 패딩을 다시 추가해야 할 수 있습니다.
// JavaScript: add padding back to an unpadded Base64 string
function pad(b64) {
const remainder = b64.length % 4;
return remainder ? b64 + '='.repeat(4 - remainder) : b64;
}
Base64와 Base64URL 비교 — 웹에서 중요한 변형
표준 Base64는 62번째와 63번째 문자로 +와 /를 사용합니다. 둘 다 URL에서 특별한 의미를 가집니다: +는 쿼리 문자열에서 "공백"을 의미하고, /는 경로 구분자입니다. 표준 Base64를 추가 인코딩 없이 URL에 넣으면 문제가 발생합니다.
Base64URL(RFC 4648에 정의됨)은 이러한 문자를 교체하여 이 문제를 해결합니다: +이(가)- 및 /는 _이 됩니다. 또한 일반적으로 패딩을 생략합니다. 결과는 URL, 파일 이름 및 HTTP 헤더에 직접 넣어도 안전합니다.
Standard Base64: "abc/d+ef=="
Base64URL: "abc_d-ef"
// Convert one to the other
const toUrlSafe = (b64) => b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const fromUrlSafe = (b64u) => {
const b64 = b64u.replace(/-/g, '+').replace(/_/g, '/');
return pad(b64); // add padding back
};
JWT는 Base64URL을 사용합니다. 대부분의 최신 토큰 형식, OAuth 상태 매개변수 및 URL로 전송되는 다른 모든 것들도 마찬가지입니다.
JavaScript에서의 인코딩 및 디코딩
JavaScript에는 두 개의 내장 함수가 있습니다.btoa()(2진수-ASCII 변환, 인코딩) 및atob()(ASCII-to-binary, decode). 이름들이 혼란스럽습니다 — 임의의 이진 데이터에 대해 예상한 대로 작동하지 않습니다.
// Simple ASCII strings — these work
btoa("Hello, world!");
// → "SGVsbG8sIHdvcmxkIQ=="
atob("SGVsbG8sIHdvcmxkIQ==");
// → "Hello, world!"
// Unicode strings — this BREAKS
btoa("héllo");
// → DOMException: invalid character
// Correct way for Unicode: encode to UTF-8 first
function utf8ToBase64(str) {
return btoa(unescape(encodeURIComponent(str)));
}
function base64ToUtf8(b64) {
return decodeURIComponent(escape(atob(b64)));
}
utf8ToBase64("héllo"); // → "aMOpbGxv"
base64ToUtf8("aMOpbGxv"); // → "héllo"
// Modern alternative (Node 16+, modern browsers)
const bytes = new TextEncoder().encode("héllo");
const b64 = btoa(String.fromCharCode(...bytes));
파일 업로드와 같은 이진 데이터의 경우, 작업하세요.ArrayBuffer또는Uint8Array:":
// Convert a file to Base64 (browser)
async function fileToBase64(file) {
const buffer = await file.arrayBuffer();
const bytes = new Uint8Array(buffer);
let binary = '';
for (const byte of bytes) binary += String.fromCharCode(byte);
return btoa(binary);
}
// FileReader alternative — gives you a data URL
function fileToDataUrl(file) {
return new Promise(resolve => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.readAsDataURL(file);
});
}
Python에서 인코딩 및 디코딩
import base64
# Encode a string
encoded = base64.b64encode(b"Hello, world!")
# → b"SGVsbG8sIHdvcmxkIQ=="
# Decode
decoded = base64.b64decode(b"SGVsbG8sIHdvcmxkIQ==")
# → b"Hello, world!"
# URL-safe variant — for JWTs, URLs, filenames
url_safe = base64.urlsafe_b64encode(b"data with /and+chars")
# → b"ZGF0YSB3aXRoIC9hbmQrY2hhcnM="
# Encode a file
with open("photo.jpg", "rb") as f:
encoded_file = base64.b64encode(f.read()).decode("ascii")
명령줄에서 인코딩 및 디코딩
# macOS and Linux — encode
echo -n "Hello, world!" | base64
# → SGVsbG8sIHdvcmxkIQ==
# Decode
echo "SGVsbG8sIHdvcmxkIQ==" | base64 -d
# → Hello, world!
# Encode a file
base64 photo.jpg > photo.txt
# Decode a file
base64 -d photo.txt > photo.jpg
# Watch out — many systems wrap output at 76 characters by default
# Use -w 0 (GNU) or no flag (BSD) to disable wrapping
echo -n "long content..." | base64 -w 0
SQL에서 인코딩 및 디코딩
-- PostgreSQL
SELECT encode('Hello, world!'::bytea, 'base64');
-- → SGVsbG8sIHdvcmxkIQ==
SELECT convert_from(decode('SGVsbG8sIHdvcmxkIQ==', 'base64'), 'UTF8');
-- → Hello, world!
-- MySQL 8+
SELECT TO_BASE64('Hello, world!');
-- → SGVsbG8sIHdvcmxkIQ==
SELECT FROM_BASE64('SGVsbG8sIHdvcmxkIQ==');
-- → Hello, world!
일반적인 버그와 이를 방지하는 방법
줄 바꿈 함정. 일부 구현체(특히 MIME 및 OpenSSL)는 Base64 출력을 64자 또는 76자마다 줄 바꿈으로 감쌉니다. 다른 구현체는 줄 바꿈이 포함된 입력을 거부합니다. 유효한 Base64처럼 보이는 문자열을 디코딩할 때 "잘못된 문자" 오류가 발생하면 먼저 공백을 제거하십시오.
패딩 불일치. JWT와 URL-safe Base64는 일반적으로 패딩을 생략합니다. 많은 디코더가 패딩을 필요로 합니다. 디코딩이 실패하면, 몇 개의 = 문자를 추가해야 하는지 계산하십시오: (4 - (length % 4)) % 4 그 중에서.
UTF-8 가정. Base64는 바이트를 인코딩하며, 문자를 인코딩하지 않습니다. 문자열을 인코딩하려면 해당 문자열이 어떤 문자 인코딩을 사용하는지 알아야 합니다. 항상 인코딩을 명시적으로 지정하고(UTF-8이 거의 항상 올바른 답입니다), 결과를 문자열로 처리하기 전에 다시 바이트로 디코딩하십시오.
크기의 놀라움. Base64는 페이로드 크기를 33% 증가시킵니다. 작은 자산의 경우 문제되지 않지만, JSON에 포함된 10MB 파일의 경우 와이어를 통해 13.3MB를 전송하게 됩니다. 더 큰 파일의 경우 멀티파트 업로드를 선호하십시오.
이것을 비밀로 취급하십시오. 두 번 말할 가치가 있습니다: Base64는 암호화가 아닙니다. 비밀번호, API 키 또는 기타 민감한 데이터를 Base64로 저장하여 숨겨질 것이라고 기대하지 마세요. 인코딩된 문자열을 볼 수 있다면 원본도 볼 수 있습니다.
저는 DevCrate를 개발한 William입니다. Base64 도구는는 의심스러운 온라인 변환기에 무작위 문자열을 넣어 안에 무엇이 있는지 확인하는 것에 지쳐서 만들어졌습니다. 이것은 표준 및 URL-safe 변형을 인코딩 및 디코딩하고, 파일을 처리하며, 사용자 컴퓨터에서 단 하나의 바이트도 보내지 않습니다.
이 가이드에서 다루지 않은 Base64 사례가 있다면 댓글에 남겨주세요. 모든 댓글을 읽습니다.












