현재 언어: 한국어 영어로 보기

JWT 디코더

JSON Web Token을 디코딩해 내용을 확인합니다. 서명 검증에는 서명 키가 필요하며 서버 측에서 이루어져야 해요 — 이 도구는 표시만 합니다.

  1. 앱, API 응답, 또는 Authorization 헤더에서 JWT를 복사하세요.
  2. 상자에 붙여넣으세요. 입력하는 동안 자동으로 디코딩됩니다.
  3. 디코딩된 헤더와 페이로드를 확인하세요. 서명은 참고용으로 그대로 표시됩니다.
  4. 시간 클레임 요약(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)이에요.