Base64를 본 적이 있을 것입니다 — SGVsbG8gV29ybGQ=같은 길고 이상한 문자열 말이죠. 이메일, 데이터 URI, API 페이로드, JWT에서 나타납니다. 하지만 Base64가 정확히 무엇이고, 언제 사용해야 할까요? 함께 알아봅시다.
Base64가 하는 일 (쉽게 설명)
Base64는 어떤 데이터든 — 텍스트, 이미지, 파일, 무엇이든 — 64개의 "안전한" ASCII 문자만 사용하는 문자열로 변환합니다: A-Z, a-z, 0-9, +, /. 끝에 있는 =는 패딩입니다.
왜 필요할까요? 모든 시스템이 원시 바이너리 데이터를 처리할 수 있는 것은 아니기 때문입니다. 이메일은 텍스트용으로 설계되었습니다. JSON은 바이너리를 지원하지 않습니다. URL 매개변수는 임의의 바이트를 포함할 수 없습니다. Base64는 바이너리 데이터를 텍스트 전용 채널을 통해 전달할 수 있게 해주는 다리입니다.
내부 동작 원리
알고리즘은 놀랍도록 간단합니다. 입력 3바이트(24비트)를 가져와 각 6비트씩 4그룹으로 나누고, 각 그룹을 64개 문자 중 하나에 매핑합니다. 간단한 예를 봅시다:
입력: Hi (2바이트: 72, 105)
바이너리: 01001000 01101001 + 패딩 0
6비트 그룹으로 분할: 010010 000110 100100
Base64 알파벳에 매핑: SGk=
이 계산에 따라 Base64 출력은 항상 입력보다 약 33% 더 큽니다. 이것이 안전한 텍스트 전송을 위한 트레이드오프입니다. RFC 4648 사양에서 정확한 알고리즘을 확인할 수 있습니다.
Base64를 사용해야 할 때
HTML/CSS에 작은 이미지 임베딩: 브라우저가 별도 파일을 가져오는 대신, 작은 아이콘을 인라인으로 넣을 수 있습니다: . HTTP 요청 하나를 절약합니다. 2-3KB 이하 아이콘에 적합합니다.
JSON API에서 바이너리 데이터 전송: JSON은 원시 바이트를 담을 수 없습니다. JSON API로 파일을 업로드해야 한다면 Base64로 인코딩하세요:
이메일 첨부파일: 이것이 바로 Base64가 설계된 목적입니다. MIME 인코딩은 텍스트 기반 이메일 메시지에 바이너리 첨부파일을 포함하기 위해 Base64를 사용합니다.
JWT와 인증 토큰: JSON Web Token은 헤더와 페이로드 섹션에 Base64URL 인코딩(URL 안전 변형)을 사용합니다.
텍스트 필드에 바이너리 저장: 데이터베이스 텍스트 컬럼, 환경 변수, 설정 파일 — Base64를 사용하면 텍스트가 가능한 어디든 바이너리 데이터를 넣을 수 있습니다.
Base64를 사용하지 말아야 할 때
- 큰 파일. 33% 크기 증가는 큰 파일에서 정말 아픕니다. 10MB 이미지가 Base64로 13.3MB가 됩니다. 대신 멀티파트 폼 업로드를 사용하세요.
- 보안. Base64는 암호화가 아닙니다. 쉽게 되돌릴 수 있습니다. 비밀번호나 민감한 데이터를 "숨기기" 위해 절대 사용하지 마세요. 누구나
cGFzc3dvcmQ=를password로 몇 초 만에 디코딩할 수 있습니다. - 큰 인라인 이미지. ~5KB 이상의 이미지는 적절한 HTTP 캐싱이 있는 별도 파일이 Base64 데이터 URI보다 성능이 좋습니다.
URL 안전 변형
표준 Base64는 URL에서 특별한 의미를 가진 +와 /를 사용합니다. Base64URL 변형은 이를 -와 _로 대체합니다. JWT와 Base64 데이터가 URL에 나타나는 모든 곳에서 이것을 보게 됩니다.
빠른 코드 예제
가장 일반적인 언어에서 Base64를 인코딩하고 디코딩하는 방법입니다:
JavaScript의 브라우저 btoa() 함수는 ASCII 문자열에서만 작동한다는 점에 주의하세요. Unicode 텍스트를 인코딩해야 한다면 먼저 TextEncoder를 통한 추가 단계가 필요합니다 — 이것 때문에 많은 개발자들이 실수합니다.
Base64에서 흔한 실수
개발자들이 가장 자주 빠지는 함정들입니다:
1. Base64가 암호화라고 생각하기. 아무리 강조해도 부족합니다. API 키와 비밀번호를 Base64로 인코딩하고 "보호되었다"고 생각하는 프로덕션 코드베이스를 본 적이 있습니다. 브라우저 콘솔만 있으면 누구나 즉시 디코딩할 수 있습니다. 데이터를 보호해야 한다면 실제 암호화(AES, RSA)나 해싱(bcrypt, argon2)을 사용하세요.
2. 패딩을 올바르게 처리하지 않기. 일부 구현은 뒤따르는 = 기호를 제거하는데, 이는 엄격한 파서에서 디코딩 실패를 일으킬 수 있습니다. 시스템 간에 Base64를 주고받을 때 패딩 포함 여부를 합의하세요.
3. URL에서 표준 Base64 사용하기. 표준 Base64의 +와 / 문자는 URL을 깨뜨립니다. 쿼리 매개변수나 경로 세그먼트에 인코딩된 데이터를 넣을 때는 항상 URL 안전 변형(Base64URL)을 사용하세요.
4. JSON 페이로드에서 큰 파일을 Base64 인코딩하기. 5MB 파일은 Base64 인코딩 후 거의 7MB가 되며, 그 전체 문자열이 메모리에 있어야 합니다. 몇 KB보다 큰 것은 대신 multipart/form-data를 사용하세요.
Base64 문자 세트 빠른 참조
| 범위 | 문자 | 개수 |
| 대문자 | A-Z | 26 |
| 소문자 | a-z | 26 |
| 숫자 | 0-9 | 10 |
| 기호 | + / | 2 |
| 패딩 | = | 1 |
| URL 안전 대체 | - _ (+ / 대신) | 2 |
실제 사용 사례: CSS에 폰트 임베딩
Base64의 잘 알려지지 않은 일반적인 사용법 중 하나는 커스텀 폰트를 CSS 파일에 직접 임베딩하는 것입니다. 이렇게 하면 폰트 파일에 대한 추가 HTTP 요청을 피할 수 있습니다:
이 기법은 작은 아이콘 폰트(10-15KB 이하)에 잘 작동합니다. 더 큰 폰트 파일은 브라우저가 독립적으로 캐시할 수 있도록 별도로 제공하는 것이 좋습니다.
Base64 vs 다른 인코딩 방식
Base64는 바이너리 데이터를 텍스트로 표현하는 유일한 방법이 아닙니다. 여러 대안이 있고, 각각 최적의 사용처가 있습니다. 주요 방식들을 비교해 봅시다.
16진수 인코딩 (Base16): 가장 간단한 방식 — 각 바이트가 두 개의 16진수 문자(0-9, A-F)가 됩니다. Hi는 4869가 됩니다. 매우 간단하고 사람이 읽기 쉽지만, 출력이 입력보다 100% 더 큽니다(두 배 크기). 16진수는 어디서나 볼 수 있습니다: 색상 코드(#FF5733), SHA 해시, MAC 주소, 디버그 출력 등.
Base32: 32개 문자(A-Z와 2-7)를 사용합니다. 출력은 입력보다 약 60% 더 큽니다. 모르는 사이에 이미 봤을 수도 있습니다 — Google Authenticator와 다른 TOTP/2FA 앱의 6자리 코드는 내부적으로 Base32로 인코딩된 시크릿을 사용합니다. 대소문자를 구분하지 않아서 사용자가 인코딩된 데이터를 수동으로 입력해야 하는 상황에 적합합니다.
ASCII85 / Base85: 85개의 인쇄 가능한 ASCII 문자를 사용하며, 출력은 입력보다 약 25% 더 큽니다. Base64보다 효율적입니다. Git은 바이너리 패치 형식(packfiles)에서 Base85의 변형을 사용하고, Adobe PostScript와 PDF 파일은 내부적으로 ASCII85 인코딩을 사용합니다. 단점은? {, }, 따옴표 같은 문자를 사용해서 JSON, XML, URL에서 문제를 일으킬 수 있습니다.
동일한 100바이트 입력을 인코딩한 비교입니다:
| 인코딩 | 출력 크기 | 오버헤드 | 사용 문자 | 최적 용도 |
| Hex (Base16) | 200바이트 | +100% | 16 (0-9, A-F) | 디버깅, 해시 |
| Base32 | ~160바이트 | +60% | 32 (A-Z, 2-7) | TOTP 코드, 대소문자 구분 없는 환경 |
| Base64 | ~133바이트 | +33% | 64 (A-Z, a-z, 0-9, +/) | 이메일, JSON, 데이터 URI |
| Base85 | ~125바이트 | +25% | 85 (인쇄 가능 ASCII) | Git packfiles, PDF 내부 처리 |
대부분의 경우 Base64가 이기는 이유는 무엇일까요? 최적의 균형점에 있기 때문입니다: 적당한 오버헤드, 모든 언어와 플랫폼에서 폭넓은 지원, 그리고 일반적인 형식에서 문제를 일으키는 대부분의 특수 문자를 피합니다. Base85가 더 컴팩트하지만 범용적 지원이 적고 구조화된 텍스트 형식에서 안전하게 사용하기 어렵습니다.
인증 흐름에서의 Base64
Base64의 가장 널리 사용되는(그리고 가장 오해받는) 용도 중 하나가 HTTP Basic 인증입니다. Basic Auth로 사용자 이름과 비밀번호를 보낼 때, 브라우저는 이를 콜론으로 연결하고 결과를 Base64로 인코딩합니다.
사용자 이름 admin과 비밀번호 secret123으로 로그인할 때 내부에서 일어나는 일입니다:
서버는 이 헤더를 받아 Base64 디코딩하고, 콜론으로 분리하여 인증 정보를 확인합니다. 간단하죠? 하지만 중요한 포인트가 있습니다: HTTPS 없이는 안전하지 않습니다. 이 Base64 문자열은 쉽게 원래대로 되돌릴 수 있습니다 — 요청을 가로채는 사람이라면 누구나 YWRtaW46c2VjcmV0MTIz를 디코딩하여 1초 이내에 비밀번호를 알아낼 수 있습니다. Basic Auth의 RFC 7617 사양은 이 점에 대해 명시적으로 경고합니다.
Base64는 다른 인증 컨텍스트에서도 나타납니다. OAuth 2.0 액세스 토큰과 리프레시 토큰은 종종 Base64로 인코딩됩니다(이것은 구현 세부사항이지 요구사항은 아닙니다). AWS, Stripe, Google Cloud 같은 서비스의 많은 API 키가 Base64로 인코딩된 문자열입니다. 다시 말하지만, 인코딩은 안전한 전송을 위한 것이지 보안을 위한 것이 아닙니다. 항상 HTTPS로 전송하고 안전하게 저장하세요.
데이터 URI 심층 분석
앞서 데이터 URI를 간략히 언급했지만, 더 자세히 살펴볼 가치가 있습니다. 데이터 URI를 사용하면 파일 내용을 HTML, CSS, JavaScript에 직접 임베딩할 수 있습니다 — 외부 HTTP 요청이 필요 없습니다. 전체 구문은 다음과 같습니다:
mediatype은 표준 MIME 타입이고, ;base64 플래그는 데이터가 Base64로 인코딩되었음을 브라우저에 알려주며(없으면 URL 인코딩된 텍스트로 간주), 는 실제 내용입니다.
다양한 미디어 타입의 예입니다:
PNG 이미지 (가장 일반적):
인라인 SVG (Base64 불필요!):
SVG는 이미 텍스트이므로 Base64 인코딩 대신 URL 인코딩할 수 있다는 점에 주목하세요. 33% 오버헤드를 건너뛰기 때문에 실제로 더 작습니다. 똑똑한 개발자들은 간단한 SVG 아이콘에 이 트릭을 사용합니다.
PDF 문서:
오디오 파일:
브라우저 제한에 대해 말하자면, MDN의 데이터 URI 사양은 최대 크기를 정의하지 않지만, 브라우저는 자체 제한을 부과합니다. Chrome은 내비게이션 컨텍스트(iframe 및 최상위 페이지 등)에서 데이터 URI를 약 2MB로 제한합니다. Firefox는 더 관대합니다. CSS 배경 이미지와 인라인 이미지의 경우, 실질적인 제한은 사용자의 인내심입니다 — CSS 파일에 500KB Base64 문자열을 넣는 것은 기술적으로 유효하지만 로딩 시간을 완전히 망칠 것입니다.
성능 영향: Base64가 해가 될 때
실제 숫자로 이야기합시다. "33% 오버헤드"는 실제 영향을 보기 전까지는 추상적으로 들리니까요.
대역폭 비용: 50KB 이미지가 Base64 인코딩 후 ~67KB가 됩니다. 이미지당 17KB 추가입니다. 페이지에 20개의 인라인 아이콘이 있다면 340KB의 불필요한 데이터를 보내고 있는 것입니다. 참고로, 이는 대부분의 웹 페이지 전체 HTML보다 많습니다.
메모리 사용량: 이미지를 Base64로 인코딩하여 HTML이나 CSS에 임베딩하면, 인코딩된 전체 문자열이 DOM이나 스타일시트의 일부로 메모리에 유지되어야 합니다. 브라우저가 이를 바이너리로 디코딩하므로, 잠시 인코딩된 버전과 디코딩된 버전을 모두 보유하게 됩니다. 1MB 이미지의 경우, 인코딩된 문자열만으로 약 2.33MB, 디코딩된 바이너리 1MB — 원본 파일 크기의 3배 이상입니다.
파싱 시간: HTML이나 CSS 내의 Base64 문자열은 해당 문서의 일부로 파싱되어야 합니다. 큰 데이터 URI는 전체 CSS 파일이나 HTML 문서의 파싱을 느리게 만듭니다. web.dev의 이미지 최적화 가이드에 따르면, 인라인 이미지는 일반적으로 성능상 순이득을 제공하려면 2-4KB 이하여야 합니다.
캐시 비효율성: 개발자들이 가장 간과하는 부분입니다. 이미지를 별도 파일로 제공하면 브라우저가 독립적으로 캐시합니다 — 이후 페이지 로드 시 다운로드를 완전히 건너뜁니다. 하지만 같은 이미지를 Base64로 인코딩하여 CSS 파일에 임베딩하면 CSS의 일부가 됩니다. CSS의 다른 부분을 변경하면 브라우저는 변경되지 않은 Base64 이미지 데이터를 포함하여 전체 파일을 다시 다운로드합니다. 세분화된 캐싱을 잃게 됩니다.
대략적인 벤치마크입니다:
| 시나리오 | 별도 파일 | Base64 인라인 |
| 2KB 아이콘 | 추가 HTTP 요청 1개 (HTTP/2에서 ~5ms) | HTML/CSS에 +0.67KB, 추가 요청 없음 |
| 50KB 이미지 | 독립적으로 캐시, HTTP/2 멀티플렉스 | CSS에 +17KB, CSS 변경 시마다 재다운로드 |
| 500KB 사진 | 캐시 가능, 지연 로딩 가능, 프로그레시브 렌더링 | 문서에 +167KB, 렌더링 차단, 지연 로딩 불가 |
경험 법칙: 2-4KB 이하는 Base64 인라인으로. 그 외 모든 것은 별도 파일로 제공하세요. HTTP/2와 HTTP/3에서는 추가 요청 비용이 최소화되어 이 기준은 수년에 걸쳐 더 낮아졌습니다.
다양한 프로그래밍 언어에서의 Base64
JavaScript와 Python은 앞서 다뤘습니다. 다른 인기 있는 언어에서 Base64를 다루는 방법입니다 — 각각 몇 줄이면 됩니다:
모든 언어가 Base64를 표준 라이브러리에 가지고 있다는 점에 주목하세요 — 서드파티 패키지가 필요 없습니다. 이 인코딩이 얼마나 기본적인지를 보여줍니다. 또한 Ruby에는 strict_encode64(줄바꿈 없음)와 encode64(원래 MIME 표준에 맞춰 60자마다 줄바꿈 삽입)가 있습니다. 대부분의 현대적 용도에서는 strict 버전을 원합니다.
Base64의 역사
Base64는 갑자기 등장한 것이 아닙니다. 그 역사는 이메일의 역사와 연결되어 있으며, 이를 이해하면 많은 설계 결정을 설명할 수 있습니다.
인터넷 초창기에 이메일(SMTP)은 7비트 ASCII 텍스트만 처리하도록 설계되었습니다 — 128개 문자, 그게 전부였습니다. 영어 텍스트에는 충분했지만 이미지, 문서, 심지어 영어가 아닌 언어의 텍스트를 보내는 것은 완전히 불가능했습니다. 이메일로 바이너리 데이터를 보내는 것은 단순히 불가능했습니다.
Base64의 첫 번째 공식 사양은 1993년에 RFC 1421에서 Privacy Enhanced Mail(PEM) 표준의 일부로 등장했습니다. 아이디어는 간단했습니다: 바이너리 데이터를 텍스트 기반 전송 시스템을 손상 없이 통과할 수 있는 ASCII의 하위 집합으로 변환하는 것이었습니다.
그 다음 1996년에 RFC 2045가 등장하여 MIME(Multipurpose Internet Mail Extensions)을 정의했습니다. MIME은 이메일 첨부파일의 작동 방식을 표준화했고, Base64는 바이너리 콘텐츠를 위한 주요 인코딩이었습니다. 오늘날에도 원시 이메일 메시지에서 Content-Transfer-Encoding: base64 헤더를 볼 수 있는 이유입니다.
인코딩은 RFC 4648(2006년)에서 다시 개선되어 결정적인 참조가 되었습니다. 이 RFC에서는 URL 안전 변형(Base64URL)도 도입하고 패딩에 관한 엣지 케이스를 명확히 했습니다. MDN의 Base64 용어집 페이지는 원시 RFC를 읽지 않고 사양을 탐색하고 싶을 때 좋은 출발점입니다.
흥미로운 것은 Base64가 7비트 이메일이라는, 더 이상 존재하지 않는 제한에서 태어났다는 점입니다. 현대 SMTP는 8비트 및 바이너리 전송을 지원합니다. 그럼에도 Base64는 원래 목적을 훨씬 넘어 살아남아, 웹 API, JWT, 데이터 URI 및 수많은 다른 컨텍스트에서 새로운 생명을 찾았습니다. 문제를 너무 잘 해결해서 사람들이 해결할 새로운 문제를 계속 찾게 되는 기술 중 하나입니다.
직접 해보세요
Base64를 실제로 체험해 보고 싶으신가요? 아무 텍스트나 파일을 Base64 Encoder에 붙여넣으면 인코딩된 출력을 즉시 볼 수 있습니다. 디코딩이 필요하신가요? Base64 Decoder가 처리합니다. Base64로 인코딩된 이미지를 다루고 있다면, Base64 to Image 도구로 브라우저에서 바로 미리볼 수 있습니다.