Base64와 Base64URL 차이: JWT에서 왜 문자가 다른가
Base64와 Base64URL은 비슷해 보이지만 그대로 섞어 쓰면 디코딩 오류가 납니다. 특히 JWT를 디코딩할 때 +, /, =가 보이지 않는 이유를 이해하지 못하면 “토큰이 깨졌다”라고 오해하기 쉽습니다. 실제로는 인코딩 규칙이 조금 다를 뿐입니다.
1) Base64와 Base64URL의 핵심 차이
일반 Base64는 +, /, = 문자를 사용합니다. 반면 Base64URL은 URL에서 안전하게 쓰기 위해 +를 -로, /를 _로 바꾸고 패딩 =를 생략할 수 있습니다. 즉 본질은 비슷하지만 표현 방식이 다릅니다.
2) 왜 URL 안전 버전이 필요한가
일반 Base64의 +, /, = 문자는 URL 쿼리 문자열, 경로, 쿠키, 헤더 같은 환경에서 해석 충돌을 일으킬 수 있습니다. 그래서 JWT처럼 웹 전송이 많은 포맷은 Base64URL을 사용합니다. 이 덕분에 별도 URL 인코딩 없이도 비교적 안전하게 전달할 수 있습니다.
3) JWT에서 자주 보는 모습
JWT의 header.payload.signature 중 앞의 두 파트는 Base64URL로 인코딩되어 있습니다. 그래서 일반 Base64 디코더에 그대로 넣으면 패딩이 없거나 문자셋이 달라 실패할 수 있습니다. -와 _를 원래 문자로 되돌리고, 필요한 패딩을 보충한 뒤 디코딩해야 합니다.
4) 패딩(=)이 없는 이유
Base64URL은 패딩을 생략해도 원복할 수 있는 경우가 많아서, 토큰 길이를 조금 줄이고 문자열을 단순하게 만들기 위해 =를 제거하는 경우가 흔합니다. 하지만 모든 디코더가 이를 자동으로 처리하지는 않습니다. 그래서 직접 디코딩 코드를 짤 때는 길이를 4의 배수로 맞추는 패딩 복원이 필요합니다.
5) 가장 흔한 실패 사례
- 일반 Base64 디코더에 JWT payload를 그대로 넣음
-,_를 변환하지 않음- 패딩 복원을 하지 않음
- Base64URL과 URL 인코딩을 같은 개념으로 착각
여기서 마지막 오해가 특히 많습니다. Base64URL은 URL 인코딩이 아니라, URL에 안전한 문자셋을 쓰는 Base64 변형입니다.
6) 빠른 판별 방법
문자열에 -, _가 보이고 +, /가 거의 없으며 패딩 =가 빠져 있다면 Base64URL일 가능성이 큽니다. JWT의 각 세그먼트는 거의 항상 이 방식입니다. 반대로 파일 첨부나 data URL에서 보이는 일반 Base64는 +, /, =를 그대로 쓰는 경우가 많습니다.
7) 디버깅 순서
- 입력 문자열이 JWT 일부인지, 일반 Base64 텍스트인지 구분
-와_가 있는지 확인- 길이가 4의 배수인지 확인
- 필요하면 패딩을 보충한 뒤 디코딩
- 디코딩 후 UTF-8 JSON인지 바이너리인지 확인
이 순서만 알아도 디코딩 실패를 대부분 줄일 수 있습니다.
8) 실무에서 왜 중요할까
JWT, 서명 토큰, 일부 OAuth 파라미터처럼 보안 관련 문자열은 Base64URL을 자주 씁니다. 반면 파일 업로드, 이메일 첨부, data URL은 일반 Base64를 많이 씁니다. 둘을 구분하지 못하면 토큰 파싱과 파일 복원 로직이 서로 꼬일 수 있습니다.
9) 체크리스트
- 문자열이 일반 Base64인지 Base64URL인지 먼저 구분했는가
-,_를 적절히 치환했는가- 패딩이 필요한 환경인지 확인했는가
- JWT 디코딩 결과를 서명 검증으로 오해하지 않았는가
10) 관련 도구
일반 문자열 변환은 Base64 Encode/Decode로 확인할 수 있고, JWT 구조 확인은 JWT Decoder가 더 적합합니다. 토큰은 Base64URL이라는 점을 전제로 보면 디버깅이 훨씬 빨라집니다.