본문으로 건너뛰기
Toova
모든 도구

Base64 인코딩 이해 — 완전한 개발자 가이드

Toova

Base64 인코딩은 웹 개발의 거의 모든 영역에 나타납니다 — JWT 토큰, 데이터 URI, 이메일 첨부 파일, API 페이로드, 암호학적 서명 및 설정 파일. 보편적임에도 불구하고 자주 오해됩니다: 개발자는 때때로 그것을 암호화와 혼동하거나 그것이 상황을 악화시키는 상황에서 사용합니다. 이 가이드는 Base64가 정확히 어떻게 작동하는지, 언제 손을 뻗어야 하는지, 언제 피해야 하는지, 그리고 JavaScript에서 올바르게 사용하는 방법을 설명합니다.

Base64 인코딩이 무엇인가(그리고 아닌가)

Base64는 바이너리-텍스트 인코딩 체계입니다. 그것의 유일한 작업은 임의의 바이너리 데이터를 인쇄 가능한 ASCII 문자 문자열로 변환하는 것입니다. 데이터를 압축하지 않고, 데이터를 암호화하지 않으며, 데이터를 검증하지 않습니다. 순전히 표현 변환입니다 — null 바이트, 제어 문자 또는 텍스트 기반 프로토콜을 깨뜨릴 값을 포함할 수 있는 바이트를 안전한 문자 세트로 변환합니다.

이름은 인코딩 알파벳으로 사용되는 64개의 인쇄 가능한 문자에서 유래합니다: A–Z(26자), a–z(26자), 0–9(10자), 더하기 +/(2자). = 문자는 패딩에 사용됩니다. 문자 위치당 64개의 가능한 값이 있고 2^6 = 64이기 때문에 각 Base64 문자는 원본 데이터의 정확히 6비트를 인코딩합니다.

Base64 작동 방식 — "Hello" 단계별

Base64를 이해하는 가장 좋은 방법은 구체적인 예제를 추적하는 것입니다. Hello 문자열을 인코딩해봅시다.

1단계: 바이트로 변환

Hello의 각 문자는 ASCII 코드에 매핑되며, 이는 이진수(바이트당 8비트)로 표현됩니다:

H  e  l  l  o
72 65 6C 6C 6F   (ASCII / 16진수)
01001000 01100101 01101100 01101100 01101111   (이진수)

2단계: 6비트 청크로 그룹화

모든 비트를 연결: 0100100001100101011011000110110001101111(40비트). Base64는 한 번에 3바이트(24비트)를 처리하고 4개의 Base64 문자(4 × 6 = 24비트)에 매핑합니다. 40비트를 6비트 청크로 그룹화하고, 마지막 그룹을 0으로 채워 채웁니다:

010010 000110 010101 101100 011011 000110 1111
18     6      21     44     27     6      (마지막 그룹은 6비트로 패딩됨: 111100 = 60)

3단계: Base64 알파벳에 매핑

각 6비트 값은 Base64 알파벳의 문자에 매핑됩니다(A=0, B=1, ... Z=25, a=26, ... z=51, 0=52, ... 9=61, +=62, /=63). 5바이트는 3의 배수가 아니므로 하나의 = 패딩 문자가 추가됩니다:

인덱스: 18  6   21  44  27  6   60
문자:  S   G   V   s   b   G   8
결과: SGVsbG8=   (=는 패딩)

결과

"Hello" → "SGVsbG8="

Toova Base64 인코더/디코더로 즉시 검증할 수 있습니다 — Hello를 붙여넣고 Encode를 클릭하면 SGVsbG8=를 얻습니다. Decode를 클릭하여 반대로 합니다.

33% 크기 오버헤드

Base64 인코딩은 항상 데이터 크기를 약 33% 증가시킵니다. 수학은 간단합니다: 3바이트의 입력(24비트)은 4개의 Base64 문자(4 × 6비트 그룹으로 인코딩된 24비트)를 생성합니다. 그것은 4/3 비율, 즉 33.3% 오버헤드입니다. 패딩 문자를 더하면 실제 오버헤드는 입력 길이에 따라 33%에서 36% 사이입니다.

이는 성능에 상당히 중요합니다. HTML에 Base64 데이터 URI로 임베드된 1 MB 이미지는 약 1.37 MB가 됩니다. 모든 바이너리 페이로드를 Base64로 인코딩하는 API는 필요한 것보다 33% 더 많은 데이터를 보냅니다. 짧은 토큰이나 체크섬 같은 작은 값의 경우 오버헤드는 무시할 수 있습니다. 큰 파일의 경우 실제 비용입니다.

