Base64 인코더·디코더

입력한 내용은 저장, 기록, 공유되지 않습니다.

텍스트를 Base64로 인코딩하거나 다시 디코딩합니다. 유니코드를 올바르게 처리하므로 한국어와 이모지도 깨지지 않고 변환됩니다.

사용 방법

  1. 인코딩 또는 디코딩을 선택합니다.
  2. 입력창에 텍스트나 Base64 문자열을 붙여넣습니다.
  3. 복사 버튼으로 결과를 복사합니다.

Base64는 무엇을 위한 것인가

Base64는 임의의 바이트를 어떤 텍스트 경로에서도 깨지지 않는 64개의 문자로 다시 씁니다. 세 바이트씩 가져와 그 24비트를 6비트씩 네 묶음으로 나누고, 각 묶음을 A-Z, a-z, 0-9와 기호 두 개 중 한 문자에 대응시킵니다. 입력 세 바이트마다 네 문자가 나오므로, 줄바꿈을 빼고도 결과는 원본보다 약 33% 커집니다.

목적은 전송이지 비밀 유지가 아닙니다. Base64는 원시 바이트를 망가뜨리는 경로를 위해 설계되었습니다. 최상위 비트를 잘라 내는 메일 시스템, 특정 제어 문자를 명령으로 취급하는 프로토콜, 순수 텍스트여야 하는 형식 같은 것들입니다. 암호화도 압축도 아니며, 인코딩된 내용은 디코딩하려는 사람이라면 누구나 쉽게 읽을 수 있습니다. Base64 문자열을 보호된 것처럼 다루는 것은 오해이며, 이 디코더로 그 사실을 쉽게 보여 줄 수 있습니다.

패딩과 두 가지 알파벳

입력이 세 바이트 단위로 딱 나누어지지 않으면, 출력 길이가 4의 배수가 되도록 = 문자 한두 개로 패딩합니다. 패딩을 생략하는 생성기도 있는데, 올바른 개수는 길이로 알 수 있으므로 이 디코더는 입력을 거부하지 않고 패딩을 다시 채웁니다.

표준 알파벳은 +와 /로 끝나는데, 둘 다 URL에서 의미가 있어 이스케이프하면 %2B와 %2F가 되므로 쿼리 문자열이나 파일 이름에서는 보기 흉하고 실수하기 쉽습니다. 그래서 RFC 4648 5절은 대신 -와 _를 쓰는 URL 안전 변형을 정의하며, =도 이스케이프가 필요하므로 보통 패딩을 생략합니다. JWT의 모든 세그먼트가 이 변형을 씁니다. 이 도구의 인코딩은 둘 다 제공하고, 디코딩은 붙여 넣은 문자열이 어느 알파벳인지 자동으로 감지하므로 따로 지정할 필요가 없습니다.

유니코드와 btoa의 함정

브라우저에는 수십 년 전부터 btoa 함수가 내장되어 있지만, 대부분의 사람이 생각하는 대로 동작하지 않습니다. btoa는 Latin-1을 기준으로 하므로 입력의 모든 문자는 코드 포인트가 256 미만이어야 하고, 그렇지 않으면 InvalidCharacterError를 던집니다. 한글 한 글자, 키릴 문자 이름, 이모지 하나만 넣어도 바로 실패합니다.

사람들이 가장 먼저 찾는 우회 방법은 인코딩 전에 문자열을 escape하는 것인데, 이는 ASCII가 아닌 문자를 다른 바이트 열로 바꿔 받는 쪽에서 깨진 글자로 디코딩되게 만듭니다. 올바른 방법은, 여기서 쓰는 것처럼, 먼저 TextEncoder로 텍스트를 UTF-8 바이트로 바꾼 뒤 그 바이트를 인코딩하는 것입니다. 그래서 이 도구에서는 어떤 문자 체계든 왕복해도 그대로 돌아옵니다.

디코딩은 그 반대로 진행하며, 추측하지 않습니다. 디코딩한 바이트가 유효한 UTF-8이 아니면, 대체 문자로 가득한 문자열을 보여 주는 대신 바이너리라고 알려 줍니다. 이는 대개 페이로드가 이미지, 압축 파일, protobuf 메시지, 암호문이라는 뜻이며, 텍스트로 읽을 것이 아니라 바이트로 저장해야 합니다.

사용하지 말아야 할 때

Base64는 아무것도 보호하지 않으므로 비밀 정보를 저장하는 데는 맞지 않습니다. 큰 리소스를 넣는 기본 방식으로도 좋지 않습니다. 이미지를 data URI로 만들면 크기가 3분의 1 늘어나고, 그것을 담은 문서와 별도로 캐시할 수 없으며, 파싱하는 동안 페이지를 막습니다.

