이미지 Base64 변환 방법과 결과 읽는 법

이미지를 HTML이나 CSS에 파일 형태가 아니라 문자열로 직접 넣고 싶을 때가 있습니다. 또는 어딘가에서 받은 Base64 문자열을 다시 이미지 파일로 되돌리고 싶을 때도 있습니다.
이럴 때 대부분 같은 지점에서 막힙니다. 문자열이 원본보다 길어지는 이유, "data:image/png;base64," 접두사의 정체, 붙여넣은 이미지가 깨지는 이유가 그것입니다.
Base64는 파일을 압축하는 방식이 아니라 이진 데이터를 텍스트로 옮겨 적는 표기법입니다.
이 글은 그 표기법이 어떻게 동작하는지, 결과물이 왜 원본보다 커지는지, 두 가지 출력 형식을 언제 써야 하는지를 순서대로 정리합니다.
요약 ① Base64는 8비트 이진 데이터를 6비트씩 끊어 64개 문자로 표현하는 방식이라 결과물이 원본보다 약 33% 커집니다. ② "Data URL"은 data:MIME타입;base64, 접두사가 붙어 HTML/CSS에 바로 쓸 수 있고, "Plain Base64"는 그 접두사 없이 순수 인코딩 값만 담습니다. ③ img 태그에 접두사 없이 Plain Base64만 붙여넣거나 공백·줄바꿈이 섞인 문자열을 그대로 디코딩하면 이미지가 깨지거나 오류가 납니다.
왜 이 결과물이 헷갈리는가 — 흔한 상황 하나
작은 아이콘 하나를 별도 이미지 파일 없이 HTML 안에 통째로 넣고 싶은 경우가 있습니다. 이메일 템플릿처럼 외부 이미지 로딩이 자주 막히는 환경이거나, 파일 하나로 배포해야 하는 위젯을 만들 때입니다.
이럴 때 이미지를 Base64로 바꿔 <img src="..."> 안에 문자열째로 넣는 방법을 씁니다.
문제는 변환 결과를 그대로 복사해 붙였는데 이미지가 안 뜨는 경우입니다. 반대로 서버에서 받은 Base64 문자열을 파일로 저장했는데 확장자를 뭘로 붙여야 할지 모르는 경우도 있습니다.
원본 파일의 형식 정보가 문자열 자체에는 없는 경우가 많고, 있어도 어디에 붙여야 하는지 모르면 못 씁니다. 두 상황 모두 인코딩 원리를 알면 바로 풀립니다.
도구 없이 원리부터 직접 계산해보는 방법
6비트씩 잘라 문자로 바꾸는 원리
Base64 인코딩의 핵심은 8비트 단위로 저장된 이진 데이터를 6비트 단위로 다시 자르는 것입니다. 그 6비트 값(063)을 미리 정해진 64개 문자표(AZ, az, 09, +, /)에 대응시킵니다.
8비트와 6비트의 최소공배수는 24비트입니다. 그래서 원본 3바이트(24비트)마다 6비트씩 4묶음, 즉 4개의 문자가 만들어집니다.
예를 들어 문자 "Man"의 바이트 값은 M=77, a=97, n=110입니다. 이를 이진수로 이어 붙이면 24비트(010011010110000101101110)가 됩니다.
이걸 6비트씩 4묶음으로 나누면 19, 22, 5, 46이 되고, 문자표에서 각각 T, W, F, u에 해당해 "Man"은 "TWFu"로 인코딩됩니다.
용량이 늘어나는 이유와 "=" 패딩
여기서 용량 증가의 이유가 그대로 드러납니다. 원본 3바이트가 인코딩되면 문자 4개가 되고, 이 문자 4개를 텍스트로 저장하면 다시 4바이트가 됩니다.
3바이트가 4바이트로 늘어나는 비율은 4/3, 약 1.333배입니다. 이것이 "인코딩 후 용량이 약 33% 늘어난다"는 계산의 근거입니다.
원본 용량이 3의 배수로 딱 나눠떨어지지 않으면 마지막 자리를 "=" 문자로 채웁니다. 1바이트가 남으면 뒤에 "=="가, 2바이트가 남으면 "="가 하나 붙어 출력 길이를 항상 4의 배수로 맞춥니다.
터미널에서 직접 변환해보기
이 계산을 손으로 하지 않고 직접 변환해보려면 운영체제에 내장된 명령어를 쓰면 됩니다. macOS나 리눅스 터미널이라면 다음과 같이 입력합니다.
base64 -i image.png
결과로 나오는 문자열이 Plain Base64입니다. 여기에 파일의 MIME 타입을 알고 있다면 앞에 "data:image/png;base64," 처럼 접두사를 붙이면 Data URL이 완성됩니다.
반대로 문자열을 파일로 되돌릴 때는 같은 명령어에 -d 옵션을 붙입니다.
저희 도구로 확인하기.
파일을 선택하면 브라우저 안에서 즉시 Base64로 변환되며, 서버로 전송되지 않고 최대 10MB까지 지원합니다.

