Tomcat과 Spring 컨테이너의 요청 처리 흐름

dradra·2024년 11월 2일
1

Spring Boot Deep Dive

목록 보기
1/2

Spring Boot Deep Dive (1)

Spring Deep Dive를 준비하게 된 이유

최근에 백엔드 개발을 하면서 느낀 점이 있다. 여러 Background 지식들이 파편처럼 모이는 것이 꽤나 도움이 됐다는 것이다. 예를 들어, @RestControllerAdvice로 예외를 관리할 때 필터 단에서는 처리할 수 없다는 것을 알게 되었을 때, 예전에 UsernamePasswordAuthenticationFilter를 상속한 LoginFilter를 직접 구현하면서의 기억을 떠올리면서 상기하게 되었다.
웹, 네트워크, OS과 같은 지식들도 마찬가지라 생각한다. 우선 지금은 개발과 가장 근접한 프레임워크인 Spring Boot에 대해 깊이 공부해볼 것이다.

0. 요청 처리 흐름 그림


[해당 포스트에 사용된 개념 및 자료는 ASAC 웹 풀스택 교육에서 일부 참고하였습니다.]

Tomcat의 서블릿 컨테이너FilterChainDispatcherServlet을 통해 Spring 컨테이너의 WebApplicationContextRoot WebApplicationContext 내의 HandlerMapping, Controller, Security 등 다양한 컴포넌트와 상호작용하여 클라이언트 요청을 처리한다.

🤔 서블릿 컨테이너(Servlet Container)란?

  • 웹 애플리케이션을 실행하고 관리하는 환경
  • JSP나 서블릿 같은 웹 컴포넌트를 실행할 수 있도록 지원하는 서버
  • Tomcat자바 서블릿과 JSP(JavaServer Pages)를 실행할 수 있도록 지원하는 오픈 소스 웹 서버이자 서블릿 컨테이너이다.

1. Tomcat의 역할

Tomcat

1-0. Web Server

  • 사용자가 브라우저에서 작성한 HTML, CSS, JS 같은 정적 파일들을 서빙하는 부분이다.

1-.1 Servlet Container

  • 웹 요청을 받아들여 Spring으로 넘겨주는 역할을 한다.
  • 여기서 FilterChain이 구성되어 있고, 여러 필터들이 요청을 사전 처리하는 구조를 볼 수 있다.

1-2. DelegatingFilterProxy

  • DelegatingFilterProxy 는 Spring Security에서 설정한 필터 체인으로 요청을 전달한다.
  • 실제 보안 관련 처리는 Spring Security가 담당하지만, Tomcat의 필터 체인을 통해 그 처리가 시작되는 것이다.

1-3. DispatcherServlet (FrontController)

  • DispatcherServlet이 흔히 말하는 FrontController이다.

  • DispatcherServletSpring MVC의 중심으로서 모든 HTTP 요청은 이 서블릿을 거쳐 간다. Spring 애플리케이션에서 일어나는 모든 요청의 진입점이자 라우터 역할을 한다.

  • 요청을 받아들인 후, 이 요청을 어떻게 처리할지를 결정하기 위해 Spring MVC의 다양한 컴포넌트들과 상호작용한다.

  • 주요 컴포넌트는 Handler Interceptor, Handler Mapping, Handler Adapter, Handler Exception Resolver, View Resolver로 구성되어 있다.

Handler Interceptor

  • 요청 전후로 특정 작업을 수행하는 인터셉터이다. 예를 들어, 로깅, 인증 검사 등을 처리할 수 있다. PreHandle, PostHandle 같은 메서드를 통해 요청 전후에 실행할 로직을 정의할 수 있다.

Handler Mapping

  • DispatcherServlet은 우선 Handler Mapping을 통해 요청 URL에 맞는 컨트롤러(핸들러)를 찾으려고 한다. 요청 경로에 맞는 핸들러 객체를 매핑하는 것이다.
  • 예를 들어, 요청이 /user/profile 경로로 들어온다면, Handler Mapping은 이 URL 패턴에 맞는 컨트롤러의 메서드를 찾아준다.

Handler Adapter

  • Handler Mapping이 알맞은 컨트롤러를 찾으면, Handler Adapter가 이 컨트롤러를 실제로 실행하는 역할을 한다.
  • 각 핸들러마다 동작 방식이 다를 수 있기 때문에, Handler Adapter가 컨트롤러의 메서드를 호출하고 그 결과를 받는 역할을 담당해. 이를 통해 요청을 처리하고, 결과 데이터를 얻을 수 있다.

Handler Exception Resolver

  • 요청 처리 중에 예외가 발생하면, Handler Exception Resolver가 이 예외를 잡아서 적절한 응답을 만들어주는 역할을 한다.
  • 예를 들어, 인증되지 않은 사용자에게는 401 에러 페이지를, 리소스를 찾을 수 없을 때는 404 에러 페이지를 반환하는 방식으로 동작한다.

View Resolver

  • 컨트롤러가 반환한 뷰 이름을 실제 뷰(HTML, JSP) 파일로 변환해주는 역할을 한다.

❓DispatcherServlet은 Servlet Container에 속한 것일까 아니면, Spring Container에 속하는가?


출처 : https://mossgreen.github.io/Servlet-Containers-and-Spring-Framework/

Tomcat과 Spring이 요청을 처리하는 흐름을 공부하기 위해 다른 포스팅들을 살펴보면, Dispatcher 서블릿이 Servlet Container에 속한다고 보는 그림도 있고, Spring Container에 속하는 것처럼 보이는 그림도 존재한다. 왜 이럴까?

