웹 애플리케이션에는 두 개의 분리된 공간이 있습니다. 하나는 톰캣 같은 서블릿 컨테이너가 다스리는 서블릿이고, 다른 하나는 ApplicationContext가 모든 것을 관리하는 스프링입니다.
서블릿에 서블릿 필터는 모든 요청을 가장 먼저 만나는 문지기 역할을 합니다. 하지만 스프링에 대해 전혀 알지 못해서, '스프링 빈'에 도움을 요청할 방법이 없습니다.
그런데 Spring Security는 이 둘이 완벽하게 대화하며 협력하게 만듭니다. 어떻게 서블릿 필터는 스프링 빈에게 말을 걸 수 있는 것일지 오늘 포스팅을 통해 알아가보겠습니다.
이 둘을 제대로 이해하려면, 먼저 서로 얼마나 다른지 알아야 합니다.
@Service, @Repository 등 우리가 만든 모든 빈(Bean)들이 존재하고, 의존성 주입(DI)이나 AOP 같은 강력한 기능들을 마음껏 사용합니다.이처럼 둘은 서로의 존재를 모르기 때문에, 서블릿 필터가 @Autowired로 스프링 빈을 주입받는 것은 불가능합니다. 마치 서로 다른 언어를 쓰는 두 사람과 같습니다.
이때, 두 공간의 언어를 모두 할 줄 아는 DelegatingFilterProxy가 이를 도와줍니다.
DelegatingFilterProxy는 조금 특별한 서블릿 필터입니다.
몸은 서블릿에 속해 있어 서블릿 컨테이너에 의해 정상적으로 생성되고 동작합니다.
하지만, 스프링에 접근하여 그곳의 빈을 찾아낼 수 있습니다.
하는 역할은 아주 명확합니다.
실제 업무를 처리하지는 않지만 서블릿에 온 요청을 스프링에 있는 빈에게 위임
DelegatingFilterProxy는 이 임무를 수행하기 위해, 스프링에 springSecurityFilterChain이라는 이름을 가진 빈을 찾습니다.
DelegatingFilterProxy가 찾는 것이 바로 FilterChainProxy입니다. FilterChainProxy는 스프링에 존재하는 빈입니다.
스프링 빈이기 때문에 의존성 주입을 통해 우리가 HttpSecurity로 설정한 모든 보안 정책(SecurityFilterChain)들을 전부 알고 있습니다.
결국, DelegatingFilterProxy라는 통역사가 다리를 놓아준 덕분에, 서블릿의 세계로 들어온 요청이 마침내 스프링 세계의 보안 전문가인 FilterChainProxy와 성공적으로 만날 수 있게 된 것입니다.
이 둘의 대화(위임) 과정은 DelegatingFilterProxy의 코드에 그대로 담겨 있습니다.
"누구에게 말을 걸어야 하죠?" (전문가 찾기)
DelegatingFilterProxy는 요청을 받으면, 먼저 대화 상대(delegate)를 찾습니다. 처음에는 아는 전문가가 없으므로 initDelegate를 통해 찾아 나섭니다.
// DelegatingFilterProxy.java - initDelegate()
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
// "springSecurityFilterChain"이라는 이름의 전문가를 찾아주세요!
String targetBeanName = getTargetBeanName();
Filter delegate = wac.getBean(targetBeanName, Filter.class);
return delegate;
}
"말씀을 전해드리겠습니다." (요청 전달하기)
전문가(FilterChainProxy)를 성공적으로 찾았다면, invokeDelegate를 통해 원래 왔던 요청을 그대로 전달하며 대화를 시작시킵니다.
// DelegatingFilterProxy.java - invokeDelegate()
protected void invokeDelegate(
Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 찾은 전문가(delegate)에게 요청을 그대로 전달!
delegate.doFilter(request, response, filterChain);
}
결론적으로, 서블릿 필터가 스프링 빈에게 말을 거는 방법은 바로 DelegatingFilterProxy라는 뛰어난 통역사를 통하는 것이었습니다.
이 우아한 설계 덕분에 Spring Security는 서블릿 표준을 완벽하게 준수하면서도, 스프링 프레임워크가 제공하는 DI, AOP 등의 강력한 기능들을 보안 로직에 마음껏 녹여낼 수 있습니다. 이 둘의 매끄러운 대화가 바로 Spring Security가 강력하고 유연한 이유입니다.