JWT 디코딩 사용법
eyJ로 시작하는 긴 토큰을 입력란에 붙여 넣습니다. 개발자 도구나 Postman에서 복사한Authorization: Bearer …헤더 전체, 토큰을 감싼 따옴표, 중간의 줄바꿈은 알아서 정리합니다.- 디코딩된 헤더와 페이로드를 정렬된 JSON으로 확인하고, 맨 위의 만료 상태와 표준 클레임을 봅니다. 날짜는 내 시간대(한국이라면 KST)로 바뀌고, 지금부터 얼마나 지났는지 또는 남았는지도 함께 나옵니다.
- 서명을 검증하려면 키를 넣습니다. HS256·HS384·HS512는 공유 비밀 키, RS·PS·ES·EdDSA는 공개 키를 PEM 블록, JWK, JWKS 전체 중 하나로 넣으면 올바른 서명 또는 잘못된 서명이 표시됩니다.
JWT 토큰의 구조
JSON 웹 토큰(RFC 7519)은 base64url 텍스트 세 조각을 점으로 이은 헤더.페이로드.서명입니다. 헤더와 페이로드는 JSON 객체를 인코딩만 했을 뿐 암호화하지 않았기 때문에, {"를 인코딩한 eyJ로 늘 시작합니다. 헤더에는 서명 알고리즘(alg)이, 페이로드에는 사용자나 세션에 대한 정보인 클레임이 들어 있습니다. 서명은 앞의 두 부분을 쓰인 그대로 계산한 값이라, 한 글자만 바뀌어도 검증에 실패합니다.
| 클레임 | 이름 | 뜻 |
|---|---|---|
iss | 발급자 | 토큰을 만들고 서명한 곳. 흔히 로그인 서버의 URL |
sub | 주체 | 토큰이 가리키는 대상. 보통 회원 ID |
aud | 대상 | 토큰을 받아들여야 하는 서비스. 다른 API용 토큰은 거부해야 함 |
exp | 만료 시각 | 이 시각이 지나면 토큰을 거부해야 함 |
nbf | 시작 시각 | 이 시각 전에는 토큰을 거부해야 함 |
iat | 발급 시각 | 토큰을 만든 시각 |
jti | JWT ID | 같은 토큰의 재사용을 막기 위한 고유 ID |
세 날짜는 1970년 1월 1일(UTC)부터 센 초, 곧 Unix 타임스탬프입니다. 13자리라면 밀리초로 잘못 넣은 것이며, 디코더가 이를 짚어 줍니다. 서버는 보통 1~2분의 시계 오차를 허용하지만 여기 표시되는 상태는 오차를 두지 않습니다. 카카오 로그인처럼 OpenID Connect를 지원하는 소셜 로그인이 발급하는 ID 토큰도 JWT라서, 여기에 붙여 넣으면 iss, aud, exp를 바로 확인할 수 있습니다.
예시로 보기
JSON 웹 서명 표준인 RFC 7515는 첫 번째 예시(부록 A.1)에서 다음 토큰에 서명합니다.
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
헤더는 { "typ": "JWT", "alg": "HS256" }로 HMAC SHA-256 토큰이고, 페이로드는 { "iss": "joe", "exp": 1300819380, "http://example.com/is_root": true }입니다. 발급자는 “joe”, 비공개 클레임이 하나(http://example.com/is_root) 있으며, exp 1300819380은 2011년 3월 22일 18:43:00 UTC, 한국 시간으로는 3월 23일 오전 3시 43분입니다. 2026년 10월에 디코딩하면 상태가 ‘만료됨(16년 전)’으로 나옵니다. 서명을 검증하려면 RFC의 키를 JWK로 넣으세요.
{"kty":"oct","k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"}
그러면 서명이 올바르다고 나오고, 페이로드의 글자를 하나만 바꿔도 잘못된 서명이 됩니다. 입력란에 처음 들어 있는 토큰은 jwt.io의 유명한 예시이며 비밀 키는 your-256-bit-secret입니다. 이 키는 19바이트라 RFC 7518이 HS256에 요구하는 32바이트보다 짧으므로, 검증하면 디코더가 짧다고 표시합니다. Spring에서 많이 쓰는 jjwt 라이브러리도 HS256 키가 256비트보다 짧으면 WeakKeyException으로 거부하니, 운영 키는 32바이트 이상의 무작위 값으로 만드세요.
서명 검증
- HS256, HS384, HS512는 서명과 검증에 같은 비밀 키 하나를 씁니다. 키를 그대로 입력하거나, Base64로 인코딩된 키라면 유형이
oct인 JWK로 넣으세요.application.yml의 키 문자열을 복사할 때 끝에 공백이 붙지 않았는지도 확인하세요. - RS256, PS256(RSA)과 ES256(타원 곡선 P-256, ES384·ES512는 P-384·P-521)은 개인 키로 서명하고 짝이 되는 공개 키로 검증합니다. 로그인 제공자는
/.well-known/openid-configuration에 적힌jwks_uri에 공개 키를 JWKS로 공개하며, 그 JSON을 붙여 넣으면 디코더가 토큰의kid와 맞는 키를 고릅니다. - 검증은 HTTPS를 지키는 것과 같은 브라우저 내장 Web Crypto로 합니다. 키는 확인에만 쓰이고 서명, 저장, 전송에는 쓰이지 않습니다.
보안 팁
- 디코딩은 검증이 아닙니다. 누구나 JWT를 읽을 수 있고, 누구나 원하는 클레임으로 토큰을 만들 수 있습니다. 서버에서 서명,
exp,iss,aud를 확인한 뒤에만 믿으세요. - alg “none”은 거부하세요. 서명되지 않은 토큰이라, 받아들이면 공격자가 아무 신원이나 위조할 수 있습니다(RFC 8725).
- 알고리즘을 고정하세요. RSA 공개 키를 ‘비밀 키’로 삼아 HS256 토큰을 검증하는 서버는 위조 토큰에 속을 수 있습니다(알고리즘 혼동 공격). 이 디코더는 그런 조합을 거부합니다.
- 운영 중인 토큰은 웹사이트에 붙여 넣지 마세요. 이 페이지를 포함해서입니다. 여기서는 모든 것을 기기 안에서 처리하고 아무것도 보내지 않지만, 유효한 토큰은 살아 있는 동안 비밀번호와 같습니다. 가능하면 만료된 토큰이나 테스트 토큰을 쓰고, 개인 키는 절대 넣지 마세요.
- 페이로드에 개인정보를 넣지 마세요. 토큰을 가진 누구나 읽을 수 있습니다. 클레임 자체를 숨겨야 한다면 다섯 부분으로 된 암호화 JWT(JWE)를 쓰세요. 디코더는 JWE를 알아보고 헤더를 보여 줍니다.
base64url 조각 하나를 직접 풀어 보려면 Base64 디코딩을, 페이로드를 더 자세히 살펴보려면 JSON 정렬을 쓰세요. URL 쿼리에 실린 토큰은 먼저 URL 디코딩으로 풀면 됩니다.
자주 묻는 질문
여기에 JWT를 붙여 넣어도 안전한가요?
토큰은 브라우저의 JavaScript로 디코딩·검증되며 서버로 전송되지 않고 저장되지도 않습니다. 그래도 유효한 토큰은 임시 비밀번호와 같으므로, 어떤 웹사이트에서든 만료된 토큰이나 테스트 토큰을 쓰는 습관이 가장 안전합니다.
비밀 키 없이 JWT를 디코딩할 수 있나요?
네. 헤더와 페이로드는 base64url로 인코딩만 되어 있어 키 없이 읽을 수 있습니다. 비밀 키나 공개 키는 서명을 검증할 때, 곧 토큰이 진짜이고 바뀌지 않았는지 증명할 때만 필요합니다.
“잘못된 서명”이 나오는 이유는?
서명 뒤에 토큰이 바뀌었거나, 서명한 키가 아니기 때문입니다. 다른 환경(개발·운영)의 비밀 키, 빠지거나 더 들어간 글자, 키 교체 뒤의 다른 공개 키, Base64로 먼저 디코딩해야 하는 키(oct 유형 JWK로 넣으세요)가 흔한 원인입니다.
JWT, JWS, JWE는 무엇이 다른가요?
JWS(RFC 7515)는 세 부분으로 된 서명된 데이터, JWE(RFC 7516)는 다섯 부분으로 된 암호화된 데이터입니다. JWT(RFC 7519)는 그중 하나에 실린 클레임 집합이며 거의 언제나 JWS라서, ‘JWT’라고 하면 보통 서명된 토큰을 뜻합니다.
토큰이 언제 만료되는지 어떻게 아나요?
만료(exp)를 보세요. 내 시간대의 날짜와 함께 ‘2일 후’, ‘3시간 전’처럼 표시됩니다. exp 클레임이 없는 토큰은 저절로 만료되지 않으므로 액세스 토큰으로는 위험합니다.
최종 수정일: 2026년 10월 16일