🔐 JWT Decoder
Decode and inspect JSON Web Tokens (JWT)
🔐 JWT Token Input
ℹ️ About JWT (JSON Web Tokens)
JWT is a compact, URL-safe means of representing claims to be transferred between two parties. The token consists of three parts separated by dots: Header.Payload.Signature
Header
Contains the token type (JWT) and signing algorithm (e.g., HS256, RS256)
Payload
Contains the claims (user data, permissions, expiration time, etc.)
Signature
Used to verify the token hasn't been tampered with
⚠️ Security Warning
This tool only decodes JWTs - it does NOT verify signatures. Never paste sensitive tokens into online tools. Use this for learning and debugging only.
📖 JWT란?
🔑 JWT (JSON Web Token)
JWT는 당사자 간에 정보를 JSON 객체로 안전하게 전송하기 위한 개방형 표준(RFC 7519)입니다. 디지털 서명되어 있어 정보의 무결성을 검증할 수 있으며, 주로 인증(Authentication)과 권한 부여(Authorization)에 사용됩니다. 세 부분으로 구성되어 있으며, 점(.)으로 구분된 Base64 URL 인코딩 문자열입니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cHeader.Payload.Signature 세 부분으로 구성
💡 JWT 사용 사례
- 사용자 인증: 로그인 후 JWT를 발급하여 후속 요청에서 사용자 식별
- 단일 로그인 (SSO): 여러 시스템 간 사용자 인증 정보 공유
- 정보 교환: 공개키/개인키를 사용하여 서명된 데이터 전송
- API 인증: REST API 요청 시 Authorization 헤더에 포함하여 인증
- 권한 부여: 사용자의 역할 및 권한 정보를 토큰에 포함
- 세션 대체: Stateless 인증으로 서버 부담 감소
🧩 JWT 구조
1️⃣ Header (헤더)
토큰의 타입과 서명 알고리즘 정보
{
"alg": "HS256",
"typ": "JWT"
}- alg: 서명 알고리즘 (HS256, RS256, ES256 등)
- typ: 토큰 타입 (일반적으로 "JWT")
2️⃣ Payload (페이로드)
실제 전달할 데이터 (Claims)
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022,
"exp": 1516242622
}- Registered Claims: 미리 정의된 클레임 (sub, iss, exp, iat 등)
- Public Claims: 공개적으로 정의된 클레임
- Private Claims: 사용자 정의 클레임
3️⃣ Signature (서명)
헤더와 페이로드를 검증하기 위한 서명
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)- Header + Payload를 비밀키로 서명
- 토큰 변조 여부 검증 가능
- 서명은 디코딩 불가 (검증만 가능)
📋 표준 클레임 (Standard Claims)
iss (Issuer)
토큰 발행자
"https://example.com"sub (Subject)
토큰 주제 (일반적으로 사용자 ID)
"user123"aud (Audience)
토큰 대상 (수신자)
"https://api.example.com"exp (Expiration Time)
토큰 만료 시간 (Unix timestamp)
1735689600nbf (Not Before)
토큰 활성화 시간
1735603200iat (Issued At)
토큰 발행 시간
1735603200jti (JWT ID)
토큰 고유 식별자
"550e8400-e29b-41d4"🔐 서명 알고리즘
HMAC (대칭키)
동일한 비밀키로 서명 생성 및 검증
- HS256: HMAC SHA-256 (가장 일반적)
- HS384: HMAC SHA-384
- HS512: HMAC SHA-512
장점: 빠르고 간단, 단점: 키 공유 필요
RSA (비대칭키)
개인키로 서명, 공개키로 검증
- RS256: RSA SHA-256
- RS384: RSA SHA-384
- RS512: RSA SHA-512
장점: 공개키 배포 안전, 단점: 느림
ECDSA (타원곡선)
타원곡선 암호화 기반 서명
- ES256: ECDSA SHA-256
- ES384: ECDSA SHA-384
- ES512: ECDSA SHA-512
장점: RSA보다 빠르고 작은 키, 단점: 복잡
none (서명 없음) ⚠️
서명 없이 사용 (개발 전용)
경고: 프로덕션에서 절대 사용 금지!
🔄 JWT 사용 흐름
1. 사용자 로그인
사용자가 아이디/비밀번호로 로그인 요청
POST /api/login { "username": "john", "password": "***" }2. 서버가 JWT 생성
인증 성공 시 서버가 JWT 토큰 생성 및 발급
{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }3. 클라이언트 저장
클라이언트가 토큰을 로컬스토리지/쿠키에 저장
localStorage.setItem('token', token)4. API 요청 시 전송
후속 요청마다 Authorization 헤더에 토큰 포함
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...5. 서버 검증
서버가 서명 검증 및 만료 시간 확인
verify(token, secret) → { sub: "john", exp: 1735689600 }6. 응답 반환
검증 성공 시 요청 처리, 실패 시 401 Unauthorized
❓ 자주 묻는 질문 (FAQ)
Q: JWT는 암호화되나요?
A: 아니요. JWT는 Base64 URL 인코딩되어 있을 뿐 암호화되지 않습니다. 누구나 디코딩하여 내용을 볼 수 있으므로 민감한 정보(비밀번호, 신용카드 번호 등)를 넣으면 안 됩니다. 서명(Signature)은 변조 방지용이지 암호화가 아닙니다. 암호화가 필요하면 JWE(JSON Web Encryption)를 사용하세요.
Q: JWT와 세션의 차이는 무엇인가요?
A: JWT: Stateless (서버에 상태 저장 안 함), 확장성 좋음, 토큰 무효화 어려움. 세션: Stateful (서버에 세션 저장), 즉시 무효화 가능, 서버 부담 증가. JWT는 마이크로서비스와 분산 시스템에 적합하고, 세션은 단일 서버 애플리케이션에 적합합니다.
Q: JWT는 안전한가요?
A: 올바르게 사용하면 안전하지만, 주의사항이 많습니다. 안전한 사용: HTTPS 사용, 강력한 비밀키, 짧은 만료 시간, 민감한 정보 제외. 위험: XSS 공격 (LocalStorage 저장 시), CSRF (쿠키 저장 시), 알고리즘 혼동 공격. httpOnly 쿠키 + SameSite 속성 사용을 권장합니다.
Q: JWT 토큰을 어디에 저장해야 하나요?
A: httpOnly 쿠키 (권장): XSS 공격 방어, CSRF 대책 필요. LocalStorage: XSS 취약, 간편함. SessionStorage: 탭 닫으면 삭제, XSS 취약. 메모리 (변수): 가장 안전, 새로고침 시 삭제. 보안이 중요하면 httpOnly 쿠키 + SameSite=Strict를 사용하세요.
Q: JWT 토큰을 로그아웃 시 무효화할 수 있나요?
A: JWT는 기본적으로 무효화할 수 없습니다 (Stateless). 해결 방법: (1) 블랙리스트: 무효화된 토큰을 Redis에 저장 (만료 시까지), (2) 짧은 만료 시간: Access Token 15분 + Refresh Token 사용, (3) 토큰 버전: 사용자별 토큰 버전 관리, 버전 변경 시 기존 토큰 무효화.
Q: Access Token과 Refresh Token의 차이는?
A: Access Token: 짧은 수명 (15분~1시간), API 요청에 사용, 만료 시 재발급 필요. Refresh Token: 긴 수명 (7일~30일), Access Token 재발급용, httpOnly 쿠키에 저장. 이 방식으로 보안과 사용자 경험을 균형있게 유지합니다.
Q: JWT 크기가 너무 큰데 어떻게 하나요?
A: JWT는 HTTP 헤더에 포함되므로 크기가 중요합니다. 해결 방법: (1) 불필요한 클레임 제거, (2) 압축 사용 (deflate), (3) 긴 데이터는 DB에 저장하고 ID만 포함, (4) 일반적으로 1KB 이하 권장, HTTP 헤더 제한은 8KB입니다.
💡 JWT 사용 모범 사례
- HTTPS 필수: HTTP에서는 토큰이 평문으로 전송되어 가로채기 위험
- 짧은 만료 시간: Access Token은 15분~1시간, Refresh Token과 함께 사용
- 강력한 비밀키: 최소 256비트 (32자 이상) 랜덤 문자열
- 민감한 정보 제외: 비밀번호, 신용카드, 개인정보는 절대 포함 금지
- 알고리즘 검증: Header의 alg 값 검증, "none" 알고리즘 차단
- 토큰 크기 최소화: 필요한 클레임만 포함 (1KB 이하 권장)
- httpOnly 쿠키: XSS 공격 방어를 위해 LocalStorage 대신 사용
- aud 클레임 검증: 토큰이 올바른 서비스용인지 확인
- JTI 사용: 토큰 ID로 재사용 방지 및 로그아웃 구현
⚠️ 보안 주의사항
- JWT는 암호화되지 않음 - 민감한 정보 절대 포함 금지
- alg="none" 공격 방지 - 서버에서 알고리즘 검증 필수
- 비밀키 노출 시 모든 토큰 무효화 - 키 관리 철저히
- LocalStorage에 저장 시 XSS 공격에 취약 - httpOnly 쿠키 사용 권장
- 만료 시간 검증 누락 시 무한정 사용 가능 - exp 클레임 반드시 검증
- 서명 검증 생략하면 변조된 토큰 통과 - 항상 서명 검증
- HTTPS 미사용 시 토큰 가로채기 가능 - 프로덕션에서 HTTPS 필수
- 하드코딩된 비밀키 사용 금지 - 환경 변수로 관리
💻 프로그래밍 언어별 JWT 구현
JavaScript (Node.js)
const jwt = require('jsonwebtoken');
// 토큰 생성
const payload = { sub: 'user123', name: 'John' };
const secret = process.env.JWT_SECRET;
const token = jwt.sign(payload, secret, { expiresIn: '1h' });
// 토큰 검증
try {
const decoded = jwt.verify(token, secret);
console.log(decoded); // { sub: 'user123', name: 'John', iat: ..., exp: ... }
} catch (err) {
console.error('Invalid token');
}
// 토큰 디코딩 (검증 없이)
const decoded = jwt.decode(token);
console.log(decoded.header); // { alg: 'HS256', typ: 'JWT' }Python
import jwt
from datetime import datetime, timedelta
# 토큰 생성
payload = {
'sub': 'user123',
'name': 'John',
'exp': datetime.utcnow() + timedelta(hours=1)
}
secret = 'your-secret-key'
token = jwt.encode(payload, secret, algorithm='HS256')
# 토큰 검증
try:
decoded = jwt.decode(token, secret, algorithms=['HS256'])
print(decoded) # {'sub': 'user123', 'name': 'John', 'exp': ...}
except jwt.ExpiredSignatureError:
print('Token expired')
except jwt.InvalidTokenError:
print('Invalid token')Java (Spring Boot)
import io.jsonwebtoken.*;
// 토큰 생성
String secret = "your-secret-key";
String token = Jwts.builder()
.setSubject("user123")
.claim("name", "John")
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
// 토큰 검증
try {
Claims claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
String userId = claims.getSubject();
} catch (ExpiredJwtException e) {
// 만료된 토큰
} catch (JwtException e) {
// 유효하지 않은 토큰
}PHP
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
// 토큰 생성
$payload = [
'sub' => 'user123',
'name' => 'John',
'exp' => time() + 3600
];
$secret = 'your-secret-key';
$token = JWT::encode($payload, $secret, 'HS256');
// 토큰 검증
try {
$decoded = JWT::decode($token, new Key($secret, 'HS256'));
echo $decoded->sub; // user123
} catch (Exception $e) {
echo 'Invalid token: ' . $e->getMessage();
}Go
import "github.com/golang-jwt/jwt/v5"
// 토큰 생성
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"sub": "user123",
"name": "John",
"exp": time.Now().Add(time.Hour * 1).Unix(),
})
secret := []byte("your-secret-key")
tokenString, err := token.SignedString(secret)
// 토큰 검증
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return secret, nil
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
fmt.Println(claims["sub"]) // user123
} else {
fmt.Println("Invalid token")
}🆚 JWT vs Session vs OAuth
| 특성 | JWT | Session | OAuth 2.0 |
|---|---|---|---|
| 저장 위치 | 클라이언트 (쿠키/Storage) | 서버 (Redis, DB) | 인증 서버 + 클라이언트 |
| Stateful/Stateless | Stateless | Stateful | Stateless (토큰) |
| 확장성 | 우수 (서버 상태 없음) | 낮음 (세션 공유 필요) | 우수 |
| 즉시 무효화 | 어려움 | 쉬움 | 쉬움 (revoke) |
| 크기 | 큼 (매 요청마다 전송) | 작음 (Session ID만) | 큼 (Access Token) |
| CSRF 취약성 | 쿠키 사용 시 취약 | 취약 | 낮음 |
| 적합한 용도 | API, 마이크로서비스 | 모놀리식 웹 앱 | 제3자 서비스 연동 |
🔗 관련 도구 및 리소스
📚 공식 문서
- RFC 7519: JWT 표준 명세
- jwt.io: JWT 공식 웹사이트
- OWASP: JWT 보안 가이드
🛠️ 라이브러리
- jsonwebtoken (Node.js): 가장 인기
- PyJWT (Python): Python 표준
- java-jwt (Java): Auth0 제공
🔐 보안 도구
- JWT Inspector: 브라우저 확장
- Burp Suite: JWT 분석 플러그인
- jwt_tool: 보안 테스팅 도구