Base64로 바꾸면 비밀이 될까: 인코딩과 암호화의 차이
웹 통신이나 설정 파일에서 무작위 영문과 숫자가 섞인 긴 문자열을 접하면 암호문으로 오해하기 쉽습니다. 그러나 알파벳 대소문자와 숫자, 더하기(+), 슬래시(/), 등호(=) 기호로 끝나는 문자열의 상당수는 암호화된 결과가 아니라 Base64로 인코딩된 데이터입니다. Base64는 정보를 숨기거나 보호하기 위한 암호화 기술이 아니라, 이진 데이터를 텍스트 환경에서도 안전하게 표기하기 위한 규약입니다. 비밀번호나 개인정보를 안전하게 다루려면 인코딩과 암호화의 차이를 명확히 구분해야 합니다.
Base64는 암호화가 아니라 '바이트 표현 형식'이다
암호화(Encryption)는 비밀 키를 소유한 대상만 원문을 열람할 수 있도록 수학적 변환을 거치는 보안 절차입니다. 반면 RFC 4648 표준에 정의된 Base64는 US-ASCII 인쇄 가능 문자 집합을 사용해 임의의 바이트 열을 표현하는 인코딩(Encoding) 방식입니다.
Base64 변환에는 어떤 비밀번호나 복호화 키도 필요하지 않습니다. 표준 표를 아는 사람이나 소프트웨어라면 누구나 즉시 원본 바이트로 복원할 수 있습니다. 따라서 민감한 토큰이나 비밀번호를 단순히 Base64로 바꾸어 저장하거나 노출하는 것은 평문을 그대로 방치하는 것과 보안상 차이가 없습니다. 실제 시스템의 자격 증명이나 계정 정보를 임의의 온라인 디코더 웹사이트에 붙여넣어 확인하는 행위 역시 원본 값이 외부로 유출될 위험이 있으므로 반드시 피해야 합니다.
문자열에서 바이트로: UTF-8과 24비트 분할 원리
Base64 변환을 이해하려면 텍스트와 바이트의 관계를 먼저 살펴야 합니다. 컴퓨터는 글자 자체를 직접 다루지 않고 규정된 문자 인코딩 규칙에 따라 바이트 배열로 변환합니다. 한글과 같은 다국어 문자는 대개 UTF-8 인코딩을 거쳐 여러 바이트로 표현됩니다.
RFC 4648에 명시된 Base64 처리 과정은 다음과 같이 24비트 단위를 기본 단위로 삼습니다.
- 바이트 열 확보: 입력 문자열을 8비트 바이트 배열로 변환합니다. 한글 한 글자는 UTF-8에서 대개 3바이트(24비트)를 차지합니다.
- 24비트 결합: 3개의 8비트 바이트를 이어 붙여 하나의 24비트 묶음을 만듭니다.
- 6비트 단위 분할: 24비트 묶음을 6비트씩 4개로 나눕니다. 6비트로 표현할 수 있는 값의 범위는 0부터 63(총 64개)입니다.
- 색인 매핑: 각 6비트 값을 64개 기호(A-Z, a-z, 0-9, +, /) 색인표에 대입하여 4개의 출력 문자로 치환합니다.
- 패딩 처리: 데이터 끝부분이 3바이트(24비트) 배수로 떨어지지 않으면 0 비트를 보충하고 빈자리를 등호(=) 기호로 채웁니다.
| 입력 바이트 잔여량 | 출력 문자 구성 | 패딩 문자 수 |
|---|---|---|
| 3바이트 배수 (24비트) | 인코딩 문자 4개 | 0개 (패딩 없음) |
| 2바이트 잔여 (16비트) | 인코딩 문자 3개 | 1개 (=) |
| 1바이트 잔여 (8비트) | 인코딩 문자 2개 | 2개 (==) |
가상 텍스트를 사용한 단계별 인코딩과 복원
실제 비밀값을 다루지 않고 가상의 한국어 문구인 '가상 메모'를 사용해 인코딩과 복원 과정을 확인해 보겠습니다. 이 문구는 공백을 포함해 UTF-8 기준 총 13바이트로 구성되며, 3바이트 배수(12바이트)를 초과하여 1바이트가 남기 때문에 끝에 2개의 등호(==) 패딩이 붙습니다.
{
"original": "가상 메모",
"base64": "6rCA7IOBIOuplOuqqA==",
"decoded": "가상 메모"
}Python base64 모듈을 사용하면 터미널이나 로컬 환경에서 외부 유출 없이 안전하게 같은 과정을 검증할 수 있습니다.
import base64
# 1. 텍스트를 UTF-8 바이트로 변환
original_text = "가상 메모"
byte_data = original_text.encode("utf-8")
# 2. 바이트를 Base64로 인코딩
encoded_bytes = base64.b64encode(byte_data)
encoded_string = encoded_bytes.decode("ascii")
print(encoded_string) # 출력: 6rCA7IOBIOuplOuqqA==
# 3. Base64 문자열을 원본 바이트로 디코딩
decoded_bytes = base64.b64decode(encoded_string)
restored_text = decoded_bytes.decode("utf-8")
print(restored_text) # 출력: 가상 메모위 예제에서 확인할 수 있듯이, b64encode 함수는 암호화 키를 요구하지 않으며 b64decode 함수 역시 아무런 인증 절차 없이 원본 바이트를 온전히 되돌려 줍니다.
자주 발생하는 실패 사례와 binascii.Error 점검
Base64 데이터를 처리하는 과정에서는 패딩 누락이나 잘못된 문자 포함으로 인해 파싱 오류가 발생할 수 있습니다.
- 패딩 길이 불일치 (Incorrect padding): Base64 인코딩 결과 문자열의 길이는 반드시 4의 배수여야 합니다. 통신 과정에서 끝부분의 등호(=)가 잘려 나가 길이가 맞지 않으면
binascii.Error: Incorrect padding예외가 발생합니다. - 비알파벳 문자 포함 (Non-alphabet characters): RFC 4648 표준은 규정된 64개 문자 집합 이외의 문자가 들어오면 처리를 거부하도록 명시합니다. 공백, 쉼표, 줄바꿈 또는 URL에 맞지 않는 문자가 섞여 있으면 디코딩에 실패할 수 있습니다.
- 문자 인코딩 오해: 디코딩하여 얻은 결과는 '문자열'이 아니라 '원시 바이트(bytes)'입니다. 이를 다시 텍스트로 보려면 원래 기록되었던 인코딩(예: UTF-8)으로 역변환해야 하며, 인코딩 형식이 일치하지 않으면 글자가 깨지거나 유니코드 오류가 발생합니다.
Base64 방식이 검증하지 못하는 한계
Base64는 데이터를 텍스트 통로로 운반하기 위한 표현 형식에 불과하므로 데이터 보호 관점에서 다음과 같은 한계를 갖습니다.
- 기밀성 미보장: 누구나 디코딩 알고리즘을 사용해 원문을 확인할 수 있으므로 비밀성을 전혀 제공하지 못합니다.
- 무결성 미검증: 중간에 데이터가 변조되거나 일부가 유실되어도 패딩 규칙과 알파벳 집합만 충족하면 정상적으로 디코딩되므로, 내용이 조작되지 않았는지 자체적으로 검증할 수 없습니다.
- 데이터 크기 증가: 3바이트의 이진 데이터를 4글자의 텍스트(4바이트)로 확장하므로 데이터 용량이 약 33% 증가합니다.
데이터의 기밀성과 안전한 보관이 필요한 경우에는 인코딩에 의존하지 않고, 용도에 맞는 정식 암호화 규격과 비밀 키 관리 체계를 별도로 적용해야 합니다.
참고 자료와 확인 범위
아래 자료는 형식·기능의 정의를 확인하는 데 사용했습니다. 본문의 예제와 설명은 이 사이트의 작업 상황에 맞춰 구성했습니다. 제품 메뉴는 버전과 언어에 따라 다를 수 있습니다.
확인일: 2026-10-20 · 오류를 발견하면 이 글의 오류 신고로 알려주세요.