[Spring] 스프링 필터(Filter) vs 인터셉터(Interceptor)
NextStep 강의를 들으면서 필터와 인터셉터를 접할 일이 생겼다. 필터와 인터셉터는 기본적으로 비슷한 역할을 한다는 점을 알고있었다. 하지만 주어진 코드를 접해봤는데, 역할별로 필터와 인터셉터를 구별하여 사용한 것이 보였다. 어떤 기준을 가지고 구별을 했는지 알아보기 위해, 둘의 특성과 차이점을 정리하고자 한다.
1. 필터(Filter)란?
J2EE 표준 스펙 기능
- 스프링 컨테이너가 아닌 톰캣과 같은 웹 컨테이너로 관리
서블릿에 요청이 전달되기 전/후에 url 패턴에 맞는 모든 요청에 대해 부가작업을 처리할 수 있게 하는 기능(ex) 로그인 유무 확인)
request, response 객체를 다른 객체로 바꿀 수 있다.
chain.doFilter()
로 사용
Filter 인터페이스를 구현한 Filter를 FilterRegistrationBean에 등록하여 사용한다.
@Configuration public class WebConfig { @Bean public FilterRegistrationBean logFilter() { FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new MyFilter()); filterRegistrationBean.setOrder(1); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } }
1.1 동작과정
- 동작 과정
HTTP 요청 → WAS → <<필터>> → (디스패처)서블릿 → 컨트롤러
순으로 동작한다.(스프링에선 서블릿이 디스패처 서블릿이 된다.)- 만약 필터에서 걸러지게 되면 서블릿을 호출하지 않게 된다.
- 필터 체인
HTTP 요청 → WAS → <<필터1>> → <<필터2>> → ... → 서블릿 → 컨트롤러
- 필터를 연속에서 추가 시킬 수 있다.
- 등록된 순서에 따라서 동작이 달라진다.
1.2 필터 인터페이스
public interface Filter {
public default void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
public default void destroy() {}
}
- 필터 인터페이스를 구현하고 등록하면 서블릿 컨테이너가 필터를 싱글톤 객체로 등록하고, 관리한다.
init()
: 초기화 메서드로 서블릿 컨테이너가 생성될 때 호출doFilter()
: 요청이 올 때 마다 호출되는 메서드, 필터의 로직을 담당destory()
: 서블릿 컨테이너가 종료될 때 호출
2. 인터셉터(Interceptor)란?
Spring MVC가 제공하는 기술
- Spring 컨테이너에서 관리
서블릿이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공
URL 패턴을 정밀하게 사용할 수 있다.
HandlerInterceptor 인터페이스를 구현한 핸들러를 WebMvcConfigurer를 구현한 설정파일에 등록하여 사용한다.
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogInterceptor()) .order(1) .addPathPatterns("/**") .excludePathPatterns("/css/**", "/*.ico", "/error"); } }
2.1 동작과정
- 동작과정
HTTP 요청 → WAS → 필터 → (디스패처)서블릿 → <<인터셉터>> → 컨트롤러
순으로 동작- 인터셉터에서 걸러지게 되면 컨트롤러가 호출되지 않는다.
- 인터셉터 체인
HTTP 요청 → WAS → 필터 → (디스패처)서블릿 → <<인터셉터1>> → <<인터셉터2>> → ... → 컨트롤러
2.2 인터페이스
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler) throws Exception {}
default void postHandle(HttpServletRequest request, HttpServletResponse
response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}
default void afterCompletion(HttpServletRequest request, HttpServletResponse
response, Exception {} Object handler, @Nullable Exception ex) throws Exception {}
}
- 서블릿 필터와 달리 다양한 default 메서드 제공
preHandle()
: 컨트롤러 호출 전 실행- 더 정확히 말하자면 핸들러 어댑터 호출 전에 실행
- 반환 타입이
boolean
인데 여기서 false가 반환되면 더 이상 작업을 하지 않는다(다음 인터셉터 및 컨트롤러 실행 X). - 파라미터인 handler는
@RequestMapping
을 사용하면HandlerMethod
로 반환되며, 정적 리소스일 경우에는ResourceHttpRequestHandler
로 반환된다.HandlerMethod
: 호출할 컨트롤러 메서드의 모든 정보가 들어있음ResourceHttpRequestHandler
: 정적리소스를 처리하는 핸들러- 사용할 때 instanceOf로 확인하고 사용하면 된다.
postHandle()
: 컨트롤러 호출 후 실행- 더 정확히 말하자면 핸들러 어댑터 후출 후에 실행
afterCompletion()
: 요청 완료 이후 실행- 더 정확히 말하자면 뷰가 렌더링 된 이후에 실행
- 예외가 발생해도 실행이 된다.
- Exception을 파라미터로 받기 때문에
- 어떤 컨트롤러(handler)가 호출되는지 확인할 수 있음
- 어떤 ModelAndView가 반환되는지 확인도 가능
3. 필터 vs 인터셉터
대상 | 필터(Filter) | 인터셉터(Interceptor) |
---|---|---|
관리되는 컨테이너 | 웹 컨테이너 | 스프링 컨테이너 |
Request/Response 객체 조작 가능 여부 | O | X |
용도 | - 공통된 보안 및 인증/인가 관련 작업 - 모든 요청에 대한 로깅 또는 감사 - 이미지/데이터 압축 및 문자열 인코딩 - Spring과 분리되어야 하는 기능 |
- 세부적인 보안 및 인증/인가 관련 작업 - API 호출에 대한 로깅 또는 감사 - Controller로 넘겨주는 데이터의 가공 |
※ 참조
'FRAMEWORK > [SPRING]' 카테고리의 다른 글
[Spring] RestAssured로 API 테스트 진행하기 (1) | 2023.04.13 |
---|---|
[Spring] Spring ArgumentResolver란? (0) | 2022.08.10 |
[Spring] Jar vs War (0) | 2022.06.27 |
[Spring] Spring 검증 기능2 (Bean Validation) (0) | 2022.06.09 |
[Spring] Spring 검증 기능1 (BindingResult, Validator) (0) | 2022.06.07 |