- Published on
세션이란?
- Authors
- Name
- zkrp
이번에 프로젝트를 진행하는 도중에 세션에 대한 개념이 필요할거 같아서 세션에 대해 공부한걸 이번 글에 정리하려 합니다. 일단 세션을 들어가기 전에 HTTP 특징에 대해 간단하게 설명하겠습니다.
1. HTTP
HTTP는 웹 브라우저와 웹 서버가 데이터(문서, 이미지, JSON)를 교환하기 위한 통신 규약입니다.
그리고 HTTP는 서버가 이전 요청의 결과나 사용자의 상태를 내부 메모리에 보존하지 않는 특징을 가지고 있습니다.
그래서 항상 클라이언트가 요청할 때마다 필요한 모든 정보를 헤더, 쿼리, 본문에 다시 실어서 보냅니다.
Stateless
특징을 가지고 있어 수평 확장(Scale-out)이나 캐시 최적화에 대한 장점을 가지고 있지만,
매번 인증, 토큰 등을 헤더에 담아 보내거나 사용자가 항상 로그인을 해야 한다는 단점을 가지고 있습니다.
이러한 단점을 보완하기 위한 방법 중 하나가 세션(Session)입니다.
2. 세션
세션(Session)은 HTTP 통신에서 "같은 사용자의 여러 요청" 을 하나의 연속된 대화로 묶기 위해, 서버가 사용자별로 생성, 관리하는 상태공간입니다. 세션은 총 3가지 요소가 포함 되어있습니다.
2-1) 요소 세 가지
- 세션 ID
- 서버가 생성한 고유 난수 토큰 (ex. 4F08A5B2D3…)
- 세션 저장소(Session Store)
- 세션 ID ↔
Map<String, Object>
를 매핑 - 기본은 톰캣 JVM 메모리
- 세션 ID ↔
- 전송 수단 (쿠키) - 브라우저는 세션 ID를 쿠키(JSESSIONID)에 보관해 모든 요청에 자동 첨부 - 서버는 헤더의 세션 ID로 세션 저장소에서 Map을 찾아 꺼냄 세션은 이 총 3가지 요소를 가지고 서버와 클라이언트가 연속적인 상태 정보를 관리할 수 있을뿐만아니라, 사용자는 한 번 로그인하면 여러 요청에 대해 인증 정보를 매번 입력하지 않아도됩니다.
2-2) 세션 동작
서버와 클라이언트가 연속적인 상태 정보를 관리하기위해 세션이 어떻게 생성되는지 설명하겠습니다. 동작과정
클라이언트는 서버에게 요청을 보냅니다 (
/login
)서버는 요청을 확인하고
sessionId(JSESSIONID)
를 생성하고sessionId
를 포함해서 클라이언트에 요청한 값을 보냅니다.브라우저는
sessionId(JSESSIONID)
를 저장하고 요청 값을 받습니다.이후 브라우저는 앞으로 서버에 요청할 때
sessionId(JSESSIONID)
를 포함하고 요청을 보냅니다.
더 이해하기 쉽게 코드로 설명하겠습니다.
@GetMapping("/login")
public ResponseEntity<?> startPage(HttpServletRequest request,
HttpSession httpSession) {
// 세션 ID가 세션에 이미 있는지 확인 (이미 로그인 했는지 체크)
String sessionId = (String) httpSession.getAttribute("sessionId");
// 세션 ID가 없다면(처음 접속이라면)
if (sessionId == null) {
// 새로운 세션 ID를 생성
sessionId = interviewService.createSession(); //사용자 임의 지정
// 세션에 저장
httpSession.setAttribute("sessionId", sessionId);
log.info("새로운 세션 생성: " + sessionId);
} else {
log.info("기존 세션 사용: " + sessionId);
}
}
- 처음에 브라우저가 보낸 요청중에 sessionId 가 있는지 확인합니다.
- sessionId 가 없다면 서버에서 sessionId(sessionId 규칙은 사용자 지정)를 생성합니다.
- HttpSession을 사용하면 WAS가 알아서 JSESSIONID=xxxx 형태로 쿠키를 발급해서 자동 연동을 합니다. 실제로 밑에 사진을 보면 JESSIONID가 실제로 발급 되어있는것을 확인할수 있습니다.


