본문으로 바로가기

JWT 디코더

JWT를 붙여넣으면 header와 payload를 JSON으로 풀고, exp·iat·nbf를 날짜와 시각으로 바꿔 만료 여부와 함께 보여 줍니다. 서명은 검증하지 않습니다.

서명 검증 안 됨

이 도구는 내용을 읽기만 할 뿐 서명을 검증하지 않습니다. 운영 환경의 토큰이나 실제 비밀키는 이 도구를 포함한 어떤 온라인 도구에도 붙여넣지 마세요.

JWT를 붙여넣으면 header와 payload가 해석됩니다.

입력한 내용은 이 브라우저 안에서만 처리되며 서버로 전송되지 않습니다. 어떻게 동작하나요?

JWT의 세 부분과 디코딩된 페이로드; 디코딩은 서명 검증과 다름

사용 방법

“JWT 붙여넣기” 칸에 토큰을 넣으면 아래 다섯 가지가 나옵니다.

  1. 만료 알림: payload에 exp가 있으면 결과 맨 위에 “만료 전” 또는 “만료됨”과 exp 시각이 표시됩니다. 이 알림은 exp와 기기 시계만 비교한 결과입니다. nbf의 시작 시각이나 서명 검증 결과를 뜻하지 않습니다.
  2. Header, Payload: 각 부분을 들여쓰기한 JSON으로 보여 줍니다. 제목 옆 버튼으로 따로 복사할 수 있습니다.
  3. 서명 알고리즘: header의 alg 값입니다. alg가 없거나 문자열이 아니면 “표시 없음”으로 나옵니다.
  4. Signature (원문 그대로, 검증 안 함): 세 번째 조각을 손대지 않고 그대로 보여 줍니다.
  5. 등록된 클레임: exp (만료 시각), iat (발급 시각), nbf (유효 시작 시각)를 날짜와 시각으로 바꿔 보여 줍니다. payload에 없는 항목은 “없음”으로 표시됩니다.

날짜와 시각은 이 브라우저의 시간대로 표시됩니다. 서버 로그가 UTC라면 시차만큼 다르게 보입니다.

예시로 읽어 보기

아래 토큰을 붙여넣어 보세요.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQyIiwiaWF0IjoxNzY3MjI1NjAwLCJleHAiOjE3NjcyMjkyMDB9.c2lnbmF0dXJl
  • Header는 {"alg": "HS256", "typ": "JWT"}, 서명 알고리즘은 HS256으로 나옵니다.
  • Payload는 {"sub": "user-42", "iat": 1767225600, "exp": 1767229200}입니다.
  • iat 1767225600은 2026년 1월 1일 00:00:00(UTC), exp 1767229200은 그로부터 한 시간 뒤인 01:00:00(UTC)입니다. UTC+9 시간대의 브라우저에서는 각각 오전 9:00:00과 오전 10:00:00으로 표시됩니다. 이미 지난 시각이므로 맨 위 알림은 “만료됨”입니다.
  • 세 번째 조각 c2lnbmF0dXJl는 진짜 서명이 아니라 signature라는 글자를 Base64URL로 적은 것입니다. 그런데도 오류 없이 해석됩니다. 이 도구가 서명을 전혀 확인하지 않는다는 것을 보여 주는 예입니다.

JWT의 세 부분

JWT는 점(.)으로 나뉜 세 조각(header.payload.signature)입니다. header에는 서명 알고리즘(alg)과 토큰 종류(typ)가, payload에는 사용자 ID·권한·만료 시각 같은 클레임이 들어 있습니다. 클레임은 토큰이 담고 있는 이름과 값 한 쌍을 말합니다.

header와 payload는 JSON을 Base64URL로 옮겨 적은 것일 뿐 암호화된 것이 아닙니다. 토큰을 손에 넣은 사람은 키 없이도 내용을 읽을 수 있으므로, 이메일이나 내부 권한 정보가 든 토큰을 메신저나 이슈 트래커에 그대로 올리면 그 내용까지 함께 공개됩니다. 마지막 signature 조각만 발급자의 키로 만든 값이고, header와 payload가 발급 뒤에 바뀌지 않았는지 확인하는 데 쓰입니다.

