</>DevTools

B64Base64 인코드/디코드

Base64 문자열 인코딩 및 디코딩

Base64 인코딩 이해하기: 원리, 용도, 그리고 흔한 오해

Base64는 임의의 바이트 데이터를 ASCII 문자 64개만으로 표현하는 인코딩 방식입니다. 암호화가 아니고, 압축도 아니며, 오히려 데이터 크기를 약 33% 늘립니다. 그런데도 널리 쓰이는 이유는 '바이너리를 텍스트만 통과하는 통로로 안전하게 실어 보낼 수 있다'는 단 한 가지 성질 때문입니다.

어떻게 동작하는가

Base64는 입력 바이트를 3바이트(24비트)씩 묶고, 이를 6비트 단위 4조각으로 자릅니다. 6비트는 0~63의 값을 가지므로 64글자 알파벳(A-Z, a-z, 0-9, +, /)에 하나씩 대응시킬 수 있습니다. 3바이트가 4문자로 바뀌므로 출력 길이는 입력의 4/3배, 즉 약 33% 증가합니다.

입력 길이가 3의 배수가 아니면 마지막 묶음이 비어서, 부족한 자리를 '=' 문자로 채웁니다. 그래서 Base64 문자열 끝에 =가 0개, 1개, 2개 붙습니다. 남은 바이트가 1개면 ==, 2개면 =가 하나 붙습니다.

'Hi'(2바이트)를 인코딩하는 과정
'H' = 0x48 = 01001000
'i' = 0x69 = 01101001

비트 이어붙이기:  01001000 01101001
6비트로 자르기:   010010 000110 1001(+00 패딩)
십진수:          18     6      36
알파벳 대응:      S      G      k
남은 자리는 '=' → SGk=

사용 방법

  1. 인코딩할 텍스트나 디코딩할 Base64 문자열을 입력창에 넣습니다.
  2. Encode 또는 Decode 방향을 선택합니다.
  3. 결과를 복사해 사용합니다. 디코딩 시 입력이 올바른 Base64가 아니면 오류가 표시됩니다.
  4. URL이나 파일 이름에 넣어야 한다면 아래의 URL-safe 변형 설명을 확인하세요.

표준 Base64와 URL-safe Base64

표준 Base64가 쓰는 + 와 / 는 URL에서 특별한 의미를 가집니다. +는 쿼리 문자열에서 공백으로 해석될 수 있고, /는 경로 구분자입니다. 그래서 RFC 4648은 이 두 글자를 - 와 _ 로 바꾼 'base64url' 변형을 따로 정의합니다. JWT가 바로 이 변형을 쓰며, 패딩 =도 생략합니다.

항목표준 Base64base64url
62번째 문자+-
63번째 문자/_
패딩= 사용보통 생략
주 용도MIME, 데이터 URI, HTTP Basic 인증JWT, URL 파라미터, 파일명

한글이 깨지는 이유

Base64는 바이트를 다루는 규격이고, 문자를 바이트로 바꾸는 일은 그 앞 단계인 문자 인코딩의 몫입니다. 즉 '안녕'을 Base64로 만들려면 먼저 UTF-8로 인코딩해 바이트 3개짜리 문자 2개, 총 6바이트를 얻고 그 바이트를 Base64로 변환해야 합니다.

브라우저의 옛 API인 btoa()는 이 단계를 건너뛰고 각 문자를 코드포인트 1바이트로 취급하기 때문에, 0~255 범위를 넘는 한글이나 이모지를 넣으면 InvalidCharacterError를 던집니다. 이 도구는 TextEncoder로 UTF-8 바이트를 먼저 만들어 처리하므로 한글, 일본어, 이모지 모두 정상 동작합니다.

반대로 디코딩 결과가 깨진 글자로 나온다면, 원본이 UTF-8이 아닌 EUC-KR이나 CP949로 인코딩된 바이트일 가능성이 높습니다.

JavaScript에서 유니코드를 안전하게 다루는 방법
// 인코딩
const bytes = new TextEncoder().encode("안녕");
const b64 = btoa(String.fromCharCode(...bytes));

// 디코딩
const raw = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
const text = new TextDecoder().decode(raw);