결과를 읽을 때 자주 헷갈리는 지점
Data URL과 Plain Base64는 같은 인코딩 값을 담고 있지만 접두사 유무에 따라 쓰임이 갈립니다.
| 구분 | Data URL | Plain Base64 |
|---|---|---|
| 형태 | data:image/png;base64,iVBORw0K... | iVBORw0K... (접두사 없음) |
| 쓰는 곳 | <img src="">, CSS background-image처럼 브라우저가 바로 해석해야 하는 자리 | API 요청 바디, 파일 저장 등 순수 인코딩 값만 필요한 자리 |
| MIME 타입 정보 | 접두사 안에 포함돼 있어 별도 전달이 필요 없음 | 문자열 자체에는 없어 따로 알려줘야 함 |
가장 흔한 실수는 세 가지입니다.
실수 1: img 태그에 접두사 없이 넣기
Plain Base64 문자열만 복사해 <img src="...">에 그대로 넣으면 브라우저가 해석하지 못해 깨진 이미지 아이콘만 뜹니다.
src 속성에는 반드시 "data:이미지MIME타입;base64," 접두사가 붙은 Data URL 전체를 넣어야 합니다.
실수 2: 디코딩할 때 원본 확장자를 모름
Base64 문자열만 받으면 원래 파일이 무슨 형식이었는지 알 방법이 없어 보일 수 있습니다.
하지만 대부분의 파일 형식은 맨 앞 몇 바이트에 고유한 시그니처(매직 넘버)를 가지고 있습니다. 디코딩한 결과의 앞부분 바이트를 확인하면 PNG·JPEG·GIF·PDF 같은 형식을 역으로 추정할 수 있습니다.
다만 시그니처가 없거나 겹치는 형식이라면 정확한 확장자를 알 수 없다는 한계도 있습니다.
실수 3: 공백·줄바꿈이 섞인 문자열을 그대로 디코딩
Base64 문자표에는 공백이나 줄바꿈 문자가 포함돼 있지 않습니다.
이메일 등 일부 시스템에서는 긴 Base64 값을 76자 단위로 줄바꿈해 저장하는 관행이 있습니다. 이 줄바꿈이 섞인 문자열을 그대로 디코딩 함수에 넣으면 유효하지 않은 문자로 인식돼 오류가 나거나 결과가 깨집니다.
디코딩 전에 공백과 줄바꿈부터 제거하면 이 문제를 피할 수 있습니다.
정리
- Base64는 8비트 데이터를 6비트씩 끊어 64개 문자로 표현하는 표기법이고, 이 구조 때문에 결과물이 원본보다 약 33%(4/3배) 커집니다.
- 원본 용량이 3바이트의 배수가 아니면 "=" 문자로 자리를 채워 출력 길이를 4의 배수로 맞춥니다.
- "data:MIME타입;base64," 접두사가 붙은 것이 Data URL, 이 접두사가 빠진 순수 인코딩 값이 Plain Base64입니다. 용도가 다릅니다.
- img 태그나 CSS에는 접두사가 포함된 Data URL을 통째로 넣고, 저장·전송용 데이터가 필요하면 Plain Base64를 씁니다.
- 디코딩 결과를 읽을 때는 앞부분 바이트 시그니처로 형식을 추정하고, 공백·줄바꿈이 섞인 문자열은 미리 정리해야 오류 없이 해석됩니다.
파일을 선택하면 브라우저 안에서 즉시 Base64로 변환되며, 서버로 전송되지 않고 최대 10MB까지 지원합니다.
자주 묻는 질문
Base64로 변환하면 항상 정확히 33% 커지나요?
원리는 항상 4/3 배율이지만 실제 증가율은 원본 크기와 패딩 여부에 따라 조금씩 달라집니다.
3바이트마다 4문자가 만들어지므로 이상적으로는 약 33.3% 증가합니다. 나머지가 1~2바이트 남아 "=" 패딩이 붙으면 아주 작은 파일일수록 그 비율이 소폭 더 커질 수 있습니다.
Data URL과 Plain Base64 중 어느 쪽을 복사해야 하나요?
HTML의 img src나 CSS의 background-image처럼 브라우저가 곧바로 이미지로 렌더링해야 하는 자리에는 접두사가 포함된 Data URL을 복사합니다.
API 요청 바디나 별도 저장소처럼 순수 인코딩 값만 필요한 경우에는 접두사가 빠진 Plain Base64를 씁니다.
디코딩한 파일이 이미지로 안 열립니다. 왜 그런가요?
가장 흔한 원인은 원본 문자열이 중간에 잘려서 복사됐거나 공백·줄바꿈이 섞인 채로 디코딩된 경우입니다.
추정된 MIME 타입이 실제 형식과 다르면 확장자가 맞지 않아 이미지 뷰어가 파일을 열지 못할 수도 있습니다. 원본 문자열이 온전한지, 시그니처로 추정한 형식이 맞는지부터 확인하면 원인을 좁힐 수 있습니다.
Base64 문자열 끝에 붙는 "=" 기호는 무엇인가요?
패딩(padding) 문자입니다. Base64는 출력 결과의 길이가 항상 4의 배수가 되도록 규칙을 정해두고 있습니다.
원본 데이터가 3바이트의 배수로 딱 나눠떨어지지 않을 때, 남는 자리를 "="로 채워 길이를 맞춥니다. 실제 데이터 값이 아니라 형식을 맞추기 위한 표시입니다.
