본문으로 건너뛰기

JWT는 Stateless라는 말이 왜 반은 거짓인가

JWT는 정말 Stateless일까?

JWT를 설명할 때 가장 자주 등장하는 문장은 이겁니다.

"JWT는 Stateless 인증 방식이다"

이 말은 틀린 말은 아닙니다. 하지만 그대로 믿으면 오해를 낳는 말이기도 합니다.

실무에서 JWT를 제대로 쓰다 보면,

"어? 결국 서버가 뭔가 기억하고 있는데?"

라는 순간을 반드시 마주치게 됩니다.

이 글에서는

  • JWT가 왜 Stateless라고 불리는지
  • 그 말이 왜 반만 맞는 말인지
  • 실무에서는 어떤 지점에서 상태가 다시 생기는지

를 차근히 짚어보려 합니다.


JWT가 Stateless라고 불리는 이유

JWT의 기본 모델은 단순합니다.

요청 ── JWT ──▶ 서버
서버 ── 서명 검증 ──▶ 사용자 신뢰

서버는

  • 세션을 저장하지 않고
  • 사용자 정보를 조회하지 않으며
  • 토큰 자체만 검증합니다

즉,

"이 요청이 누구의 것인지"를 서버 내부 상태 없이 판단할 수 있습니다.

이 지점만 보면 JWT는 분명 Stateless입니다.


Stateless라는 말이 숨기고 있는 전제

JWT가 Stateless일 수 있는 이유는 단 하나입니다.

"토큰이 만료될 때까지 항상 유효하다고 가정한다"

이 가정이 깨지는 순간, Stateless 구조도 함께 흔들립니다.


문제가 되는 질문 하나

실무에서 반드시 나오는 질문이 있습니다.

"이 토큰을 지금 당장 무효화하려면 어떻게 하지?"

  • 로그아웃
  • 권한 변경
  • 계정 정지
  • 토큰 탈취 의심

이런 상황에서

"만료될 때까지 기다리면 됩니다"

는 대부분의 서비스에서 현실적인 답이 아닙니다.


로그아웃은 Stateless 모델에 존재하지 않는다

JWT 관점에서 로그아웃은 이상한 개념입니다.

  • 서버는 토큰을 저장하지 않음
  • 토큰은 만료 전까지 항상 유효

즉,

서버 입장에서 로그아웃은 아무 일도 일어나지 않는 이벤트입니다.

그래서 이 순간부터

"서버가 이 토큰을 기억해야 하나?"

라는 질문이 다시 등장합니다.


상태가 다시 생기는 지점들

1. 토큰 블랙리스트

가장 직관적인 해결책은 이겁니다.

"이 토큰은 더 이상 인정하지 않는다"

이를 위해 서버는

  • 무효화된 토큰 목록을 저장하고
  • 매 요청마다 이를 조회합니다

이 순간,

서버는 다시 상태를 가지게 됩니다.


2. Refresh Token 전략

실무에서 JWT는 거의 항상 이렇게 사용됩니다.

  • Access Token (짧은 수명)
  • Refresh Token (긴 수명)

Refresh Token을 사용하는 순간, 서버는 다음 중 하나를 선택해야 합니다.

  • Refresh Token을 저장한다
  • 사용자별로 관리한다

즉,

**"재발급을 통제하는 상태"**가 필요해집니다.

Stateless는 이 시점에서 더 이상 완전하지 않습니다.


3. 권한 변경과 즉시 반영 문제

JWT Payload에 이런 정보가 들어 있다고 가정해봅니다.

{
"userId": 1,
"role": "ADMIN"
}
  • 사용자의 권한이 변경되면?
  • 이미 발급된 토큰은?

이 문제를 해결하려면

  • 토큰 재발급
  • 버전 관리
  • 사용자 상태 체크

중 하나가 필요합니다.

이 역시 상태를 요구합니다.


그래서 JWT는 왜 계속 Stateless라고 불릴까?

JWT가 Stateless라고 불리는 이유는

"세션 모델과 비교했을 때 상대적으로 Stateless"

이기 때문입니다.

  • 모든 요청마다 세션 조회 ❌
  • 사용자 객체 로딩 ❌
  • 중앙 세션 저장소 의존 ❌

이걸 하지 않아도 되기 때문에

"Stateless에 가깝다"

라고 표현되는 것입니다.


Stateless는 목표이지, 현실은 아니다

실무에서의 JWT 구조는 보통 이렇습니다.

Access Token: Stateless
Refresh Token: Stateful

즉,

  • 요청 인증은 최대한 Stateless하게 처리하고
  • 통제와 안전은 상태로 보완합니다

이건 실패가 아니라 타협의 결과입니다.


프론트엔드 알아야 하는 이유

프론트엔드에서는 JWT를 이렇게 느끼기 쉽습니다.

"헤더에 토큰만 넣으면 끝"

하지만 실제로는

  • 만료 시점 UX
  • 재발급 타이밍
  • 로그아웃 처리

전부 이 Stateful 지점과 연결됩니다.

JWT를 Stateless라고만 이해하면

  • 로그아웃이 왜 애매한지
  • 만료 처리 왜 복잡한지

절대 설명할 수 없습니다.


이 글의 결론

  • JWT는 Stateless를 지향한다
  • 하지만 완전한 Stateless는 아니다
  • 실무에서는 반드시 상태가 다시 생긴다

그래서 더 정확한 표현은

"JWT는 상태를 최소화하려는 인증 방식이다"