Session vs Token 전략
작성일: 2025.10.01
1. 인증 방식, 무엇을 선택할까?
Spring Security를 구성할 때 가장 먼저 마주하는 아키텍처 결정 중 하나는 "사용자의 로그인 상태를 어디에 저장하고 어떻게 유지할 것인가?" 입니다. 이는 크게 Server Based(Session) 방식과 Client Based(Token) 방식으로 나뉩니다.
각 방식의 특징과 장단점을 비교하고, 우리 프로젝트에서는 왜 Session + Redis 조합을 선택했는지 정리해 봅니다.
2. Session vs Token 상세 비교
🟢 Session
전통적인 웹 서비스 방식입니다. 서버가 **"모든 것을 기억"**합니다.
- 저장: 서버의 메모리(혹은 외부 저장소)에 로그인/인증 정보를 저장합니다.
- 전송: 클라이언트는
JSESSIONID와 같은 세션 ID만 쿠키로 들고 다닙니다. - 검증: 요청이 올 때마다 서버는 세션 ID를 통해 자신이 가지고 있는 정보와 매칭하여 유효성을 검사합니다.
-
장점
- 강력한 상태 제어: 서버가 로그인 정보를 쥐고 있으므로, 강제 로그아웃, 계정 차단, 세션 만료 등을 즉각적으로 처리할 수 있습니다.
- 보안성: 중요한 정보는 모두 서버에 있고, 클라이언트는 의미 없는 ID 값만 가집니다.
- 편의성: Spring Security를 포함한 대부분의 웹 프레임워크가 기본적으로 지원하여 구현이 쉽습니다.
-
단점
- 확장성(Scalability) 이슈: 서버가 여러 대(Scale-out)일 경우, 각 서버 간 세션 정보를 공유해야 하는 문제(세션 불일치)가 발생합니다. -> 별도의 세션 저장소(Redis 등) 필요
- 리소스 부담: 동시 접속자가 늘어날수록 서버의 메모리/저장소 부담이 커집니다.
- Stateful: 서버가 반드시 클라이언트의 상태를 기억하고 있어야 합니다.
🟠 Token (JWT)
최근 MSA 환경에서 주로 사용되는 방식입니다. 서버는 "검증만 할 뿐, 기억하지 않습니다."
- 발급: 로그인 성공 시 서버가 사용자 정보가 담긴 암호화된 **토큰(JWT)**을 발급합니다.
- 전송: 클라이언트는 요청 시 헤더(
Authorization: Bearer ...)에 토큰을 담아 보냅니다. - 검증: 서버는 토큰의 서명(Signature) 만 확인하여 위변조 여부를 체크합니다. (별도 저장소 조회 X)
-
장점
- 완전한 Stateless: 서버에 세션 정보를 저장할 필요가 없습니다.
- 뛰어난 확장성: 서버를 무한히 늘려도(Scale-out), 토큰 검증 로직만 있다면 어느 서버든 처리가 가능합니다.
- 호환성: 모바일 앱, SPA(React/Vue), 다른 도메인 간의 SSO(Single Sign-On) 구현에 유리합니다.
-
단점
- 제어의 어려움: "이미 발급된 토큰은 뺏을 수 없다." 토큰이 탈취되더라도 유효기간이 끝날 때까지 막을 방법이 마땅치 않습니다. (Blacklist 관리가 필요해짐)
- 네트워크 트래픽: 토큰에 많은 정보를 담을수록 HTTP 헤더 사이즈가 커져 트래픽이 증가합니다.
3. 언제 무엇을 써야 할까?
어떤 방식이 '무조건' 좋다는 없습니다. 프로젝트의 성격에 따라 선택해야 합니다.
| 구분 | Session 권장 | Token (JWT) 권장 |
|---|---|---|
| 서비스 유형 | 전통적 웹 서비스, 내부 어드민 시스템 | MSA, 모바일 앱, SPA, 글로벌 서비스 |
| 인프라 환경 | 단일 서버 혹은 소규모 클러스터 | 오토스케일링이 잦은 클라우드/분산 환경 |
| 필요 기능 | 강제 로그아웃, 실시간 동시 접속 제어 | SSO, 다양한 클라이언트(Web/App) 지원 |
| 핵심 가치 | 보안 및 중앙 제어 (Control) | 확장성 및 유연성 (Scalability) |
"엄격한 관리와 보안이 필요한 웹 기반 내부 서비스에는 Session, 대규모 트래픽과 다양한 클라이언트 확장이 필요한 B2C 서비스에는 Token이 더 적합합니다."
4. Session + Redis 조합
> 왜 Session을 선택했나?
이전 프로젝트에서 저는 Session 기반 인증을 선택했습니다.
- 단일 도메인 환경: 현재 시스템은 비교적 단일 도메인(Same Origin) 환경에서 동작하므로 쿠키 기반의 세션 처리가 가장 효율적입니다.
- 강력한 보안 제어 요구: 관리자가 악성 사용자를 즉시 강제 로그아웃 시키거나, 중복 로그인을 방지하는 등 서버 측의 상태 제어가 필수적이었습니다. JWT로는 이를 구현하기 위해 Blacklist를 도입해야 하는 등 배보다 배꼽이 더 커질 수 있습니다.
- 구현의 용이성: Spring Security의 기본 설정이 세션 기반이므로, 빠르고 안정적인 보안 시스템 구축이 가능했습니다.
> 단점 극복: Redis를 활용한 세션 클러스터링
세션 방식의 치명적인 단점인 "확장성(서버 간 세션 불일치)" 문제는 Redis를 도입하여 해결했습니다.
- 문제 상황: WAS(Web Application Server)를 2대 이상으로 증설할 경우, A 서버에서 로그인한 사용자가 B 서버로 요청을 보내면 로그인이 풀리는 현상 발생.
- 해결책 (Redis Session Storage):
- 각 서버의 로컬 메모리가 아닌, 외부의 초고속 인메모리 DB인 Redis에 세션을 저장합니다.
- Spring Session Data Redis를 사용하면 설정 몇 줄로 이 아키텍처를 구현할 수 있습니다.
- 이제 사용자가 어떤 서버에 접속하든, Redis에서 동일한 세션 정보를 참조하므로 로그인 상태가 유지됩니다.
세션의 안정성/보안성은 챙기면서, Redis를 통해 확장성의 한계를 극복하는 하이브리드 전략을 취했습니다.
5. 마치며
결국 "어떤 기술이 더 우월한가?"보다는 "현재 우리 서비스의 요구사항에 무엇이 더 적합한가?" 가 의사결정의 핵심이었습니다. 이번 아키텍처 설계를 통해 단순히 기능을 구현하는 것을 넘어, 기술의 트레이드오프를 고려하여 최적의 해답을 찾아가는 과정의 중요성을 배울 수 있었습니다.