이 도구가 확인하지 않는 것

  • 서명: 검증하려면 발급자의 비밀키(HMAC 계열)나 공개키(RSA·ECDSA 계열)가 필요한데, 이 도구에는 키를 넣는 칸이 없습니다. 내용이 정상적으로 보인다고 해서 진짜 토큰이라는 뜻은 아닙니다.
  • 만료 판정의 기준 시계: “만료 전”과 “만료됨”은 이 기기의 시계와 비교한 결과입니다. 기기 시계가 틀리면 판정도 틀립니다.
  • 여유 시간: 현재 시각이 exp와 같아지는 순간부터 “만료됨”으로, nbf보다 앞이면 “사용 시작 시각 전”으로 표시합니다. RFC 7519는 서버 간 시계 차이를 감안해 보통 몇 분 이내의 여유를 둘 수 있다고 하지만, 이 도구는 여유를 두지 않습니다. 그래서 서버가 아직 받아 주는 토큰이 여기서는 만료로 보일 수 있습니다.
  • 그 밖의 클레임: iss(발급자)나 aud(대상) 같은 값은 Payload에 그대로 보일 뿐, 맞는 값인지 따지지 않습니다.

실제 접근 제어는 서버의 검증 결과를 따릅니다. 운영 환경의 토큰은 유효 기간 동안 그 자체가 출입증이므로, 화면의 경고대로 온라인 도구에 붙여넣지 않는 편이 안전합니다.

exp, iat, nbf 값 읽는 법

RFC 7519는 이 세 클레임의 값을 1970년 1월 1일 00:00:00(UTC)부터 센 초로 적도록 정합니다. 이 형식을 NumericDate라고 부릅니다. 이 도구는 값이 숫자일 때만 날짜로 바꿉니다.

  • "exp": "1767229200"처럼 따옴표로 감싼 문자열이면 날짜로 읽지 않고 “없음”으로 표시합니다. Payload의 JSON에는 값이 그대로 보이므로, 클레임이 있는데도 “없음”이라면 따옴표를 확인하세요.
  • 자바스크립트 날짜로 나타낼 수 없을 만큼 큰 숫자도 “없음”으로 표시합니다.
  • 상태가 붙는 것은 exp와 nbf뿐입니다. iat는 시각만 보여 줍니다.

해석되지 않을 때

화면에 나오는 오류 흔한 원인
JWT는 점(.)으로 나눈 세 부분(header.payload.signature)이어야 하는데 N개가 나왔습니다 토큰 일부만 복사한 경우. 암호화된 토큰(JWE)은 조각이 다섯 개라 이 도구로 읽을 수 없습니다
header(또는 payload) 부분을 Base64URL로 해석할 수 없습니다 앞에 “Bearer “가 붙은 경우, 중간에 줄바꿈이 낀 경우, +·/·=가 들어간 일반 Base64인 경우
header(또는 payload) 부분은 디코딩됐지만 올바른 JSON이 아닙니다 JWT가 아닌 다른 값을 점으로 이어 붙인 경우

Base64URL은 Base64의 +와 /를 -와 _로 바꾸고 끝의 =를 뗀 표기입니다. 이 도구는 A ~ Z, a ~ z, 0 ~ 9, -, _ 말고 다른 글자가 있으면 해석하지 않습니다.

참고 자료

자주 묻는 질문

Authorization 헤더 값을 "Bearer "까지 통째로 붙여넣어도 되나요?

안 됩니다. "Bearer eyJ..."처럼 앞에 다른 글자가 붙어 있으면 "header 부분을 Base64URL로 해석할 수 없습니다"라는 오류가 나옵니다. eyJ로 시작하는 토큰만 남기고 붙여넣으세요. 토큰 앞뒤의 공백과 줄바꿈은 무시하지만, 토큰 중간에 줄바꿈이나 공백이 끼어 있으면 같은 오류가 납니다.

exp가 분명히 숫자인데 수만 년 뒤 날짜로 나옵니다. 왜 그런가요?

exp에 초가 아니라 밀리초가 들어 있을 때 생기는 일입니다. 이 도구는 값을 표준대로 초로 읽기 때문에, 예를 들어 1767229200(2026년 1월 1일)을 밀리초로 적은 1767229200000은 57971년의 날짜로 표시되고 상태도 "만료 전"으로 나옵니다. 발급하는 쪽에서 밀리초를 초로 바꿔 넣어야 합니다.

exp가 없는 토큰은 어떻게 표시되나요?

결과 맨 위의 만료 알림은 나오지 않고 exp 칸에는 "없음"이 표시됩니다. nbf가 있으면 해당 칸에만 "사용 시작 시각 전" 또는 "사용 시작 시각 지남"이 붙습니다. iat에는 시각만 표시됩니다.

header의 alg 값이 "none"인 토큰을 봤는데 위험한가요?

alg가 none이면 서명 없이 누구나 원하는 내용으로 토큰을 만들 수 있습니다. 이 도구는 그런 토큰도 그대로 해석하고 "서명 알고리즘" 아래에 경고를 띄웁니다. 서버가 이런 토큰을 받아들이면 인증을 우회당할 수 있으니, 검증 코드가 alg none을 명시적으로 거부하는지 확인하세요.

최종 수정일: