Post

스프링 세션의 이해:등장 배경과 그 원리

🔍️ 왜 세션이 필요한가?

웹에서 데이터를 전송하는 데 기본적으로 사용되는 HTTP는 본질적으로 상태가 저장되지 않는다. 즉, 동일한 사용자로부터 여러 요청이 들어와도 이를 인식하지 못한다. 그러나 웹 애플리케이션에서 사용자 인증, 장바구니 등과 같은, 상태를 유지하는 것이 중요한 시나리오가 있다. 세션은 웹 애플리케이션이 특정 기간 동안 사용자를 인식하고 구분할 수 있게 함으로써 이러한 한계를 극복하는 데 중요한 역할을 한다.

🔍 세션은 언제 생성되는가?

세션은 다음과 같은 경우에 생성된다.

  • HttpServletRequest의 request.getSession()을 명시적으로 호출할 때 생성된다.
  • Spring Security를 사용하는 경우 SessionCreationPolicy에 따라 생성된다.
    • SessionCreationPolicy.IF_REQUIRED: 필요한 경우에만 생성 (기본값)

🔍전통적인 세션의 문제점

전통적인 HttpSession은 컨테이너(ex. Tomcat) 에 의해 생성되고 종속되어 사용된다. 즉 컨테이너가 세션을 생성하고 애플리케이션에 세션 ID를 전달한다. 이는 컨테이너가 자체 HTTPSession을 관리한다는 것을 의미하며, 분산 환경에서 실행되는 경우 다른 서버 간에 세션 공유를 불가능하게 하는 원인이 된다.

✏️ 고정 세션

이를 해결하기 위해 고정 세션 접근 방식을 사용할 수 있다.

  1. 로드밸런서 또는 웹 서버가 클라이언트와 앱 서버 간에 매칭을 한다.
  2. 이 작업은 로드 밸런서가 식별을 위해 클라이언트에 쿠키를 할당함으로써 수행된다.
  3. 로드 밸런서는 세션이 진행되는 동안 클라이언트의 각 요청을 동일한 애플리케이션 서버로 라우팅 한다.

고정세션

고정 세션 방식은 다음과 같은 문제점을 가지고 있다.

  1. 특정 서버에 과부하가 걸릴 수 있다.
  2. A서버가 다운되면 B서버는 A서버의 세션에 대한 정보를 얻지 못한다.

🔍 Spring Session

이러한 문제를 해결하기 위해 Spring에서는 HTTP Session을 중앙에서 관리하도록 도와준다.

스프링세션

Session Storage 방식을 사용하면 다음과 같은 장점을 가질 수 있다.

  1. 애플리케이션 재시작 시 세션 복원이 가능하다.
  2. 로드 밸런서에서 세션을 고정할 필요가 없다.
    -> 특정 서버에 과부하를 주지 않고 독점적으로 분산할 수 있다.

단점

  1. Session Storage에 장애가 발생하면 모든 세션을 잃어버려 세션을 사용하는 모든 서버에 영향을 미친다. 이를 해결하기 위해 마스터-슬레이브 복제 방법을 사용할 수 있다.
  2. 네트워크 I/O가 발생하기 때문에 로컬 메모리보다는 성능적인 면에서 떨어진다.

🔍️Spring Session의 원리

Spring Session은 애플리케이션과 Session management간의 추상화 계층을 제공함으로써 NoSQL, RDBS 등과 같은 영구 저장소에 저장할 수 있도록 도와준다. 따라서 어떤 데이터베이스를 사용하든 Spring Session이 제공하는 API를 통해 똑같은 방법으로 관리가 가능하다. 사용할 수 있는 저장소로는 다음 JDBC, Redis, MongoDB 등이 있다.

Spring Session은 HttpSession을 필터와 Wrapper로 감쌈으로써 기능을 제공한다.

  1. SessionRepositoryRequestWrapper를 이용하여 기본 HttpSession을 커스텀 세션으로 바꾼다.
    1
    2
    3
    4
    5
    6
    
      public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest {
      
     public HttpServletRequestWrapper(HttpServletRequest request) {  
         super(request);  
     }
      }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
      public class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
      
     public SessionRepositoryRequestWrapper(HttpServletRequest original) {
         super(original);
     }
      
     public HttpSession getSession() {
         return getSession(true);
     }
      
     public HttpSession getSession(boolean createNew) {
         // create an HttpSession implementation from Spring Session
     }
      
     // ... other methods delegate to the original HttpServletRequest ...
      }
    
  2. HttpServlet 요청을 세션 리포지토리 요청 래퍼로 대체한다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    public class SessionRepositoryFilter implements Filter {
    
     public doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
             HttpServletRequest httpRequest = (HttpServletRequest) request;
             SessionRepositoryRequestWrapper customRequest =
                     new SessionRepositoryRequestWrapper(httpRequest);
    
             chain.doFilter(customRequest, response, chain);
     }
    
     // ...
    }
    

놀라운 점은 스프링 부트를 사용하면 Auto-Configuration 기능 덕분에 다음과 같은 의존성을 추가하고 yml파일에 설정해주는 것만으로 위의 작업을 자동화해준다.

1
implementation("org.springframework.boot:spring-boot-starter-data-redis")
1
spring.session.store-type=redis # Session store type.

이렇게 하면 Filter를 구현하는 springSessionRepositoryFilter라는 이름의 Spring 빈이 생성되며, 이 필터는 스프링 세션이 지원하도록 HttpSession 구현을 대체하는 역할을 담당한다.

🔍 결론

  • 웹 애플리케이션의 세션 관리는 사용자 인증 및 쇼핑 카트와 같은 상태 유지가 필요한 경우에 매우 중요하다.
  • 전통적인 HttpSession은 분산 환경에서의 한계를 가지고 있으며, 이를 해결하기 위해 스프링 세션은 중앙집중식으로 세션을 관리한다.
  • 세션 저장소 다운으로 인한 전체 세션 손실의 가능성과 네트워크 I/O에 의한 성능 저하와 같은 단점도 고려해야 한다.

🔍관련 글

스프링 세션 적용하기

Key가 두 개 생기는 이유

쿠키와 Base64 인코딩

Vue.js에서 커스텀 쿠키 및 세션 정보 받기

참고 자료

How to Use Session from Oracle

SpringSession - Redis Guide

SpringSession - Redis Guide2

SpringSession - configuration

Session With Spring Security

This post is licensed under CC BY 4.0 by the author.

© bear-su. Some rights reserved.