본문으로 건너뛰기
소이툴즈

JWT 디코더

JWT의 헤더와 페이로드를 열어 클레임을 확인하고 만료 시각을 사람이 읽을 수 있는 형태로 보여줍니다.

서명은 검증하지 않습니다. 검증에는 비밀키나 공개키가 필요한데, 그 키를 웹 도구에 붙여넣도록 유도하는 것 자체가 위험한 관행이라 의도적으로 제외했습니다. 디코딩이 된다고 해서 유효한 토큰이라는 뜻은 아닙니다. 디코딩은 전적으로 브라우저 안에서 이루어집니다. 그렇더라도 운영 환경의 유효한 토큰은 어떤 온라인 도구에도 붙여넣지 않는 것이 안전합니다.

JWT는 어떻게 생겼나

JWT(JSON Web Token)는 점(.)으로 구분된 세 부분으로 이루어집니다.

eyJhbGciOiJIUzI1NiJ9 . eyJzdWIiOiIxMjM0In0 . 4pcPyMD09olPSyXnrXCjTw
    헤더                   페이로드              서명

앞의 두 부분은 URL-safe Base64로 인코딩된 JSON입니다. 암호화가 아니라 인코딩이므로 누구나 내용을 볼 수 있습니다.

헤더에는 서명 알고리즘(alg)과 토큰 타입(typ)이 들어갑니다.

페이로드에는 클레임(claim)이 들어갑니다. 사용자 ID, 권한, 만료 시각 같은 정보입니다.

서명은 앞의 두 부분을 비밀키로 서명한 값입니다. 내용이 위조되지 않았음을 증명합니다.

도구 사용법

토큰을 붙여 넣으면 헤더와 페이로드가 JSON으로 펼쳐지고, exp·iat·nbf 같은 시각 클레임은 사람이 읽는 날짜로 함께 표시됩니다. exp가 있으면 지금 기준으로 만료됐는지를 위에 크게 알려 주므로, 로그인이 자꾸 풀리는 원인이 토큰 만료인지 바로 확인할 수 있습니다. 표준 클레임에는 한국어 설명이 붙고, 그 밖의 값은 키 이름 그대로 나옵니다.

토큰은 브라우저 안에서만 디코딩되고 어디로도 전송되지 않습니다. 그래도 실제 서비스의 유효한 토큰은 그 자체가 로그인 증표이므로, 붙여 넣은 뒤 화면을 캡처해 공유하는 일은 피하세요. 문제를 보고할 때는 서명 부분을 지우거나 만료된 토큰을 쓰는 것이 안전합니다.

토큰은 어디서 찾나

브라우저 개발자 도구 → 애플리케이션(Application) 탭 → 로컬 스토리지나 쿠키에서 token, access_token, Authorization 같은 이름으로 저장된 값을 찾습니다. 네트워크 탭에서 API 요청을 열면 요청 헤더의 Authorization: Bearer eyJ...에도 있습니다. Bearer 는 접두어이므로 빼고 eyJ부터 붙여 넣으면 됩니다.