Base64가 제 몫을 하는 곳은 작고 까다로운 경우입니다. PEM 형식의 인증서, 서명, JSON 본문 속 바이너리 필드, 짧은 인라인 아이콘, 토큰 세그먼트 같은 것들입니다.

3바이트가 들어가고 4문자가 나온다

한 번 손으로 계산해 보면 이 인코딩을 믿기가 쉬워집니다. ASCII 세 글자 Man을 예로 들면 바이트 값은 77, 97, 110이고 2진수로는 01001101, 01100001, 01101110입니다. 이 24비트를 한 줄로 늘어놓고 8비트 세 묶음이 아니라 6비트 네 묶음으로 자릅니다. 010011, 010110, 000101, 101110이 되죠. 각 묶음을 숫자로 읽으면 19, 22, 5, 46이고, A-Z, a-z, 0-9, +, / 알파벳에서 찾습니다. 인덱스 0이 A, 26이 a입니다. 결과는 TWFu입니다.

Base64의 모든 성질이 이 계산에서 나옵니다. 문자당 6비트이므로 알파벳이 정확히 64개입니다. 3바이트당 4문자이므로 출력이 3분의 1 커집니다. 그리고 패딩이 있는 이유는 마지막 묶음이 모자랄 수 있기 때문입니다. 1바이트가 남으면 두 문자와 ==가, 2바이트가 남으면 세 문자와 =가 붙습니다.

디코딩은 같은 과정을 거꾸로 밟는 일입니다. 그래서 길이가 4의 배수가 아닌 Base64 문자열은 패딩되었거나, 잘렸거나, 패딩을 일부러 뺀 인코더가 만든 것입니다.

실제 시스템에서 마주치는 곳

PEM 파일, 즉 인증서와 CSR과 개인 키는 머리글과 꼬리글 줄을 붙이고 64자마다 줄을 바꾼 Base64입니다. 이 줄 길이는 Base64가 요구하는 것이 아니라 MIME의 관례이며, 디코더는 줄바꿈을 무시하도록 되어 있습니다.

HTTP 기본 인증은 username:password를 Base64로 인코딩해 Authorization 헤더에 담습니다. 평문 HTTP에서 기본 인증을 쓰는 것이 비밀번호를 그대로 보내는 것과 같은 이유가 바로 이것입니다. 이메일 첨부 파일은 1992년 MIME이 정의된 이래 Base64를 써 왔고, 이유는 그때와 같습니다. 당시 메일 서버는 임의의 바이트를 안전하게 나르지 못했습니다.

data URI는 파일 전체를 문서에 넣습니다. data:image/png;base64, 뒤에 페이로드가 이어지는 형태죠. JSON API는 바이트를 담아야 하는 필드가 있으면 언제나 Base64를 씁니다. JSON에 바이너리 타입이 없기 때문입니다. JWT의 각 세그먼트는 패딩 없는 URL 안전 변형을 쓰고, Docker 설정과 Kubernetes 시크릿, 여러 CI 시스템은 자격 증명을 Base64로 인코딩해 저장합니다. 그것은 저장 방식이지 보호가 아닙니다.

크기, 메모리, 그리고 큰 파일

33% 증가는 눈에 띄는 비용이지만 대개 가장 작은 비용입니다. Base64 텍스트는 원래 바이트보다 압축이 덜 됩니다. 인코딩이 압축기가 활용했을 바이트 단위 패턴을 망가뜨리기 때문에, gzip으로 압축한 Base64 페이로드는 원본을 압축한 것보다 대체로 큽니다.

브라우저에서는 메모리가 더 날카로운 제약입니다. 파일을 인코딩하려면 바이트와 만들어진 문자열을 동시에 들고 있어야 하고 문자열은 3분의 1 더 크므로, 100MB 파일은 무엇을 보내기도 전에 수백 메가바이트가 필요할 수 있습니다. 파일을 조각으로 읽어 각각 인코딩하는 스트리밍 API가 이를 피하게 해 주며, 각 조각이 3바이트의 배수여야 패딩이 맨 끝에만 나타납니다.

큰 데이터에 대해서는 아예 인코딩하지 않는 것이 대개 더 나은 답입니다. 파일은 multipart form data나 원시 본문으로 보내고, Base64는 텍스트 형식 안을 통과해야 하는 작고 까다로운 값에 쓰세요.

가까운 알파벳들과 그들이 존재하는 이유

