JWT란 무엇인가? 토큰 기반 인증 원리 완전 정리
JWT는 사용자 정보를 JSON으로 담아 서명한 토큰으로, 서버가 상태를 저장하지 않고 인증을 처리하는 방식이다.
이 글은 로그인 API를 처음 구현하는 개발자와 인증 방식에 관심 있는 IT 입문자를 대상으로 작성되었다. JWT가 무엇이고 왜 사용하는지, 어떻게 동작하는지 단계별로 설명한다.
JWT(JSON Web Token)란?
JWT는 JSON 형식으로 데이터를 담고 디지털 서명한 토큰이다. RFC 7519 표준으로 정의된다.
JWT의 핵심 특징:
- Stateless: 서버가 토큰 정보를 별도로 저장하지 않는다
- Self-contained: 토큰 자체에 사용자 정보가 포함된다
- Verifiable: 서명으로 변조 여부를 확인할 수 있다
JWT의 구조
JWT는 점(.)으로 구분된 3개의 파트로 구성된다:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJleHAiOjE3MDk4NTYwMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- Header (헤더)
{
"alg": "HS256", // 서명 알고리즘
"typ": "JWT" // 토큰 타입
}
- Payload (페이로드)
{
"userId": "123",
"email": "user@example.com",
"exp": 1709856000 // 만료 시간 (Unix timestamp)
}
- Signature (서명)
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
서버_비밀키
)
JWT 인증 동작 과정
- 로그인: 사용자가 아이디/비밀번호를 서버에 전송
- 토큰 발급: 서버가 JWT를 생성하여 클라이언트에 반환
- 토큰 저장: 클라이언트가 로컬스토리지 또는 쿠키에 저장
- 인증된 요청: 이후 API 요청 시 Authorization 헤더에 토큰 포함
Authorization: Bearer <JWT 토큰> - 서버 검증: 서버가 서명을 확인하고 만료 여부 체크
- 응답 반환: 유효한 토큰이면 요청 처리
JWT vs 세션 비교
| 구분 | JWT | 세션 |
|---|---|---|
| 저장 위치 | 클라이언트 | 서버 |
| 서버 부하 | 낮음 (상태 저장 없음) | 높음 (세션 DB 필요) |
| 확장성 | 뛰어남 (마이크로서비스 적합) | 낮음 (서버 간 공유 필요) |
| 즉시 무효화 | 어려움 | 쉬움 |
| 보안 | 토큰 탈취 시 만료 전까지 유효 | 즉시 무효화 가능 |
| 토큰 크기 | 세션 쿠키보다 큼 | 세션 ID만 저장 |
| 적합 환경 | REST API, 마이크로서비스 | 전통적인 웹 앱 |
Access Token과 Refresh Token 전략
JWT의 가장 큰 약점은 즉시 무효화가 어렵다는 것이다. 이를 보완하기 위해 두 종류의 토큰을 사용한다:
Access Token
- 짧은 유효 기간 (보통 15분~1시간)
- API 요청에 사용
- 만료되면 Refresh Token으로 재발급
Refresh Token
- 긴 유효 기간 (7일~30일)
- 새로운 Access Token 발급에만 사용
- 서버 DB에 저장하여 무효화 가능
이 전략으로 Access Token이 탈취되더라도 짧은 시간 후 자동으로 만료되어 피해를 최소화한다.
JWT 보안 주의사항
- 민감 정보 저장 금지: Payload는 Base64 인코딩이므로 누구나 디코딩 가능. 비밀번호, 카드 정보는 절대 포함하지 않는다.
- 강력한 비밀키 사용: 서명에 사용하는 비밀키는 충분히 길고 복잡해야 한다.
- HTTPS 사용 필수: 토큰 전송 시 반드시 암호화된 채널 사용.
- XSS 방지: 로컬스토리지 저장 시 XSS에 취약하므로, HttpOnly 쿠키 저장이 더 안전하다.
- 적절한 만료 시간: Access Token은 짧게, Refresh Token은 적절하게.
자주 묻는 질문 (FAQ)
Q1. JWT는 암호화된 건가요? A. 기본 JWT(JWS)는 서명만 되어 있고 암호화는 되지 않는다. 누구나 Payload를 디코딩할 수 있으나, 서명 없이는 내용을 변조할 수 없다. 암호화가 필요하면 JWE(JSON Web Encryption)를 사용한다.
Q2. JWT를 어디에 저장하는 것이 좋나요? A. HttpOnly 쿠키에 저장하는 것이 가장 안전하다. 로컬스토리지는 XSS 공격으로 탈취될 수 있다. 메모리(React State)에 저장하면 보안은 높지만 페이지 새로고침 시 사라지는 단점이 있다.
Q3. JWT 토큰이 탈취되면 어떻게 되나요? A. Access Token은 만료 시간이 짧으므로 피해가 제한적이다. Refresh Token이 탈취된 경우 서버 DB에서 해당 Refresh Token을 무효화하여 대응할 수 있다. 이 때문에 Access/Refresh Token 분리 전략이 중요하다.
Q4. "Bearer" 토큰이란 무엇인가요?
A. Bearer는 "소지자"라는 의미로, 이 토큰을 가진 사람에게 권한을 부여한다는 뜻이다. Authorization: Bearer <토큰> 형식으로 HTTP 헤더에 포함하는 것이 OAuth 2.0 표준 방식이다.
Q5. JWT는 어디서 사용하는 건가요? A. REST API 인증, 마이크로서비스 간 인증, 모바일 앱(iOS/Android) 인증, 소셜 로그인(OAuth), SSO(Single Sign-On) 등에 널리 사용된다. Auth0, Firebase Auth 등 인증 서비스도 JWT를 기반으로 한다.