디코딩에 실패하면 대개 복사 범위 문제입니다. 세 부분이 아니라는 안내가 나오면 앞뒤에 따옴표나 Bearer가 섞였거나 끝이 잘린 것이고, 헤더나 페이로드를 디코딩하지 못했다는 안내가 나오면 JWT가 아닌 다른 형식의 토큰(세션 ID, 불투명 토큰)일 가능성이 큽니다. eyJ로 시작하지 않는 토큰은 JWT가 아닙니다. eyJ는 {"를 Base64로 인코딩한 앞 세 글자라 모든 JWT가 이렇게 시작합니다.

표준 클레임

JWT 표준(RFC 7519)이 정의한 클레임입니다.

| 클레임 | 의미 | |---|---| | iss | 발급자 (issuer) | | sub | 주체 — 보통 사용자 ID | | aud | 이 토큰을 받을 대상 (audience) | | exp | 만료 시각 | | nbf | 이 시각 이전에는 사용 불가 (not before) | | iat | 발급 시각 | | jti | 토큰 고유 ID |

이 밖에 서비스가 필요로 하는 값(이름, 역할, 테넌트 ID 등)을 자유롭게 넣을 수 있습니다.

exp는 초 단위입니다 (밀리초 아님)

가장 자주 발생하는 버그입니다. exp, iat, nbf는 모두 1970년 1월 1일 UTC부터 흐른 초(second) 단위입니다.

그런데 자바스크립트의 Date.now()는 밀리초를 반환합니다. 이 값을 그대로 넣으면 1,000배 큰 값이 되어 서기 5만 년 같은 날짜가 나옵니다.

Math.floor(Date.now() / 1000)   ← 올바른 방법
Date.now()                       ← 1000배 어긋남

이 디코더는 값이 지나치게 크면 밀리초를 넣은 것은 아닌지 알려줍니다.

서명 알고리즘 읽는 법

헤더의 alg 값으로 서명 방식을 알 수 있습니다.

| alg | 방식 | 키 | | ------- | ----------------------------- | ---------------------------- | | HS256 | HMAC + SHA-256 (대칭) | 발급자와 검증자가 같은 비밀키 | | RS256 | RSA + SHA-256 (비대칭) | 비밀키로 서명, 공개키로 검증 | | ES256 | ECDSA + SHA-256 (비대칭) | 타원곡선 키, 서명이 짧음 | | none | 서명 없음 | 검증 불가, 거부해야 함 |

HS256은 검증하는 쪽도 비밀키를 알아야 해서 한 서비스 안에서 쓰기 좋고, RS256과 ES256은 공개키만 배포하면 여러 서비스가 검증할 수 있어 소셜 로그인과 OAuth 제공자가 주로 씁니다. 구글이나 카카오 로그인의 ID 토큰을 이 도구에 넣어 보면 헤더에 RS256과 키 식별자 kid가 있고, 그 공개키는 제공자의 JWKS 주소에서 받습니다. 키가 주기적으로 바뀌므로 kid로 맞는 키를 골라야 합니다.

왜 서명 검증은 안 해주나요

서명을 검증하려면 **비밀키(HS256)나 공개키(RS256)**가 필요합니다.

그런데 사용자에게 서명 키를 웹 도구에 붙여넣도록 유도하는 것 자체가 위험한 관행입니다. 그 키 하나면 누구든 유효한 토큰을 위조할 수 있기 때문입니다. 그래서 이 도구는 디코딩만 제공합니다.

기억하실 점은 디코딩이 된다고 해서 유효한 토큰이 아니라는 것입니다. 서명이 완전히 엉터리여도 헤더와 페이로드는 읽힙니다. 실제 검증은 서버에서 해야 합니다.

JWT에 민감한 정보를 넣지 마세요

페이로드는 암호화되지 않습니다. Base64를 되돌리면 누구나 내용을 봅니다.

따라서 다음은 절대 넣으면 안 됩니다.

  • 비밀번호
  • 주민등록번호, 카드번호
  • 내부 시스템의 상세 정보

서명은 위조를 막을 뿐 내용을 숨기지 않습니다. 내용까지 감춰야 한다면 JWE(암호화된 JWT)를 써야 합니다.

alg: none 공격

과거 여러 JWT 라이브러리에 있던 심각한 취약점입니다. 헤더의 alg를 none으로 바꾸고 서명 부분을 비우면, 검증을 건너뛰고 토큰을 받아들이는 구현이 있었습니다.

공격자가 페이로드의 사용자 ID를 관리자로 바꿔 넣으면 그대로 통과됩니다.

방어 방법은 서버가 기대하는 알고리즘을 고정하는 것입니다. 토큰이 알려주는 alg를 그대로 믿으면 안 됩니다.

토큰이 길어지면 생기는 일

JWT는 요청마다 통째로 전송됩니다. 페이로드에 권한 목록, 프로필, 설정값을 계속 넣다 보면 토큰이 수 KB로 불어나고, 모든 API 호출에 그만큼의 헤더가 붙습니다. 쿠키에 담는 경우 브라우저와 서버의 쿠키 크기 한도(대개 4KB)에 걸려 로그인이 조용히 실패하기도 합니다. 이 도구에 넣었을 때 페이로드가 화면을 가득 채운다면 설계를 다시 볼 신호입니다. 토큰에는 사용자 ID와 역할처럼 검증에 꼭 필요한 값만 두고, 나머지는 서버에서 ID로 조회하는 편이 안전하고 가볍습니다.

토큰이 만료되면

exp가 지난 토큰은 서버가 거부합니다. 이때는 보통 리프레시 토큰으로 새 액세스 토큰을 발급받습니다.

액세스 토큰은 수명을 짧게(15분~1시간) 두고, 리프레시 토큰은 길게(2주~한 달) 두는 것이 일반적입니다. 액세스 토큰이 유출되어도 피해 기간을 줄이기 위해서입니다.

한 가지 알아둘 점은 JWT는 서버에서 즉시 무효화하기 어렵다는 것입니다. 서버가 상태를 저장하지 않기 때문입니다. 강제 로그아웃이 필요하다면 별도의 블랙리스트를 두거나 토큰 수명을 짧게 가져가야 합니다.

함께 확인하면 좋은 것

Base64 자체를 다루려면 Base64 인코더·디코더를, 페이로드 JSON을 정리하려면 JSON 포맷터를 이용하세요.

자주 묻는 질문

더 읽을 글

  • JWT 구조와 검증 — 디코딩과 서명 확인의 차이

    예시 토큰을 헤더·페이로드·서명으로 분해해 각 부분의 생성 원리, 페이로드를 바꾸면 서명이 맞지 않는 이유, alg none과 알고리즘 혼동 공격, Base64와 Base64URL 차이, 서버가 토큰을 받아들이는 다섯 단계 검증 순서, HS256·RS256·ES256 선택 기준을 정리했습니다.

최종 수정 2026년 9월 6일