CSS 파일을 열었더니 배경 이미지가 URL이 아니라 data:image/png;base64,iVBORw0KGgo...로 시작하는 긴 문자열이었다. Base64라는 건 알겠는데, 왜 이미지를 이렇게 바꿔서 쓰는 걸까.
Base64가 하는 일
바이너리 데이터(이미지, 파일, 특수문자 포함 텍스트 등)를 ASCII 문자열로 바꾸는 인코딩 방식이다. A-Z, a-z, 0-9, +, / 총 64개 문자만 사용한다.
이메일, JSON, XML처럼 텍스트 기반 프로토콜에서는 바이너리 데이터를 직접 넣을 수 없다. Base64로 변환하면 텍스트 형태가 되니까 어디든 넣을 수 있게 된다.
참고 Base64는 암호화가 아니다. 인코딩 규칙이 공개되어 있어서 누구나 디코딩할 수 있다. 보안 목적으로 쓰면 안 된다.
어디에 쓰이는가
1. 이미지 Data URL
작은 아이콘이나 로고를 HTML/CSS에 직접 삽입할 때 쓴다. HTTP 요청을 줄여서 로딩 속도를 약간 개선할 수 있다.
background-image: url(data:image/png;base64,iVBORw0KGgo...);
다만 Base64는 원본 대비 약 33% 크기가 커지기 때문에, 큰 이미지에는 오히려 비효율적이다. 보통 1~2KB 이하의 작은 아이콘에만 적용한다.
2. JWT 토큰
웹 인증에서 쓰이는 JWT(JSON Web Token)는 세 부분으로 나뉘는데, 헤더와 페이로드가 Base64URL로 인코딩되어 있다. 디코딩하면 JSON 형태의 사용자 정보가 나온다.
3. API 데이터 전송
파일 업로드를 REST API로 처리할 때 파일을 Base64 문자열로 바꿔서 JSON body에 넣는 방식이 있다. multipart/form-data 방식보다 구현이 간단하지만 용량이 33% 늘어나는 단점이 있다.
4. 이메일 첨부파일
이메일 프로토콜(SMTP)은 7비트 ASCII 기반이라 바이너리 첨부파일을 그대로 보낼 수 없다. MIME 표준에서 Base64로 인코딩해서 전송한다.
인코딩 원리 (간략 버전)
- 원본 데이터를 8비트 바이트 단위로 나눈다
- 3바이트(24비트)씩 묶어서 6비트 4개로 분할한다
- 각 6비트 값(0~63)을 Base64 문자표에서 대응하는 문자로 바꾼다
- 입력이 3의 배수가 아니면 끝에 = 패딩을 붙인다
"Hi"를 Base64로 바꾸면 "SGk="가 된다. 2바이트짜리 입력이라 패딩 =이 하나 붙은 것이다.
변환 방법
코드로
// JavaScript
btoa("Hello"); // "SGVsbG8="
atob("SGVsbG8="); // "Hello"
한글은 btoa에 바로 넣으면 에러가 난다. encodeURIComponent로 먼저 변환한 뒤 넣어야 한다.
온라인 도구로
코드를 쓸 수 없는 상황이거나 이미지를 Data URL로 변환해야 할 때는 Base64 변환 도구에서 텍스트나 이미지 파일을 넣으면 바로 결과가 나온다. 이미지를 드래그 앤 드롭하면 Data URL 형태의 Base64 문자열이 생성되니까 CSS에 바로 붙여넣을 수 있다.
Base64는 데이터를 텍스트로 바꾸는 변환일 뿐이다. 암호화도 압축도 아니고, 오히려 크기가 커진다. 하지만 텍스트 기반 환경에서 바이너리를 다뤄야 할 때 거의 유일한 선택지이기 때문에 개발에서 피할 수 없는 개념이다.