스프링 시큐리티를 사용한 로그인(with JWT)을 구현하기 전, JWT에 대해 간단하게 알아보려고 한다!
🔎 JWT 개념
JWT는 사용자 인증 정보를 JSON 형태로 안전하게 전달하는 Claim 기반 웹 토큰으로, Base64로 인코딩되어 클라이언트 - 서버 간 권한 검증에 사용된다.
🔧 JWT 구조
JWT는 Header, Payload, Signature 총 세 부분으로 구성된다. 각 부분을 .을 이용해서 연결하고, 이 값을 Base64로 인코딩하여 JWT를 생성한다.

생성한 JWT는 HTTP 요청 시 Authorization 헤더에 Bearer JWT 토큰 형태로 전달된다.
{
"Authorization": "Bearer {JWT 토큰}"
}
Header
Header는 JWT에서 사용할 토큰의 타입과 해시 알고리즘의 정보로 구성된다. (key - value 형태)
alg: 해시 알고리즘 정보- ex) HS256, HS512, RS256, ES256
typ: 사용할 토큰의 타입
{
"alg": "HS256",
"typ": "JWT"
}
Payload
Payload는 서버로 보낼 사용자 권한 정보와 데이터를 담는 부분으로, key - value 형태의 클레임(Claim)들로 구성된다.
{
"userId": "hong",
"name": "홍길동"
}
클레임은 등록된 클레임, 공개 클레임, 비공개 클레임 총 세 가지로 분류된다.
- 등록된 클레임: 토큰에 대한 정보를 담기 위해, 이름이 이미 정해진 클레임
등록된 클레임 이름
iss: 토큰 발급자 (issue)sub: 토큰 제목 (subject)aud: 토큰 대상자 (audience)exp: 토큰 만료시간 (expiration)- NumericDate 형식으로 지정해야 하고 현재 시간보다 이후로 설정해야 함
- ex) 1초 = 1,000, 1분 = 1,000 * 60 = 60,000, 1시간 = 1,000 * 60 * 60 = 3,600,000
nfb: Not Before- 이 날짜가 지나기 전까지는 토큰이 처리되지 않음
- NumbericDate 형식으로 지정해야 함
iat: 토큰이 발급된 시간 (issued at)- 이 값을 이용해서 토큰의 나이가 얼마나 되었는지 알 수 있음
jti: JWT의 고유 식별자- 주로 중복적인 처리를 방지하기 위해 사용함
- 공개 클레임: 충돌이 방지된 이름을 가지고 있어야 하므로 클레임 이름을 URI 형식으로 지음
- ex)
"http://test.com/jwt/test": true
- ex)
- 비공개 클레임: 양측(클라이언트 - 서버) 협의하에 사용되는 클레임으로, 이름이 중복되어 충돌이 발생할 수 있음
- ex)
"username": "hong"
- ex)
Signature
Signature는 토큰의 유효성을 검증하기 위한 문자열로, Base64로 인코딩된 Header와 Payload를 Secret Key(서버의 개인키)로 해싱한 후, 다시 Base64로 인코딩하여 생성한다.
⚖️ 서버 기반 인증 vs 토큰 기반 인증
서버(session) 기반 인증
서버에서 사용자 인증 정보를 관리하며, 클라이언트로부터 요청을 받으면 클라이언트 상태를 계속 유지한다(Stateful). 그러나 서버에서 관리하므로 클라이언트가 많아지면 성능 문제가 발생할 수 있고, 세션을 사용하므로 서버를 확장하는 것이 어렵다.

토큰(token) 기반 인증
서버에서 클라이언트에게 토큰을 발급하여 클라이언트가 인증 정보를 관리한다. 따라서 서버가 클라이언트 상태를 유지하지 않는다(Stateless). 로그인이 필요한 작업일 경우, HTTP 요청 헤더에 토큰을 삽입하여 전달한다.

👍 JWT의 장점
- Stateless & 확장성
- 서버가 클라이언트 상태를 저장하지 않으므로 서버 확장이 자유롭다
- 보안성
- 서명(signature)으로 위/변조를 방지한다 (단, 토큰 탈취당하는 것을 조심해야 함)
- 다양한 환경
- 모바일, 웹 등 모든 플랫폼에서 사용이 가능하다
👎 JWT의 단점
- Self-contained
- 토큰 자체에 정보를 담고 있어 보안 위험이 있다
- Payload 인코딩
- Payload 자체는 암호화 된 것이 아니라 Base64 URL로 인코딩 한 것
- 네트워크 전송 방식이라 토큰을 탈취당할 수 있으므로, 중요한 정보를 저장하면 안된다
- Stateless
- JWT는 상태를 저장하지 않으므로 한 번 만들어지면 제어가 불가능
- 따라서 토큰을 임의로 삭제하는 것이 불가능하여 토큰 만료 시간을 꼭 넣어야 한다
- 토큰 길이
- 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다
참고
https://mangkyu.tistory.com/56
'Backend' 카테고리의 다른 글
| [Spring] Access Token 블랙리스트 관리하기 (0) | 2025.02.25 |
|---|---|
| [Web] 웹 소켓(Web Socket)이란? (1) | 2025.01.29 |
| [Spring] Spring Security JWT 로그인 구현하기(with Redis) (1) | 2025.01.24 |
| [Spring] 객체 지향 설계와 스프링 (0) | 2024.10.22 |
| [Error] 셧다운 포트가 설정되지 않았습니다. (0) | 2024.04.16 |