DispatcherServletServlet ContainerSpring Container의 경계에서 동작하는 역할을 한다.
두 컨테이너에 걸쳐 있는 특별한 서블릿이라고 이해할 수 있다.

Servlet Container의 일부라고 보는 관점

  • DispatcherServlet은 서블릿이기 때문에 Tomcat 같은 서블릿 컨테이너에 의해 초기화되고 실행된다.
  • 이는 서블릿 스펙에 따라 동작하고, URL 매핑을 통해 요청을 받는 등의 역할을 수행한다.
  • 따라서 기본적으로 Servlet Container의 일부로 간주할 수 있다.

Spring Container의 일부라고 보는 관점

  • DispatcherServlet은 Spring MVC의 핵심 컴포넌트로, 내부적으로 Spring의 ApplicationContext(주로 WebApplicationContext)와 통합된다.
  • 이를 통해 Spring Bean을 관리하는 Spring Container의 기능도 활용할 수 있다.
  • 즉, 요청을 받아 Spring MVC 구조에 따라 적절한 핸들러(Controller)를 호출하기 위해 Spring Container와 연결되는 역할도 수행한다.

왜 그림마다 다르게 표기될까?

  • DispatcherServlet이 서블릿 역할과 Spring과의 통합을 동시에 수행하기 때문이다.
  • Tomcat 은 Servlet 이라는 인터페이스를 통해 웹 처리를 하고,
  • Spring 은 Servlet 인터페이스에 대한 Spring 만의 구현체 DispatcherServlet 자체 개발을 수행한다.

2. Spring 컨테이너의 구성 요소

2-1. Root WebApplicationContext

  • 애플리케이션 전체에서 공유되는 전역적인 Bean을 관리하는 최상위 컨텍스트이다.
  • Service, Repository, Spring Security와 같은 공통적으로 사용되는 Bean들을 가지고 있다.

구성 요소:

  • Service: 비즈니스 로직을 처리하는 계층으로, Repository와 상호작용하여 데이터를 가져오거나 처리한다.
  • Repository: 데이터베이스와 직접 연결되는 계층으로, 주로 JPA, MyBatis 등의 ORM과 연결된다.
  • Spring Security: 애플리케이션의 인증과 권한 관리를 담당함. SecurityContextHolder, AuthenticationManager, SecurityFilterChain, FilterChainProxy 등의 구성 요소로 보안 기능을 제공한다.

2-2. Servlet WebApplicationContext

  • DispatcherServlet에 의해 생성되는 컨텍스트로, 각 서블릿의 Bean을 관리한다. 주로 웹 요청 처리에 필요한 Bean들이 여기에 속한다.
    해당 그림에서는 HandlerMapping, HandlerInterceptor 등 DispatcherServlet의 요소가 포함되어 있는데 이 요소들은 앞에 설명한 것이라 생략하겠다.

3. Spring Security의 구성

SecurityContextHolder

  • 사용자의 인증 정보를 관리하는 핵심 객체이다.
  • 인증된 사용자의 세션 정보나 권한 정보를 저장한다.

AuthenticationManager

  • 사용자 인증을 실제로 처리하는 곳이다.
  • 사용자가 로그인을 시도할 때, 입력된 사용자 정보를 확인하고 인증된 사용자인지 검사하는 역할을 한다.

SecurityFilterChain

  • 여러 보안 필터들로 구성된 체인으로, 요청이 들어올 때마다 차례로 필터링을 수행한다.
  • 각 필터는 인증이나 권한 검사 같은 특정 보안 작업을 수할 수 있다.

Filter ChainProxy

  • Security FilterChain을 관리하는 역할을 하는 프록시 객체이다.
  • 요청이 들어오면 이 프록시가 적절한 보안 필터 체인을 선택하고, 요청을 그 체인에 전달해 보안 검사를 수행하게 한다.

번외. DelegatingFilterProxy와 FilterChainProxy의 차이

💡 Servlet Container단에도 FilterChain이 있고, Spring Security단에도 FilterChain이 있는 것을 확인할 수 있다. 그리고, 둘 다 Proxy가 존재하는 것을 볼 수 있는데, 이 둘의 차이점에 대해 궁금해졌다.

DelegatingFilterProxy

  • DelegatingFilterProxy는 Servlet 필터로서 Spring Security의 진입점 역할을 한다.
  • Servlet 컨테이너(Tomcat)의 FilterChain에 등록되며, Spring Security의 필터 체인으로 요청을 위임하는 역할을 수행한다.

본질적으로 DelegatingFilterProxySpring Security가 아닌 Servlet Container 차원에서 설정되는 필터이다. 따라서 이 필터는 요청을 받아 Spring ApplicationContext 내에서 정의된 Bean인 FilterChainProxy를 호출한다.

쉽게 말해, DelegatingFilterProxy는 단지 FilterChainProxy로 요청을 넘기는 역할을 할 뿐, 직접적으로 보안 처리를 하지 않는다.

FilterChainProxy

FilterChainProxy는 Spring Security가 제공하는 실제 보안 필터 체인이다. Spring Security 내에서 보안 관련 필터들이 모여 있는 필터 체인을 관리하는 역할을 한다.

DelegatingFilterProxy를 통해 요청이 들어오면, FilterChainProxy는 각종 필터들을 차례로 실행하여 보안 처리를 진행한다.

Spring ApplicationContext에서 관리되는 Bean으로, Spring Security에서 설정한 여러 보안 필터를 순서대로 호출하면서 요청을 처리한다.

정리하자면, FilterChainProxy는 Spring Security의 필터들을 관리하고, 적절한 순서로 필터 체인을 실행해서 인증, 인가, 세션 관리 등의 보안 처리를 수행한다.

0개의 댓글

관련 채용 정보