URL 안전 변형

표준 Base64는 마지막 두 알파벳 문자로 +/를 사용합니다. 이 둘은 URL에서 문제가 됩니다:

  • +는 쿼리 문자열에서 공백 문자로 디코딩됩니다
  • /는 URL의 경로 구분자입니다

URL 안전 Base64(RFC 4648 섹션 5에 정의된 Base64url라고도 함)는 +-로, /_로 대체합니다. 일부 URL 파서에서도 잘못 해석될 수 있기 때문에 URL 안전 컨텍스트에서 패딩(=)이 일반적으로 생략됩니다.

JWT 토큰은 패딩 없는 Base64url을 사용합니다. JWT 헤더나 페이로드를 수동으로 디코딩할 때 문자 대체와 누락된 패딩을 모두 처리해야 합니다. JavaScript에서 그것을 하는 방법은 다음과 같습니다:

// URL 안전 Base64 (+ 를 - 로, / 를 _ 로 대체)
function toBase64Url(base64) {
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

function fromBase64Url(base64url) {
  const padded = base64url.padEnd(
    base64url.length + (4 - base64url.length % 4) % 4,
    '='
  );
  return atob(padded.replace(/-/g, '+').replace(/_/g, '/'));
}

Toova Base64 인코더/디코더는 단일 토글로 표준과 URL 안전 변형을 모두 지원합니다.

JavaScript의 Base64

브라우저: btoa()와 atob()

브라우저는 두 개의 내장 함수를 제공합니다: btoa()(이진수에서 ASCII, 즉 인코딩)와 atob()(ASCII에서 이진수, 즉 디코딩). 혼란스러운 이름 순서에도 불구하고 10년 넘게 브라우저에서 사용 가능했습니다.

// 브라우저 — atob / btoa (문자열만, ASCII 안전)
const encoded = btoa("Hello");
console.log(encoded); // "SGVsbG8="

const decoded = atob("SGVsbG8=");
console.log(decoded); // "Hello"

중요한 제한: btoa()는 Latin-1 범위(코드 포인트 0–255)의 문자가 있는 문자열만 받습니다. 이모지나 CJK 문자 같은 유니코드 문자가 있는 문자열을 전달하면 DOMException을 throw합니다. 임의 바이너리 데이터를 인코딩하려면 먼저 Uint8Array로 변환하세요:

// 브라우저 — 임의 바이너리 인코딩(Uint8Array)
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
const encoded = btoa(String.fromCharCode(...bytes));
console.log(encoded); // "SGVsbG8="

유니코드 문자를 포함할 수 있는 임의 문자열을 인코딩하기 위해 권장되는 현대적 접근 방식은 먼저 TextEncoder를 사용하여 Uint8Array를 얻은 다음 위에서 보여준 대로 인코딩하는 것입니다.

Node.js: Buffer

Node.js는 바이너리 데이터를 올바르게 처리하고 Base64와 Base64url을 포함한 여러 인코딩을 지원하는 Buffer 클래스를 제공합니다:

// Node.js — Buffer(바이너리 안전 처리)
const encoded = Buffer.from('Hello').toString('base64');
console.log(encoded); // "SGVsbG8="

const decoded = Buffer.from('SGVsbG8=', 'base64').toString('utf8');
console.log(decoded); // "Hello"

// Node.js의 URL 안전 변형
const urlSafe = Buffer.from('Hello').toString('base64url');
console.log(urlSafe); // "SGVsbG8" (패딩 없음)

base64url 인코딩 옵션(Node.js 16 이후 사용 가능)은 문자 대체와 패딩 제거를 자동으로 처리하여 수동으로 변환하는 것보다 훨씬 쉽게 만듭니다.

큰 바이너리 파일을 처리해야 하는 브라우저 환경의 경우 FileReader.readAsDataURL 메서드는 모든 것을 메모리에 한 번에 로드하지 않고 파일을 Base64 데이터 URI로 인코딩합니다.

Base64를 사용할 때

텍스트 전용 프로토콜에 바이너리 데이터 임베드

Base64의 원래 사용 사례는 7비트 ASCII 텍스트만 지원하는 프로토콜인 SMTP의 바이너리 이메일 첨부 파일을 인코딩하는 것이었습니다. 동일한 원리는 원시 바이트를 처리할 수 없는 형식에 바이너리 데이터를 포함해야 하는 곳 어디에나 적용됩니다: JSON API 페이로드, XML 문서, HTML 속성, CSS 값, HTTP 헤더.

작은 자산을 위한 데이터 URI

CSS와 HTML을 사용하면 이미지, 글꼴 및 SVG를 Base64 데이터 URI로 임베드할 수 있습니다. 이는 아이콘 같은 작은 자산에 대해 HTTP 왕복을 제거하고 중요한 above-the-fold 이미지에 대한 unstyled content의 깜박임을 제거합니다.

<!-- Base64 데이터 URI로 인라인 SVG 아이콘 -->
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0c..." alt="icon" />

<!-- 인라인 CSS 배경 -->
.icon {
  background-image: url("data:image/png;base64,iVBORw0KGgo...");
}

트레이드오프: Base64 데이터 URI는 그것들을 포함하는 HTML/CSS 파일과 별도로 캐시될 수 없습니다. 이미지가 절대 변경되지 않지만 주변 HTML이 변경되면 브라우저는 모든 페이지 다시 로드에서 이미지 데이터를 다시 다운로드합니다. 왕복 제거가 캐시 페널티보다 더 큰 작은 자산(이상적으로 4 KB 미만)에만 데이터 URI를 사용하세요.

JSON 또는 URL 매개변수를 위한 바이너리 데이터 인코딩

JSON은 텍스트 형식입니다 — 원시 바이너리 바이트를 직접 표현할 수 없습니다. API가 바이너리 데이터(이미지 썸네일, 암호학적 서명, 압축된 데이터)를 전송해야 할 때 Base64는 JSON 페이로드에 포함하는 표준 방법입니다. 유사하게, URL 쿼리 매개변수에 바이너리 데이터를 전달해야 할 때 Base64url 인코딩은 데이터가 손상 없이 퍼센트 인코딩을 견디도록 보장합니다.

JWT와 기타 토큰 형식

JWT 토큰은 헤더와 페이로드 섹션을 인코딩하기 위해 Base64url을 사용합니다. 이는 토큰을 HTTP 헤더, 쿠키 또는 URL 매개변수에 전달될 수 있는 인쇄 가능하고 URL 안전한 문자열로 만듭니다. 인코딩은 보안을 위한 것이 아닙니다(페이로드는 토큰을 가진 누구나 읽을 수 있음) — 순전히 안전한 전송을 위한 것입니다.

Base64를 사용하지 말아야 할 때

보안 또는 기밀성

Base64는 보안을 0 제공합니다. 밀리초 안에 사소하게 되돌릴 수 있습니다. 비밀번호, API 키 또는 민감한 설정 값을 "난독화"하기 위해 사용하지 마세요. Base64 문자열을 보는 모든 개발자는 즉시 디코딩할 것입니다. 기밀성이 필요하다면 암호화를 사용하세요.

비밀번호 저장

Base64 인코딩된 비밀번호를 저장하는 것은 평문으로 저장하는 것과 동일합니다 — 인코딩이 즉시 되돌릴 수 있습니다. 비밀번호는 bcrypt, Argon2 또는 scrypt 같은 적절한 비밀번호 해싱 함수로 해시되어야 합니다.

큰 바이너리 파일

10 MB 파일을 Base64로 인코딩하면 13.7 MB 문자열이 생성됩니다. 그것을 데이터베이스 컬럼에 저장하고, 검색하거나, API를 통해 전송하면 매번 33% 오버헤드를 지불합니다. 큰 바이너리 데이터의 경우 전용 바이너리 저장소를 사용하세요: 데이터베이스 BLOB/BYTEA 컬럼, S3 또는 GCS 같은 객체 저장소, 또는 바이너리를 직접 스트리밍하세요.

바이너리를 직접 사용할 수 있는 상황

프로토콜이나 형식이 원시 바이너리를 지원한다면 — 예를 들어 바이너리 메시지 타입이 있는 WebSocket, multipart/form-data HTTP 업로드 또는 바이너리 파일 형식 — 바이너리를 직접 사용하세요. Base64는 전송 매체가 진정으로 원시 바이트를 처리할 수 없을 때만 필요합니다.

일반적인 함정

인코딩과 암호화 혼동

이것이 가장 흔한 실수입니다. Base64는 보입니다. 보안 메커니즘이 아닙니다. "비밀번호는 보안을 위해 Base64 인코딩으로 저장됨" 같은 코드 주석은 코드 리뷰에서 잡혀야 할 심각한 오해를 나타냅니다.

유니코드 문자열로 btoa() 사용

255 이상의 코드 포인트를 가진 문자가 포함된 문자열에 btoa()를 호출하면 DOMException: Failed to execute 'btoa': The string to be encoded contains characters outside of the Latin1 range를 throw합니다. 유니코드 문자를 포함할 수 있는 문자열을 인코딩하기 전에 항상 TextEncoder를 통해 Uint8Array로 변환하세요.

디코딩 시 패딩 잊기

Base64 문자열은 4의 배수인 길이를 가져야 합니다. Base64 문자열이 패딩 없이 생성되었다면(URL 안전 인코딩에서 일반적), 디코딩 전에 올바른 수의 = 문자를 다시 추가해야 합니다. 길이 n의 Base64 문자열은 (4 - n % 4) % 4 패딩 문자가 필요합니다. 이것을 잊으면 진단하기 어려운 디코딩 오류가 발생합니다.

이중 인코딩

Base64 문자열은 그 자체로 유효한 ASCII이므로 btoa(btoa(data))는 오류 없이 작동하지만 이중 인코딩된 출력을 생성합니다. 직렬화의 여러 계층을 통해 Base64 값을 전달할 때(예: JSON 내의 JSON) 동일한 데이터를 두 번 인코딩하기 쉽습니다. 항상 인코딩한 횟수와 정확히 같은 횟수로 디코딩하세요.

빠른 참조: 실제의 Base64

코드를 작성하지 않고 브라우저에서 인코딩과 디코딩을 위해 Toova Base64 인코더/디코더는 브라우저에서 완전히 실행됩니다 — 서버 왕복 없음. 표준과 URL 안전 변형, 바이너리 파일 인코딩을 위한 파일 업로드, 디코딩된 데이터를 위한 텍스트와 16진수 출력 모두를 지원합니다.

URL 내부의 인코딩된 콘텐츠로 작업한다면 URL 인코더/디코더는 Base64와 별도로 퍼센트 인코딩을 처리합니다. HTML 엔티티의 경우 HTML 엔티티 변환기는 HTML 컨텍스트에서 문자 이스케이프를 처리합니다. 이것들은 별개의 인코딩 체계입니다 — 각각 특정한 사용 사례가 있습니다.

Base64의 표준 참조는 표준 Base64(섹션 4), Base64url(섹션 5) 및 Base32(섹션 6–7)를 정의하는 RFC 4648입니다. btoa()atob() 브라우저 API의 경우 btoa()에 대한 MDN 문서는 브라우저 호환성과 유니코드 제한을 자세히 다룹니다.

요약

Base64 인코딩은 64자 알파벳을 사용하여 바이너리 데이터를 인쇄 가능한 ASCII로 변환합니다. 데이터 크기를 33% 증가시키고, 완전히 되돌릴 수 있으며, 보안을 제공하지 않습니다. 텍스트 기반 형식에 바이너리 데이터를 임베드해야 할 때 사용하세요 — JSON 페이로드, HTML 데이터 URI, JWT 토큰, 이메일 첨부 파일, URL 매개변수. 보안이 필요하거나, 전송이 바이너리를 직접 지원하거나, 33% 오버헤드가 규모에서 중요할 때는 피하세요.

Base64가 무엇인지 — 그리고 아닌지 — 이해하면 가장 흔한 실수를 방지할 수 있습니다: 보안을 위해 사용, 큰 파일에 불필요하게 적용, 그리고 URL 인코딩이나 HTML 엔티티 같은 다른 인코딩 체계와 혼동. 각 인코딩 체계는 특정 문제를 해결합니다. Base64는 정확히 하나를 해결합니다: 바이너리 데이터를 텍스트 전용 채널에 안전하게 만들기.

인코딩하거나 디코딩할 준비가 되었습니까? Toova Base64 인코더/디코더를 사용해보세요 — 텍스트를 붙여넣거나 파일을 드롭하고, 표준 또는 URL 안전을 토글하고, 결과를 복사하세요. 계정 없음, 서버 없음, 제한 없음.