JWT 디코더
JSON Web Token을 디코딩해 내용을 확인합니다. 서명 검증에는 서명 키가 필요하며 서버 측에서 이루어져야 해요 — 이 도구는 표시만 합니다.
헤더
페이로드
서명
- 앱, API 응답, 또는 Authorization 헤더에서 JWT를 복사하세요.
- 상자에 붙여넣으세요. 입력하는 동안 자동으로 디코딩됩니다.
- 디코딩된 헤더와 페이로드를 확인하세요. 서명은 참고용으로 그대로 표시됩니다.
- 시간 클레임 요약(iat, exp, nbf)을 확인해 만료된 토큰을 찾아내세요.
어떤 도구인가요?
JSON Web Token은 점(.)으로 연결된 세 개의 base64url 인코딩된 세그먼트예요: header.payload.signature. 헤더와 페이로드는 JSON이고, 서명은 앞의 두 세그먼트를 HMAC 또는 RSA/ECDSA로 서명한 출력이에요. 이 도구는 점 단위로 분리해 각 부분을 base64url 디코딩하고 JSON을 파싱한 뒤, exp 같은 표준 시간 클레임을 사람이 읽을 수 있는 날짜로 보여 줍니다. 서명 검증은 하지 않아요 — 이유는 아래 FAQ에 있습니다.
예시
JWT 스펙의 예시 토큰 (HS256으로 서명, 비밀 키는 your-256-bit-secret):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c 디코딩된 헤더:
{
"alg": "HS256",
"typ": "JWT"
} 디코딩된 페이로드:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
} 내 JWT 서명이 왜 유효하지 않다고 뜨나요?
이 디코더는 서명을 확인하지 않지만(FAQ 참고), 서버 측 검증기가 토큰을 거부한다면 보통 아래 원인들이에요.
- 잘못된 비밀 키나 키. HMAC 비밀 키가 한 글자만 달라도 완전히 다른 서명이 나옵니다. 검증하는 서비스의 JWT_SECRET 환경 변수가 발급자와 일치하는지 확인하세요.
- 알고리즘 불일치. HS256으로 서명된 토큰은 RS256으로 검증할 수 없어요. 헤더의 alg 클레임을 확인하고, 검증기가 같은 알고리즘으로 설정되어 있는지 점검하세요.
- 만료된 토큰. 올바르게 서명된 JWT도 exp가 지나면 검증에 실패합니다. 디코딩 후 시간 클레임 요약에서 이를 명확하게 보여 줍니다.
- 시계 차이(clock skew). nbf(이전 불가)가 가까운 미래로 설정되어 있고 서버 시계가 조금 어긋나면 "토큰이 아직 유효하지 않음" 오류가 납니다. 검증기에 약간의 여유(예: 60초)를 허용하세요.
- 붙여넣은 토큰의 공백. 복사/붙여넣기 과정에서 앞뒤로 공백이나 줄바꿈이 섞이기도 해요. JWT는 앞뒤 공백 없이 정확히 header.payload.signature 형식이어야 합니다.
- alg: none. 헤더에 "alg": "none"이 있다면 해당 토큰은 서명이 없는 것이에요. 검증기에서 이런 토큰은 무조건 거부하세요 — 절대 유효한 것으로 취급하면 안 됩니다.
자주 묻는 질문
이 도구로 JWT 서명을 검증할 수 있나요?
아니요, 그리고 일부러 그렇게 만들었어요. 서명 검증에는 서명 키 — HMAC 공유 비밀이나 비대칭 공개 키 — 가 필요합니다. 그 키는 토큰을 발급하거나 소비하는 서버에 있어야지, 웹 페이지에 붙여넣을 대상이 아닙니다. 이 도구는 디코딩과 표시만 해요. 검증은 백엔드 서버에서 이루어져야 합니다.
JWT의 세 세그먼트 각각에는 무엇이 들어 있나요?
JWT는 header.payload.signature 구조예요. 헤더는 알고리즘(alg)과 토큰 유형을 기술한 JSON입니다. 페이로드는 sub, iat, exp 같은 클레임을 담은 JSON이에요. 서명은 앞의 두 세그먼트를 비밀 키 또는 개인 키로 서명해 base64url로 인코딩한 결과입니다. 앞의 두 부분은 단순히 인코딩된 것이지 암호화된 것이 아니에요.
제 JWT가 만료됐는지 어떻게 알 수 있나요?
페이로드의 exp 클레임을 보세요. 초 단위 Unix 타임스탬프입니다. Date.now() / 1000 이 exp보다 크면 토큰이 만료된 것이에요. 이 도구는 exp, iat, nbf 값을 페이로드 아래에 사람이 읽을 수 있는 날짜로 표시해서, 직접 계산하지 않아도 한눈에 확인할 수 있어요.
alg: none은 무엇이며 왜 위험한가요?
alg: none은 서명이 비어 있고 검증되지 않는 JWT 기능이에요. 과거에 많은 라이브러리가 이런 토큰을 받아들이는 바람에 공격자가 페이로드를 만들고 alg를 none으로 설정해 JWT를 위조할 수 있었어요. 이 헤더 값이 보이면 서명되지 않은 토큰이니, 이를 받아들이는 서버는 신뢰하지 마세요.
여기에 붙여넣은 JWT를 저장하나요?
아니요. 디코더에 붙여넣으신 토큰은 저장하지 않습니다. 넣으신 내용은 탭을 닫거나 새로고침하면 사라져요 — 로그도 남지 않고, 검사하신 토큰에 대한 기록은 저희 쪽에 전혀 없어요. 다만 JWT는 exp 전까지 접근 권한을 주니, 비밀번호처럼 취급하고 운영 토큰을 디버깅한 뒤에는 반드시 갱신하세요.
서명 부분에 읽을 수 없는 문자열이 나오는데, 정상인가요?
네, 정상입니다. 서명은 HMAC 혹은 RSA/ECDSA의 이진 출력이고, base64url로 인코딩되어 있어요. 사람이 읽으라고 만든 게 아니라 암호학적 검사 용도예요. 실제로 다루는 JSON 부분은 디코딩된 헤더와 페이로드입니다. 서명이 비어 있다면 토큰이 서명되지 않은 것(alg: none)이에요.