Base32는 32개 문자를 쓰고 출력이 입력보다 60% 커집니다. 손해처럼 들리지만, 사람이 소리 내어 읽거나 직접 입력해야 할 때는 이야기가 다릅니다. 대소문자를 구분하지 않고 혼동하기 쉬운 문자를 피하며, TOTP 비밀 키와 토르의 어니언 주소가 쓰는 방식입니다.

Base58은 0, O, I, l과 두 기호를 빼서 눈으로 보고 옮겨 적어도 헷갈리지 않게 만든 것입니다. 비트코인 주소가 가장 잘 알려진 용례입니다. Base85, 즉 Ascii85는 4바이트를 5문자에 담아 Base64보다 조밀하지만, 많은 형식이 이스케이프해야 하는 문장 부호를 씁니다. PDF와 PostScript 안에서 주로 살아남은 이유입니다.

패턴은 일관됩니다. 이들 모두 밀도와 전달 경로의 제약을 맞바꿉니다. Base64가 지금의 자리를 차지한 것은 수고를 들일 만큼 조밀하면서도 가장 넓은 범위의 텍스트 경로에서 안전하기 때문입니다.

건네받은 페이로드를 조사하기

정체를 알 수 없는 문자열을 만났을 때 먼저 던질 질문은 그것이 정말 Base64인가입니다. 믿을 만한 단서가 셋 있습니다. 길이가 4의 배수이거나 끝에 등호가 한두 개 붙어 있고, 문자가 영문자와 숫자와 기호 두 개로 제한되며, 디코딩하면 잡음이 아니라 읽을 수 있는 텍스트나 눈에 익은 파일 헤더가 나온다는 것입니다.

그 헤더는 인코딩된 모습 그대로 알아볼 수 있으면 유용합니다. 저장하기 전에 내용이 무엇인지 알 수 있으니까요. 디코딩 결과가 89 50 4E 47로 시작하면 PNG, FF D8 FF면 JPEG, 50 4B 03 04면 zip이며 여기에는 모든 Office 문서가 포함됩니다. 25 50 44 46이면 PDF입니다. Base64 형태에서는 iVBORw0KGgo로 시작하면 PNG, /9j/면 JPEG이고, 둘 다 API 페이로드와 data URI에서 끊임없이 등장합니다.

디코딩해도 텍스트도 아니고 아는 헤더도 아니라면 설명은 보통 셋 중 하나입니다. URL 안전 Base64를 표준 알파벳으로 디코딩하고 있거나, 두 번 인코딩되었거나, Base64가 아니라 16진수나 base32인 경우입니다. 각각은 1초면 구별됩니다. URL 안전 문자열에는 마이너스나 밑줄이 들어 있고, 이중 인코딩된 것은 디코딩하면 또 Base64처럼 생긴 문자열이 나오며, 16진수는 열여섯 개 문자만 씁니다.

자주 묻는 질문

한글 같은 비영어 문자도 처리되나요?
네. 입력은 인코딩 전에 UTF-8로 변환되므로 한국어·일본어·중국어·이모지 모두 정확하게 변환됩니다. 많은 도구가 브라우저의 btoa 함수를 그대로 사용해 Latin-1 밖의 문자에서 오류를 냅니다.
URL 안전 Base64란 무엇인가요?
RFC 4648에 정의된 변형으로 +를 -로, /를 _로 바꾸고 끝의 = 패딩을 생략합니다. URL이나 파일 이름에 그대로 쓸 수 있습니다. 인코딩 시 체크하면 되고, 디코딩은 두 형식을 자동으로 인식합니다.
디코딩 결과가 바이너리 데이터라고 나오는 이유는?
Base64 자체는 유효하지만 내용이 UTF-8 텍스트가 아닌 경우입니다. 보통 이미지, 압축 파일, 암호화된 데이터입니다. 깨진 문자를 보여주는 대신 상황을 그대로 알려줍니다.
= 패딩 문자를 반드시 넣어야 하나요?
아닙니다. 빠진 =는 자동으로 채워지며, 붙여넣은 내용의 공백과 줄바꿈도 무시됩니다.
데이터가 서버로 전송되나요?
아닙니다. 인코딩과 디코딩 모두 브라우저에서 실행되므로 데이터가 기기를 벗어나지 않습니다. 토큰이나 자격 증명도 안전하게 다룰 수 있습니다.

마지막 업데이트:

문제 신고

진행 단계, 예상 결과, 실제 결과를 적어 주세요. 비밀 정보와 개인 정보는 삭제해 주세요.

관련 도구