하지만 세션 ID는 서버에서 인증할 때 매우 중요한 키이기 때문에,
이 키가 노출되면 공격자에게 사용자 정보가 그대로 넘어갈 수 있습니다.
따라서 세션에 대한 보안 강화가 필요합니다.
세션 보안을 강화하기 위한 대표적인 방법들은 다음과 같습니다.
방법 | 방어 방법 |
---|---|
Session Hijacking – 공격자가 네트워크 스니핑·악성 JS로 JSESSIONID를 탈취 | 1) HTTPS 강제 (모든 페이지) 2) 쿠키 Secure 플래그로 평문 전송 차단 3) HttpOnly 플래그로 XSS를 통한 JS 접근 차단 |
Session Fixation – 공격자가 미리 만든 세션 ID를 피해자에게 심어두고 로그인만 기다리는 공격 | 로그인 직후 session.invalidate() → request.getSession(true) 로 새 ID 발급(스프링 시큐리티는 SessionFixationProtection 기본) |
세션 탈취 후 장기 사용 | 1) 타임아웃 줄이기 server.servlet.session.timeout=30m 2) 민감 작업(비밀번호 변경, 계정 삭제) 전에 재인증 요구 |
쿠키 전달 방식 허점 – 다른 도메인/서브도메인에 의도치 않게 전파 | SameSite=Lax 또는 Strict 로 교차 사이트 요청에 쿠키 자동 전송 제한 |
세션 객체에 과도한 정보 직렬화 – 메모리 폭증·직렬화 취약점 | 세션엔 최소·불변 DTO만 저장. 대용량·민감 데이터는 Redis·DB 캐시로 분리 |
다중 노드 간 세션 강제 로그아웃 | Spring Session + Redis 도입 → 노드 간 세션 공유 & TTL, 백업·모니터링(레디스 Sentinel/Cluster) 설정 |
스프링부트에서는 세션 보안 강화를 위해 라이브러리를 지원합니다.
@Bean
public ServletWebServerFactory cookieSecureFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context ctx) {
SessionCookieConfig cfg = ctx.getServletContext().getSessionCookieConfig();
cfg.setHttpOnly(true);
cfg.setSecure(true); // HTTPS 필수
cfg.setSameSite("Lax"); // Strict / Lax / None
}
};
}
하지만 보완을해도 세션을 실제 환경에서 사용하면 단점이 있습니다.
3) 세션 단점
1. 서버를 재기동하면 서버에 있는 세션값이 사라져서 클라이언트에 저장된 sessionId 값이 일치하지않아 오류가 발생합니다.
- 클래스를 리로드하거나 docker restart처럼 애플리케이션 프로세스가 한번 내려가면 JVM 힙이 초기화됩니다. 이 순간 힙은 새로 초기화되므로, 방금 전까지 살아있던 세션 Map이 모두 초기화가 됩니다.
- 브라우저는 초기화가 된 사실을 모르기 때문에, 브라우저는 이전에 받은 JSESSIONID를 그대로 헤더에 실어 다시 보냅니다. 서버 입장에선 그 ID로 된 세션은 없어서 결국 InvalidSessionIdException 이나 404 Not Found 같은 오류가 터집니다
2. 트래픽이 급증 시 부하가 생깁니다.
- 평소엔 세션 하나가 차지하는 메모리가 미미해 보여도, 동시 접속자가 폭주하면 기하급수적으로 메모리 사용량이 늘어납니다. - 세션 객체에 DTO나 리스트를 집어넣으면 메모리 사용량은 더 가파르게 올라갑니다. 3. 스케일 아웃(다중 노드(서버 인스턴스))에서 세션 불일치 이슈
- 파드(Kubernetes)를 여러개(스케일 아웃)을하면 세션 정보가 각 서버(노드) 메모리에 따로 저장되어 일관성이 깨질 수 있습니다.
- 이럴때 Sticky Session을 의존하여 사용자를 항상 같은 서버로 보내는 방법을 사용해야합니다.
- 하지만 노드 장애가 일어나거나 스케일 다운 때는 여전히 세션 유실이 된다는 단점이 있습니다.
- 이럴때 Sticky Session을 의존하여 사용자를 항상 같은 서버로 보내는 방법을 사용해야합니다.
이런 세션의 한계점을 극복하기 위해, Redis와 같은 외부 세션 저장소를 도입하거나
JWT 기반의 무상태 인증 등 다양한 대응 방법이 있습니다.
저는 이번 프로젝트에서 세션을 사용하기 때문에 Redis를 세션 저장소로 도입하려고 합니다.
다음 게시글에서는 Redis를 활용해 세션 불일치 문제를 어떻게 해결할 수 있는지 정리해보겠습니다.
읽어주셔서 감사합니다.