Spring Deep Dive를 준비하게 된 이유
최근에 백엔드 개발을 하면서 느낀 점이 있다. 여러 Background 지식들이 파편처럼 모이는 것이 꽤나 도움이 됐다는 것이다. 예를 들어,
@RestControllerAdvice
로 예외를 관리할 때 필터 단에서는 처리할 수 없다는 것을 알게 되었을 때, 예전에UsernamePasswordAuthenticationFilter
를 상속한LoginFilter
를 직접 구현하면서의 기억을 떠올리면서 상기하게 되었다.
웹, 네트워크, OS과 같은 지식들도 마찬가지라 생각한다. 우선 지금은 개발과 가장 근접한 프레임워크인 Spring Boot에 대해 깊이 공부해볼 것이다.
[해당 포스트에 사용된 개념 및 자료는 ASAC 웹 풀스택 교육에서 일부 참고하였습니다.]
Tomcat의 서블릿 컨테이너는
FilterChain
과DispatcherServlet
을 통해 Spring 컨테이너의WebApplicationContext
와Root WebApplicationContext
내의HandlerMapping
,Controller
,Security
등 다양한 컴포넌트와 상호작용하여 클라이언트 요청을 처리한다.
🤔 서블릿 컨테이너(Servlet Container)란?
- 웹 애플리케이션을 실행하고 관리하는 환경
- JSP나 서블릿 같은 웹 컴포넌트를 실행할 수 있도록 지원하는 서버
- Tomcat은 자바 서블릿과 JSP(JavaServer Pages)를 실행할 수 있도록 지원하는 오픈 소스 웹 서버이자 서블릿 컨테이너이다.
DelegatingFilterProxy
는 Spring Security에서 설정한 필터 체인으로 요청을 전달한다. DispatcherServlet
이 흔히 말하는 FrontController
이다.
DispatcherServlet
은 Spring MVC의 중심으로서 모든 HTTP 요청은 이 서블릿을 거쳐 간다. Spring 애플리케이션에서 일어나는 모든 요청의 진입점이자 라우터 역할을 한다.
요청을 받아들인 후, 이 요청을 어떻게 처리할지를 결정하기 위해 Spring MVC의 다양한 컴포넌트들과 상호작용한다.
주요 컴포넌트는 Handler Interceptor, Handler Mapping, Handler Adapter, Handler Exception Resolver, View Resolver로 구성되어 있다.
PreHandle
, PostHandle
같은 메서드를 통해 요청 전후에 실행할 로직을 정의할 수 있다.DispatcherServlet
은 우선 Handler Mapping을 통해 요청 URL에 맞는 컨트롤러(핸들러)를 찾으려고 한다. 요청 경로에 맞는 핸들러 객체를 매핑하는 것이다./user/profile
경로로 들어온다면, Handler Mapping은 이 URL 패턴에 맞는 컨트롤러의 메서드를 찾아준다.
출처 : https://mossgreen.github.io/Servlet-Containers-and-Spring-Framework/
Tomcat과 Spring이 요청을 처리하는 흐름을 공부하기 위해 다른 포스팅들을 살펴보면, Dispatcher 서블릿이 Servlet Container에 속한다고 보는 그림도 있고, Spring Container에 속하는 것처럼 보이는 그림도 존재한다. 왜 이럴까?
DispatcherServlet은 Servlet Container와 Spring Container의 경계에서 동작하는 역할을 한다.
두 컨테이너에 걸쳐 있는 특별한 서블릿이라고 이해할 수 있다.
Service
, Repository
, Spring Security
와 같은 공통적으로 사용되는 Bean들을 가지고 있다.SecurityContextHolder
, AuthenticationManager
, SecurityFilterChain
, FilterChainProxy
등의 구성 요소로 보안 기능을 제공한다.SecurityContextHolder
AuthenticationManager
SecurityFilterChain
Filter ChainProxy
💡 Servlet Container단에도 FilterChain이 있고, Spring Security단에도 FilterChain이 있는 것을 확인할 수 있다. 그리고, 둘 다 Proxy가 존재하는 것을 볼 수 있는데, 이 둘의 차이점에 대해 궁금해졌다.
본질적으로 DelegatingFilterProxy
는 Spring Security가 아닌 Servlet Container 차원에서 설정되는 필터이다. 따라서 이 필터는 요청을 받아 Spring ApplicationContext 내에서 정의된 Bean인 FilterChainProxy
를 호출한다.
쉽게 말해, DelegatingFilterProxy
는 단지 FilterChainProxy
로 요청을 넘기는 역할을 할 뿐, 직접적으로 보안 처리를 하지 않는다.
FilterChainProxy
는 Spring Security가 제공하는 실제 보안 필터 체인이다. Spring Security 내에서 보안 관련 필터들이 모여 있는 필터 체인을 관리하는 역할을 한다.
DelegatingFilterProxy
를 통해 요청이 들어오면, FilterChainProxy
는 각종 필터들을 차례로 실행하여 보안 처리를 진행한다.
Spring ApplicationContext에서 관리되는 Bean으로, Spring Security에서 설정한 여러 보안 필터를 순서대로 호출하면서 요청을 처리한다.
정리하자면, FilterChainProxy는 Spring Security의 필터들을 관리하고, 적절한 순서로 필터 체인을 실행해서 인증, 인가, 세션 관리 등의 보안 처리를 수행한다.