Stateless의 의미를 살펴보면, 세션은 적절하지 않은 인증 방법 아닌가요?
맞습니다. 순수한 Stateless 관점에서 보면 세션은 서버에 상태를 저장하므로 적절하지 않은 방식입니다. 하지만 세션이 부적절하다기보다는 각각의 트레이드오프가 다르기 때문에 상황에 따라 선택하는 것입니다.
왜 세션이 Stateless에 어긋나는가
[Stateless 원칙]
"서버는 클라이언트의 상태를 저장하지 않는다"
[세션 방식]
서버 메모리/Redis에 {Session ID → 사용자 정보} 저장
→ 서버가 상태를 갖고 있음 → Stateful X
그래서 REST API 설계 원칙을 엄격히 따르면, 세션 방식은 RESTful하지 않습니다.
그럼에도 세션을 쓰는 이유
JWT(토큰 기반)가 Stateless에 부합하지만, 세션에 비해 해결하기 어려운 문제들이 있습니다.
JWT의 근본적 한계
[문제 상황: 사용자 강제 로그아웃]
세션 방식:
관리자 → session.invalidate("abc123") → 즉시 로그아웃 O
JWT 방식:
관리자 → ??? → 이미 발급된 토큰은 만료 전까지 유효
→ 서버가 거부할 수 없음 X
→ 결국 블랙리스트(서버 저장)를 만들어야 함
→ 그 순간 Stateful이 됨...
| 시나리오 | 세션 | JWT |
|---|---|---|
| 강제 로그아웃 | 세션 삭제로 즉시 가능 O | 불가능 (블랙리스트 필요) |
| 동시 접속 제한 | 세션 수 카운팅으로 간단 O | 서버 저장 없이는 불가능 |
| 권한 즉시 변경 | 세션 데이터 수정으로 즉시 반영 O | 토큰 재발급 전까지 이전 권한 유지 |
| 토큰/세션 탈취 대응 | 세션 무효화로 즉시 차단 O | 만료까지 차단 불가 |
JWT의 기타 단점
[토큰 크기]
JSESSIONID: abc123 → 수십 바이트
JWT: eyJhbGciOiJIUzI1NiJ9.eyJ1c2... → 수백 바이트~수 KB
→ 매 요청마다 Authorization 헤더에 포함되므로 네트워크 비용 증가
[Payload 노출]
JWT의 Payload는 암호화가 아니라 Base64 인코딩
→ 누구나 디코딩하여 내용 확인 가능
→ 민감 정보를 담으면 안 됨
결국 실무에서의 선택
| 기준 | 세션 | JWT |
|---|---|---|
| 아키텍처 | 모놀리식, SSR (Spring MVC 등) | MSA, SPA, 모바일 앱 |
| Scale-Out | Redis 세션 저장소 필요 | 서버 확장 자유 |
| 보안 통제 | 강력 (서버가 통제권 보유) | 제한적 (발급 후 제어 어려움) |
| 구현 복잡도 | 상대적으로 단순 | Refresh Token, 블랙리스트 등 추가 설계 필요 |
| Stateless | X | O (순수 JWT 한정) |
[현실적인 선택 흐름]
전통적 웹 서비스 (SSR)
→ 세션 + Redis로 충분
→ 굳이 JWT를 도입하면 오히려 복잡도만 증가
MSA / SPA / 모바일
→ 서버 간 세션 공유가 비현실적
→ JWT가 적합하지만 Refresh Token은 서버 저장 (부분적 Stateful)
대규모 서비스 (네이버, 카카오 등)
→ JWT + Refresh Token + Redis 블랙리스트 조합
→ 완전한 Stateless는 포기하고 실용적 절충
면접 포인트
- "세션은 Stateless에 어긋나므로 JWT가 더 좋다"는 단순 비교보다, 각 방식의 트레이드오프를 이해하고 상황에 맞게 선택한다고 답하는 것이 좋습니다.
- 실무에서 완전한 Stateless를 달성하는 서비스는 거의 없으며, JWT를 사용하더라도 Refresh Token 관리, 블랙리스트 등으로 부분적 Stateful이 되는 것이 일반적입니다.
- 핵심 판단 기준은 "서버의 통제권이 중요한가(세션), 서버의 확장성이 중요한가(JWT)" 입니다.