세션(Session)은 다양한 의미로 사용됩니다. 터미널에서의 세션, 웹에서의 세션 등 여러 맥락에서 세션은 상태를 유지하기 위한 방법을 제공합니다. 이 글에서는 Spring에서의 세션 동작 방식과 세션 클러스터링(Session Clustering)에 대해 다뤄보겠습니다.
HttpSession
HTTP 프로토콜은 본질적으로 무상태(Stateless) 프로토콜이다. 이는 각 요청이 독립적으로 처리되며, 서버가 특정 사용자의 요청 순서나 상태를 기억하지 않는다는 의미이다. 즉, 사용자는 매 요청마다 자신의 신원을 식별할 수 있는 정보를 서버에 전달해야 한다.
HTTP 요청이 상태를 유지하지 않기 때문에, 서버와 클라이언트는 추가적인 메커니즘을 통해 상태를 유지해야 한다. 이때 가장 많이 사용하는 방법이 쿠키(Cookie)와 세션(Session)이다.
- 쿠키(Cookie):
- 서버가 클라이언트에게 특정 데이터를 전달하고, 클라이언트는 이를 브라우저에 저장한다.
- 이후 클라이언트는 저장된 쿠키를 사용해 서버에 자신을 식별할 수 있는 정보를 다시 전송한다.
- 세션(Session):
- 세션은 서버가 특정 클라이언트를 식별할 수 있는 정보를 서버에 저장한다.
- 클라이언트는 서버가 발급한 세션 ID를 쿠키로 저장하고, 이후 요청 시 이 세션 ID를 서버에 전달하여 이전 상태를 유지한다.
위 그림은 Client와 Server 사이에서 Session과 Cookie가 통신하는 과정을 보여준다.
- 처음 페이지 접근 시:
- 클라이언트가 서버에 처음 접근할 때 서버는 클라이언트에 대한 식별 정보가 필요하며, 이를 위해 세션 ID를 생성한다.
- 세션 ID를 쿠키에 설정:
- 생성된 세션 ID는 쿠키에 저장되어 클라이언트로 전송된다. 이 쿠키는 클라이언트의 웹 브라우저에 저장된다.
- 쿠키가 있는 상태로 페이지 재접근:
- 클라이언트가 서버에 다시 페이지를 요청할 때, 이전에 저장된 쿠키(세션 ID 포함)를 함께 서버에 전송한다. 이를 통해 서버는 클라이언트를 식별할 수 있다.
- 데이터와 함께 응답:
- 서버는 클라이언트가 전송한 세션 ID를 확인하고 해당 세션에 저장된 데이터를 참조하여 필요한 정보를 클라이언트에게 응답한다.
이 과정을 통해 상태가 없는 HTTP 프로토콜 상에서도 사용자의 로그인 상태나 설정 등을 기억하고 관리할 수 있다.
Spring boot에서 Session
Spring Boot를 사용하면, Spring Boot 프로젝트에 내장되어 있는 Tomcat 서버가 세션을 생성한다.
특히 JSESSIONID라고 하는 쿠키값은 서버 내부의 Tomcat이 처음 접근한 브라우저에게 발급하는 쿠키이다. Tomcat은 이 쿠키의 값을 바탕으로 세션을 관리하고, HttpSession 객체로 만들어 준다. 그리고 Spring Boot의 Controller 메서드에서 해당 HttpSession을 가져와 사용할 수 있다. 참고로 Redis와 같은 별도의 Session 저장소를 사용하는 경우 쿠키값이 달라질 수 있다.
분산 서버 환경에서 Session
Scale-Out은 동일 기능을 하는 여러 서버를 추가하여 요청을 분산하는 방법이다. 웹 애플리케이션에서 사용자 수가 증가하면, 단일 서버로는 요청을 모두 처리하기 어려워질 수 있다. 따라서 이러한 방법을 통해 분산 서버를 운용하여 시스템 처리 능력을 향상시킬 수 있다.
하지만 위와 같은 상황에서 사용자가 A 서버로 요청을 했다가, B 서버로 요청을 하게 된다면 세션이 유지될 수 없다. 왜냐하면, 각 서버마다 Session Storage를 갖는 경우 세션 정보를 가지고 있지 않기 때문이다.
따라서 세션을 유지하기 위한 전략이 필요하다.
Sticky Session
Scale-Out 환경에서 세션 유지를 위한 한 방법은 Sticky Session이다. 이는 사용자의 모든 요청을 처음 연결된 서버에 고정시키는 방식으로, 세션 정보가 해당 서버에만 유지된다. 하지만 이 방식은 서버 간 요청이 불균등하게 분산될 수 있어 일부 서버에 과부하가 걸릴 수 있다.
Session Clustering
다른 대안으로 Session Clustering이 있다. 이 방식에서는 여러 서버가 외부 저장소(예: Redis, Memcached)를 공유하여 세션 정보를 유지한다. 이러한 방식의 장점은 세션 정보가 중앙 저장소에 있기 때문에, 서버를 자유롭게 추가하거나 제거할 수 있다. 또한 서버의 장애가 생겨도 세션 정보가 보존되어 안정성이 향상되고, 세션 정보가 모든 서버에 공유되기 때문에 로드 밸런서가 요청을 더 균등하게 분산시킬 수 있다.
다만, 이렇게 될 경우 서버 외부에 세션을 저장하는 것이므로 관리 포인트가 늘어나게 되며, 통신 과정에서 어쩔 수 없는 지연이 발생한다.
그래서 지연이 적은 Redis와 같은 인메모리 데이터베이스가 많이 사용된다.
참고
- 팀스파르타코딩클럽 인메모리 저장소 및 캐싱 전략 강의자료
'Development > Spring' 카테고리의 다른 글
[Spring] @Builder사용할 때 @AllArgsConstructor를 적용하면 왜 @NoArgsConstructor와 함께 쓰이지 못하는가? (0) | 2024.08.12 |
---|---|
[Spring] MSA와 Spring Cloud (1) | 2024.07.31 |
[Spring] MVC 패턴과 Spring MVC (0) | 2024.07.22 |
[Spring] 서버 모니터링을 위한 Spring Actuator, Prometheus, Grafana 추가하기 (0) | 2024.07.12 |
[Spring] Redisson을 활용한 캐시 사용하기 (0) | 2024.07.11 |