
JWT(JSON Web Token)는 서명된 JSON 기반 토큰으로, 서버가 클라이언트를 식별/인가하기 위해 HTTP 헤더(주로 Authorization)에 실어 보내는 인증 방식이다.
JWT는 . 으로 구분된 3개 문자열로 구성된다.

| 구분 | 쿠키·세션 인증 | JWT 인증 |
|---|---|---|
| 인증 방식 | 서버가 세션 상태 유지 | 서버 무상태(Stateless) |
| 인증 정보 저장 | 서버 메모리 / DB / Redis | 클라이언트(토큰) |
| 클라이언트 저장 | 세션ID(쿠키) | Access / Refresh Token |
| 서버 확장성 | 낮음(세션 공유 필요) | 높음(수평 확장 용이) |
정리:
필수급:
JwtAuthenticationFilter : 요청마다 토큰 추출/검증 후 SecurityContext에 인증 저장JwtTokenProvider : 토큰 생성/파싱/검증 유틸CustomUserDetails : Security가 이해하는 사용자 모델CustomUserDetailsService : DB에서 사용자 로딩SecurityConfig : FilterChain 등록/인가 규칙 설정Refresh Token까지 하면 추가:
JwtAuthenticationFilter가 헤더에서 토큰 추출JwtTokenProvider.validateToken()으로 검증getAuthentication()으로 Authentication 생성SecurityContextHolder에 저장Bearer 토큰을 꺼냄SecurityContext에 넣음@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtTokenProvider jwtTokenProvider;
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String BEARER_PREFIX = "Bearer ";
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String token = resolveToken(request);
try {
if (StringUtils.hasText(token) && jwtTokenProvider.validateToken(token)) {
Authentication authentication = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (ExpiredJwtException e) {
// 만료 토큰 정책: 여기서 401로 끊어버릴지, 그냥 익명으로 넘길지 팀 정책으로 고정
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
filterChain.doFilter(request, response);
}
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(BEARER_PREFIX)) {
return bearerToken.substring(BEARER_PREFIX.length()); // 7
}
return null;
}
}