
1. 서론
백엔드 서버에서 많이 사용하는 세션 기반 인증과 JWT 기반 인증을 비교해보려 한다. 개인 프로젝트를 진행하면서 세션 방식과 JWT 방식을 모두 구현해보기는 했지만 어떠한 방식이 더 유리한지 구현에 용이한지 어떤 규모의 프로젝트에 적합한지는 고려해본적이 없어 이번 기회에 정리하려 한다.
세션 인증
서버가 "로그인한 사용자 상태"를 들고 있는 방식이다(stateful).
구현이 쉽고, 전통적인 웹 서비스/어드민 페이지에 여전히 적합하다.
JWT 인증
서버가 사용자 정보를 서명된 토큰(JWT)에 담아서 클라이언트에게 맡기는 방식이다(stateless 지향).
마이크로 서비스, 모바일/웹/외부API를 동시에 지웒나느 대규모 서비스에서 유리하지만 설계 난이도가 높다.
처음 만드는 서비스라면 세션으로 시작해도 충분하다.
서비스가 커지고, 모바일/마이크로서비스/외부 파트너 API까지 확장한다면 JWT + 중앙 인증 서버 구조를 고민해볼 만하다.
2. 세션 기반 인증
동작 흐름
- 클라이언트가 아이디/비밀번호로 로그인 요청
- 서버가 DB에서 계정 정보 검증
- 성공 시, 서버가 세션 저장소(메모리/Redis/DB 등)에 레코드 생성 (예: `sessionId=abc123 → { userId: 42, roles: ['USER'] }`)
- `SESSIONID` 같은 값을 쿠키로 내려줌 (`HttpOnly, Secure` 옵션 사용)
- 브라우저는 이후 요청마다 쿠키 자동 전송
- 서버는 `SESSIONID`로 세션 저장소에서 사용자 정보를 조회 → 인증/인가 처리
장점
- 프레임워크 지원이 좋아서 구현난이도가 쉽다. → 개인 프로젝트나 규모가 작은 프로젝트에서 빨리 구현하기 용이.
- 서버에서 세션 레코드를 지우는것만으로도 강제 로그아웃, 전체 로그아웃 등 제어가 쉽다.
- 서버 쪽에서 명확히 관리가 가능하다. "이 세션은 더 이상 유효하지 않다"라고 판단 내리기 쉽기 때문.
단점
- 서버가 세션 상태를 들고 있으므로 확장할수록 세션 공유 이슈가 발생한다. → 작은 프로젝트에 적합한 이유. 대규모 프로젝트에서는 고려할게 많아진다.
- 서버가 여러 대일 경우: Redis 같은 공유 세션 저장소가 필요해진다.
- 완전한 의미의 RESTful/Stateless 구조와는 거리가 있음 -> 최신의 개발 트렌드와는 적합하지 않다.
- 브라우저 쿠키 기반의 웹에는 잘 맞지만, 모바일 앱이나 써드파티 API 클라이언트에는 다소 어색할 수 있다.
3. JWT 기반 인증
JWT란?
- JSON 형식의 클레임(예: `sub, userId, role`)을 담고,
- 서버가 비밀키 또는 공개키로 서명한 토큰
- 구조: `header.payload.signature`
- 서버는 이 서명을 검증해서 토큰이 위·변조되지 않았는지 확인
Access Token + Refresh Token 패턴
실무에서 거의 표준처럼 쓰이는 패턴이다.
- 사용자가 로그인
- 서버가 자격 증명 검증 후:
- Access Token (JWT) – 유효기간 짧게 (예: 15분)
- Refresh Token – 유효기간 길게 (예: 2주~1개월)
발급
- 클라이언트는
- Access Token →` Authorization: Bearer <token>` 헤더로 전송
- Refresh Token → HttpOnly 쿠키 또는 안전한 저장소에 보관
- Access Token 만료 시:
- Refresh Token으로 새 Access Token 재발급 요청
- 서버는 Refresh Token 검증 후 새 JWT 발급
장점
- Stateless 인증(Access Token 기준)
서버는 “현재 로그인한 사용자 목록”을 들고 있지 않아도 토큰 서명만 검증하면 된다. - 마이크로서비스/게이트웨이 구조에 잘 맞음
- 중앙 인증 서버에서 JWT 발급
- 각 마이크로서비스는 같은 키로 검증만 수행
- 브라우저, 모바일 앱, 외부 API 클라이언트 등 플랫폼을 가리지 않고 동일한 패턴(Bearer 토큰) 적용 가능.
단점
- 설계할 요소가 많다
- 토큰 만료 정책, Refresh Token 전략, 로그아웃/토큰 무효화, 키 관리/회전 등
- 토큰 무효화가 세션보다 까다롭다
- 이미 클라이언트에 나간 JWT를 무력화하려면
- 블랙리스트
- 토큰 버전 필드
- Refresh Token만 믿고 Access Token은 짧게 유지
같은 전략이 필요
- 이미 클라이언트에 나간 JWT를 무력화하려면
- JWT의 payload는 암호화가 아니라 인코딩이기 때문에,
- 민감 정보를 넣으면 안 됨
- 브라우저에서 localStorage에 저장할 경우 XSS에 취약
→ 실무에서는 보통 HttpOnly 쿠키 + 짧은 만료시간 + Refresh Token 패턴으로 보완
4. 한눈에 비교하기
| 항목 | 세션 인증 | JWT 인증 |
| 상태 관리 | 서버에 세션 상태 저장 (Stateful) | 토큰 서명 검증 위주 (Stateless 지향) |
| 저장 위치 | 서버: 세션 저장소클라이언트: 세션 ID 쿠키 | 서버: 서명 키만 저장클라이언트: JWT 자체 |
| 확장성 | 서버 수 증가 시 세션 공유 인프라 필요 | 서버 수와 무관하게 토큰 검증만 수행 |
| 구현 난이도 | 프레임워크가 거의 다 해주므로 쉽다 | 설계 요소 많고, 보안 실수 여지가 크다 |
| 로그아웃 | 세션 삭제로 즉시 무효화 가능 | 블랙리스트/버전 관리 등 별도 전략 필요 |
| 보안 이슈 | 세션 탈취, CSRF | 토큰 탈취, 키 관리, 긴 만료 시간, XSS |
| 적합한 케이스 | 전통 웹, 어드민, 사내 시스템 | 모바일/SPA/마이크로서비스, 외부 공개 API |
5. 언제 어떻게 사용할것인가?
이번에 정리하면서, 앞으로 서비스를 설계할 때 이렇게 생각해 보기로 했다.
세션을 우선 고려할 상황
- 서버 렌더링 기반 웹 서비스 또는 사내 관리자 페이지
- 아직 트래픽이나 시스템 규모가 크지 않음
- 인증/보안에 쓸 리소스가 많지 않고, 프레임워크 기본 제공 기능을 그대로 활용하는 편이 더 안전할 때
→ “빠르게 안정적인 서비스를 만드는 것이 목표일 때 세션이 현실적인 선택”
JWT를 고민할 상황
- 모바일 앱 + 웹 + 외부 파트너 API를 동시에 지원해야 하는 B2C 서비스
- 마이크로서비스 아키텍처, API Gateway, WebSocket/gRPC 등 다양한 통신 방식 사용
- 카카오/네이버/구글 로그인 연동이 필수이고, 토큰 기반으로 인증 체계를 통합하고 싶을 때
→ “장기적으로 대규모 확장을 전제로 한 서비스라면, 중앙 인증 서버 + JWT 체계를 설계하는 것이 이득”
'Develop > CS' 카테고리의 다른 글
| [OS] 스레드·병행성 개념을 실제 개발에 적용하자 (0) | 2025.12.20 |
|---|---|
| [HTTP] 쿠키 (1) | 2025.12.08 |
| [Web] JWT가 사용하기 어려운 이유 (0) | 2025.12.06 |
| [CS] 멱등성이란? (0) | 2025.12.04 |