이런 곳에 씁니다

  • 데이터 URI: CSS나 HTML에 작은 아이콘을 base64로 임베드해 요청 수를 줄일 때
  • HTTP Basic 인증: Authorization 헤더의 'Basic dXNlcjpwYXNz' 부분이 user:pass의 Base64
  • JWT: 헤더와 페이로드가 base64url로 인코딩되어 점(.)으로 연결됨
  • 이메일 첨부: MIME은 7비트 통로를 전제하므로 바이너리 첨부를 Base64로 변환
  • 설정 파일이나 환경변수에 인증서·키 파일 전체를 한 줄로 넣을 때
  • 웹훅 서명 검증에서 HMAC 결과를 텍스트로 비교할 때

성능상 주의할 점

이미지를 데이터 URI로 임베드하면 HTTP 요청은 줄지만 얻는 것보다 잃는 것이 클 수 있습니다. 용량이 33% 늘고, 별도 파일이 아니므로 브라우저가 개별 캐싱할 수 없으며, CSS나 HTML 문서 자체가 커져서 첫 렌더링을 지연시킵니다. 경험적으로는 1~2KB 이하의 작은 아이콘 정도가 임베드할 만하고, 그보다 크면 별도 파일로 두고 캐시 헤더를 붙이는 편이 낫습니다.

자주 묻는 질문

Base64는 암호화인가요?
아닙니다. 키가 없고 누구나 즉시 되돌릴 수 있으므로 보안 수단이 전혀 아닙니다. Base64로 감싼 비밀번호는 평문과 같다고 봐야 합니다. 실제로 HTTP Basic 인증이 안전하지 않다고 하는 이유가 이것입니다. 값을 보호해야 한다면 AES 같은 암호화나, 되돌릴 수 없어야 한다면 해시를 써야 합니다.
끝에 붙는 = 는 무슨 의미인가요?
패딩입니다. 입력 바이트 수가 3의 배수가 아닐 때 마지막 4문자 블록을 채우기 위해 붙습니다. 남은 바이트가 1개면 == 두 개, 2개면 = 한 개가 붙습니다. 일부 구현은 패딩 없이도 디코딩하지만, 엄격한 파서는 패딩을 요구하므로 임의로 지우면 오류가 날 수 있습니다.
디코딩했더니 알 수 없는 문자가 나옵니다.
세 가지를 확인하세요. 첫째, 원본이 텍스트가 아니라 이미지나 압축 파일 같은 바이너리일 수 있습니다. 둘째, UTF-8이 아닌 EUC-KR 등 다른 문자 인코딩일 수 있습니다. 셋째, 문자열이 base64url 변형인데 표준으로 디코딩했거나 그 반대일 수 있습니다. - 와 _ 가 보이면 base64url입니다.
긴 문자열에 줄바꿈이 들어 있어도 되나요?
MIME 규격(RFC 2045)은 76자마다 줄바꿈을 넣도록 규정하고, 대부분의 디코더는 공백과 줄바꿈을 무시합니다. 다만 JWT처럼 엄격한 문맥에서는 줄바꿈이 들어가면 토큰이 무효가 됩니다.
Base64가 데이터를 압축하나요?
정반대입니다. 3바이트를 4문자로 바꾸므로 약 33% 커집니다. 압축이 필요하면 gzip으로 먼저 압축한 뒤 Base64로 감싸는 순서여야 합니다. 순서를 바꾸면 Base64 출력은 엔트로피가 높아 압축률이 크게 떨어집니다.
파일도 인코딩할 수 있나요?
이 도구는 텍스트 입력을 다룹니다. 이미지 파일을 데이터 URI로 만들려면 Image to Base64 도구를 쓰는 편이 편합니다. 명령줄에서는 base64 -i file.png (macOS) 또는 base64 -w 0 file.png (Linux)를 쓸 수 있습니다.

💡 참고: 인코딩과 디코딩 모두 브라우저에서 처리되며 입력값은 서버로 전송되지 않습니다. 그래도 실제 운영 환경의 인증 토큰이나 개인정보를 외부 사이트에 붙여넣는 것은 사내 정책상 금지된 경우가 많으니 확인 후 사용하세요.

🔗관련 도구🔄 텍스트/데이터 변환