SpringBoot는 요청을 어떻게 '제어'할까? – 세션, 필터, 리스너로 흐름을 다루는 방법

EunBeen Noh·2025년 5월 8일

SpringAdvanced

목록 보기
11/16

지난 글에서는 SpringBoot가 다중 요청을 Tomcat의 스레드 풀로 어떻게 처리하는지를 살펴봤다.

https://velog.io/@goldcong/spring-servlet-threadpool

이번에는 그 요청 흐름에 우리가 개입하거나 상태를 유지하고, 반응하는 방법에 대해 알아본다.
즉, 단순히 요청을 “받는” 것을 넘어, 요청을 다루는 구조(Scope와 Lifecycle)가 어떻게 동작하는지를 이해하는 것이 핵심이다.

0. SpringBoot는 요청을 어떻게 '제어'할까?

— 세션, 필터, 리스너로 흐름을 다루는 방법

지난 글에서는 SpringBoot에서 다중 요청이 들어왔을 때,
Tomcat이 어떻게 스레드 풀(Thread Pool)을 통해 요청을 처리하고,
Spring은 DispatcherServlet을 중심으로 요청을 분기 처리한다는 흐름을 다뤘다.

하지만 요청을 잘 "받는 것"만큼이나 중요한 건,
요청 흐름에 직접 개입하거나, 요청 간 상태를 유지하거나, 시스템 이벤트에 반응하는 능력이다.
이번 글에서는 그 역할을 담당하는 세 가지 핵심 구조인 Session, Filter, Listener에 대해 정리한다.


1. Session — 요청 간 상태를 유지하는 수단

서블릿에서 제공하는 HttpSession사용자별로 상태를 서버에서 유지할 수 있는 가장 기본적인 구조다.

예를 들어 로그인한 사용자의 정보를 서버에 저장해두고,
이후 요청마다 해당 세션 값을 조회하여 사용자 인증 상태를 유지할 수 있다.

// 세션에 값 저장
HttpSession session = request.getSession();
session.setAttribute("username", "eunbeen");

// 이후 요청에서 세션 값 조회
String name = (String) session.getAttribute("username");

세션은 내부적으로 JSESSIONID라는 쿠키를 통해 브라우저와 연결되며,
서버는 이 ID를 기준으로 동일 사용자의 세션을 식별한다.

Spring에서는 기본적으로 HttpSession을 그대로 사용할 수 있으며,
Redis와 같은 외부 저장소를 이용한 세션 분산 처리도 지원한다.

2. Filter — 요청/응답 전후에 개입하는 전처리기

Filter는 모든 요청을 서블릿으로 전달하기 전/후에 공통 로직을 삽입할 수 있는 기능이다.
가장 대표적인 용도는 요청 로깅, 인코딩 처리, 인증/인가 처리 등이다.

@WebFilter(urlPatterns = "/*")
public class LogFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        System.out.println("[Filter] 요청 시작: " + request.getRemoteAddr());
        chain.doFilter(request, response); // 다음 필터 또는 서블릿 실행
        System.out.println("[Filter] 요청 종료");
    }
}

SpringBoot에서는 @ServletComponentScan을 통해 위 필터를 자동 인식시킬 수 있으며,
FilterRegistrationBean을 사용해 자바 설정 방식으로 등록할 수도 있다.

3. Listener — 시스템 이벤트에 반응하는 감시자

Listener는 서블릿 컨테이너 내부에서 발생하는 다양한 이벤트(생성/소멸 등)에 반응하는 구조다.

가장 대표적인 예는 세션의 생성/만료 이벤트를 감지하는 HttpSessionListener이다.

@WebListener
public class SessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("세션 생성됨: " + se.getSession().getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("세션 종료됨: " + se.getSession().getId());
    }
}

이 외에도 ServletContextListener, ServletRequestListener 등을 통해
어플리케이션 전체 또는 요청 단위의 생명주기를 감지할 수 있다.

구성요소주요 목적개입 시점
Session사용자별 상태 유지요청 간
Filter요청/응답 공통 로직 삽입서블릿 호출 전/후
Listener세션, 애플리케이션 이벤트 감지생성/종료 시점

0개의 댓글