Base64 인코딩과 디코딩은 언제 사용할까?
Base64가 무엇을 해결하려고 만들어졌는지, 실무에서 어디에 쓰이는지, 그리고 왜 보안 수단이 될 수 없는지 정리했습니다.
Base64는 무엇을 해결하는가
개발을 하다 보면 이미지, 압축 파일, 암호화된 바이트 배열처럼 텍스트가 아닌 데이터를 텍스트만 다룰 수 있는 통로로 보내야 하는 상황이 생깁니다. 이메일 본문, JSON 문자열 필드, HTTP 헤더, XML 속성이 대표적입니다.
이런 통로에 바이너리를 그대로 넣으면 문제가 생깁니다. 값 중간에 들어 있는 0x00이나 개행 문자가 프로토콜의 구분자로 해석되기도 하고, 시스템마다 문자 인코딩이 달라 일부 바이트가 다른 값으로 바뀌기도 합니다. 결과적으로 받는 쪽에서 원본을 복원할 수 없게 됩니다.
Base64는 이 문제를 단순하게 해결합니다. 어떤 바이너리든 A-Z, a-z, 0-9와 몇 개의 기호로만 이루어진 문자열로 바꾸는 것입니다. 이 문자들은 거의 모든 시스템에서 동일하게 취급되므로 중간에 값이 변형될 걱정이 없습니다.
어떻게 동작하는가
Base64는 입력을 3바이트씩 끊습니다. 3바이트는 24비트이고, 이것을 6비트씩 네 조각으로 나눕니다. 6비트로 표현할 수 있는 값은 0부터 63까지 64가지이고, 각 값에 문자 하나를 대응시킵니다. 이름에 64가 들어가는 이유입니다.
입력 길이가 3의 배수가 아니면 마지막 그룹이 모자랍니다. 이때 부족한 자리를 = 기호로 채우는데 이것이 패딩입니다. 남은 바이트가 1개면 == 가, 2개면 = 하나가 붙습니다. 결과 문자열 끝의 = 개수를 보면 원본 길이의 나머지를 짐작할 수 있습니다.
6비트 데이터를 8비트 문자 하나로 표현하기 때문에 인코딩 결과는 원본보다 약 33% 커집니다. 이미지를 Base64로 HTML에 직접 넣으면 파일로 따로 두는 것보다 전송량이 늘어나는 이유가 여기에 있습니다.
실무에서 마주치는 곳
아래는 개발하면서 Base64를 실제로 만나게 되는 대표적인 상황입니다.
- JWT: header와 payload가 URL-safe Base64로 인코딩되어 있습니다. 점으로 구분된 첫 두 조각을 디코딩하면 바로 내용을 볼 수 있습니다.
- HTTP Basic 인증: Authorization 헤더의 Basic 뒤에 오는 값이 아이디:비밀번호 를 Base64로 인코딩한 것입니다.
- Data URI: CSS나 HTML에 작은 아이콘을 파일 없이 직접 넣을 때 data:image/png;base64, 뒤에 이미지 데이터를 붙입니다.
- 쿠버네티스 Secret: data 필드의 값이 Base64로 저장됩니다. 암호화가 아니라 인코딩이라는 점이 자주 오해됩니다.
- 이메일 첨부: MIME 규격에서 첨부 파일을 Base64로 인코딩해 본문에 담습니다.
URL-safe 변형이 필요한 이유
일반 Base64는 62번과 63번 문자로 + 와 / 를 사용합니다. 문제는 이 두 문자가 URL에서 고유한 의미를 갖는다는 것입니다. / 는 경로 구분자이고 + 는 쿼리스트링에서 공백으로 해석되는 경우가 있습니다.
그래서 값을 URL 경로나 쿼리, 파일 이름에 넣어야 할 때는 + 를 - 로, / 를 _ 로 바꾼 URL-safe 방식을 사용합니다. JWT가 이 방식을 쓰는 이유도 토큰이 URL이나 헤더에 실려 다니기 때문입니다.
디코딩이 실패한다면 이 변형을 확인해 보십시오. 일반 Base64 디코더에 URL-safe 문자열을 넣으면 오류가 나거나 엉뚱한 결과가 나옵니다.
Base64는 보안 수단이 아니다
가장 흔한 오해입니다. Base64는 키가 필요 없는 공개된 변환 규칙이므로 누구나 즉시 되돌릴 수 있습니다. 비밀번호나 API 키를 Base64로 바꿔 설정 파일에 넣는 것은 아무런 보호 효과가 없습니다. 값을 읽기 어렵게 만들 뿐이고, 그마저도 이 페이지의 도구 하나면 몇 초 만에 풀립니다.
데이터를 보호해야 한다면 AES 같은 암호화를 사용하고 키를 안전하게 관리해야 합니다. 무결성을 확인하는 것이 목적이라면 해시나 HMAC을 사용합니다. Base64는 전송 안전성을 위한 포장이지 잠금장치가 아닙니다.
디코딩이 안 될 때 확인할 것
입력이 분명 Base64처럼 보이는데 디코딩에 실패한다면 대개 아래 중 하나입니다.
- 패딩이 잘려 있음: 끝의 = 가 제거된 상태로 전달되는 경우가 있습니다. 길이를 4의 배수로 맞춰 = 를 채우면 해결됩니다.
- URL-safe 문자가 섞여 있음: - 와 _ 가 보이면 URL-safe 변형입니다. + 와 / 로 되돌린 뒤 디코딩합니다.
- 개행이 포함됨: 이메일 규격은 76자마다 줄을 나눕니다. 줄바꿈을 제거하고 시도하십시오.
- 원본이 텍스트가 아님: 디코딩은 성공했지만 결과가 깨진 문자로 보인다면 원본이 이미지나 압축 파일일 수 있습니다. 정상입니다.