클라이언트로 부터 서버로 요청이 들어오는 경우, Dispatcher Servlet
을 거치기전 요청 사항에 대한 공통 관심사를 처리하기 위한 필터 로직을 수행한다. 대표적으로 Spring Security
를 활용하여 요청에 대한 필터 기반 인증, 인가 처리를 수행하기 위해 많이 사용된다.
Servlet filter
는 javax.servlet.Filter
인터페이스를 구현하여 만들어진다. 이를 상속한 구현체는 세 가지 주요 메서드를 사용할 수 있다.
필터를 초기화하고 설정하는 메서드로, 일반적으로 스프링 어플리케이션이 실행될 때 한번만 실행된다.
필터가 소멸될 때 호출되는 메서드로, 일반적으로 스프링 어플리케이션이 종료될 때 한번만 실행된다.
실제로 필터가 수행해야하는 로직을 작성하는 메서드이다. 요청이나 응답을 가로채어 적절한 로직을 수행한 후, FilterChain
을 통해 또다른 필터 혹은 Servlet
단으로 전달하는 것이 가능하다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 요청 처리 로직...
// 필터 체인을 통해 다음 필터로 또는 서블릿으로 제어를 전달
chain.doFilter(request, response);
// 응답 가로채는 로직...
}
Spring MVC
에서, 웹 어플리케이션 내 특정한 URI
호출을 가로채어 공통 관심사를 처리하기 위한 인터셉터 로직을 수행한다.
Interceptor
는 개발자가 구현한 로직의 수행을 기준으로, 해당 요청에 대한 전처리와 후처리를 쉽게 구현할 수 있도록 preHandle, postHandle, afterCompletion
등의 세 가지 주요 메서드를 3제공한다.
컨트롤러가 요청 로직을 수행하기 이전 전처리 로직을 수행하는 메서드로, 예를 들어 로그인 여부 및 권한 체크 등을 수행할 수 있다. 반환 값을 boolean
을 반환하며, true
가 반환되는 경우에만 작업을 이어가며, false
의 경우에는 작업을 중단시키게 된다.
작업이 중단되는 경우, 기본적으로
body
가 없는200 ok
를 반환한다. 물론,response
를 통해 개발자가 설정할 수 있다.
컨트롤러가 요청 로직을 수행한 이후 후처리 로직을 수행하는 메서드로, postHandle
의 경우, 앞의 preHandle
이 true
를 return
하는 경우에만 수행이 이루어진다.
postHandle
에서 응답 객체 조작하기결론부터 말하면 RestController
를 사용하거나 Controller + ResponseBody
어노테이션을 사용할 때 명확하게 응답을 반환하는 경우 ( ex : dto
, String
, Entity
등 ) Interceptor
에서 객체에 대한 수정이 불가능하다. Controller
가 로직을 통해 반환한 응답을 수정하는 것 자체가 좋은 접근이 아니라고 판단하는 듯 하다. 이러한 설정들은 filter
역시 동일하게 적용된다.
일반적으로 postHandle
은 View
렌더링 시 추가적인 요소를 설정하기 위해 자주 사용되었다. 현재의 RestAPI
형태의 어플리케이션 서비스에서는 postHandle
로직은 사용이 제한적일 수 밖에 없다.
HttpServletResponse
는isCommited
메서드를 통해 수정이 가능한지, 아닌지를 판단할 수 있다. (null
이나void
와 같이, 응답 결과가 없는 것과 유사한 경우에는 수정이 가능하다.)
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler)
응답 결과를 완전히 보낸 이후 해당 요청을 종료할 때 로직을 수행하는 메서드로, 주로 리소스의 정리나, 로그 기록 등의 작업에 활용된다. afterCompletion
역시, 앞의 preHandle
이나, postHandle
모두 true
를 반환하는 경우에만 afterCompletion
의 호출이 이루어진다.
filter
의 경우, 전처리와 후처리를 모두 하나의 메서드에서 수행하며 doFiter
, Interceptor
의 경우, 전처리와 후처리를 각각 다른 메서드에서 진행한다. preHandle
, postHandle
interceptor
의 경우, Spring
컨테이너 영역 내에서 운영되며, 사용성, 설정, 기본 예외처리가 명확하며, 각 요청에 대한 처리 로직을 수행하기 위해 사용되는 경우가 많고, filter
의 경우에는 Spring
영역에 진입하기 이전 웹 컨테이너 영역으로 분류되어, 다수의 요청에 대한 공통 사항을 적용하는데 사용되는 경우가 많다.
참고
[Spring] 스프링 Interceptor의 동작 과정
[Spring] 스프링 Filter, DoFilter
[Spring Security] Filter 에 대한 오해와 진실 (doFilter의 정확한 작동방식에 대한 심층분석과 Filter의 흐름) (Spring 200 OK but No Content)
spring interceptor
Spring Filter에서 Response 수정하기