필터는 서블릿이 제공하는 기술, 인터셉터는 스프링 MVC가 제공하는 기술이다.
둘다 웹과 관련된 공통 관심 사항을 처리하지만, 적용되는 순서와 범위 등이 다르다.
서블릿 필터

필터를 적용하면, 필터가 호출 된 다음에 DispatcherServlet이 호출된다.
모든 고객의 요청 로그를 남길때, 필터를 사용할수 있다.
참고로 필터는 특정 URL 패턴에 적용할 수 있다. ' /* ' 이라고 하면 모든 요청에 필터가 적용된다.

필터에서 적절하지 않은 요청이라고 판단하면
DispatcherServlet 을 호출하지 않고, 거기에서 끝을 낼 수도 있다.
그래서 로그인 여부를 체크하기에 딱 좋다.

필터는 체인으로 구성되는데, 중간에 필터를 자유롭게 추가할 수 있다.
로그를 남기는 필터를 먼저 적용하고, 그 다음에 로그인 여부를 체크하는 필터를 만들 수 있다.
public interface Filter { ~ }
필터 인터페이스를 구현하고 등록하면
, 서블릿 컨테이너가 필터를 싱글톤 객체로 생성하고 관리한다.
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// ServletRequest는 HTTP 요청이 아닌 경우까지 고려해서 만든 인터페이스이다. HTTP를 사용하려면 다운케스팅 하면 된다.
chain.doFilter(request, response);
// 다음 필터가 있으면 필터를 호출하고, 필터가 없으면 서블릿을 호출한다.
// 만약 이로직을 호출하지 않으면 다음 단계로 진행되지 않는다.
}
@Override
public void destroy() { }
}
init() : 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다.
doFilter() : 고객의 요청이 올 때 마다 해당 메서드가 호출된다. 여기에 필터의 로직을 구현하면 된다.
destroy() : 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.
스프링 인터셉터
스프링 인터셉터는 컨트롤러 호출 직전에 호출 된다. ( DispatcherServlet과 @Controller 사이에서 )

스프링 인터셉터에도 URL 패턴을 적용할 수 있는데, 서블릿 URL 패턴과는 다르고, 매우 정밀하게 설정할 수 있다.

인터셉터에서 적절하지 않은 요청이라고 판단하면 거기에서 끝을 낼 수도 있다.( 컨트롤러 호출을 안해버림 )

스프링 인터셉터는 체인으로 구성되는데, 중간에 인터셉터를 자유롭게 추가할 수 있다.
로그를 남기는 인터셉터를 먼저 적용하고, 그 다음에 로그인 여부를 체크하는 인터셉터를 만들 수 있다
지금까지 내용을 보면 서블릿 필터와 호출 되는 순서만 다르고, 제공하는 기능은 비슷해 보인다.
스프링 인터셉터는 서블릿 필터보다 편리하고, 더 정교하고 다양한 기능을 지원한다.
스프링의 인터셉터를 사용하려면 HandlerInterceptor 인터페이스를 구현하면 된다.
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
, Object handler, @Nullable Exception ex) throws Exception {}
}
서블릿 필터의 경우 단순하게 doFilter() 하나만 제공된다.
인터셉터는 컨트롤러 호출 전( preHandle ), 호 출 후( postHandle ), 요청 완료 이후( afterCompletion )와 같이 단계적으로 잘 세분화 되어 있다.
서블릿 필터의 경우 단순히 request , response 만 제공했지만
인터셉터는 어떤 컨트롤러( handler )가 호출되는지 호출정보, 그리고 어떤 modelAndView가 반환되는지 응답 정보도 받을 수 있다.

정상 흐름
preHandle : 컨트롤러 호출 전에 호출된다. ( 더 정확히는 핸들러 어댑터 호출 전에 호출된다. )
preHandle의 응답값이 true이면 다음으로 진행하고, false이면 더는 진행하지 않는다.
( false인경우 나머지 인터셉터는 물론이고, 핸들러 어댑터도 호출되지 않는다. 그림에서 1번에서 끝나버림 )
postHandle : 컨트롤러 호출 후에 호출된다. ( 더 정확히는 핸들러 어댑터 호출 후에 호출된다. )
afterCompletion : 뷰가 렌더링 된 이후에 호출된다( 응답 나오고 난 다음에 호출 )
컨트롤러에서 예외 발생한 경우

preHandle : 컨트롤러 호출 전에 호출된다.
postHandle : 컨트롤러에서 예외가 발생하면 postHandle은 호출되지 않는다.
afterCompletion : 항상 호출됨. 이 경우 예외( ex )를 파라미터로 받아서 어떤 예외가 발생했는지 로그로 출력가능
afterCompletion은 예외가 발생해도 호출된다.
예외가 발생하면postHandle() 는 호출되지 않으므로, 예외와 무관하게 공통 처리를 하려면 afterCompletion() 을 사용해야 한다.
예외가 발생하면 afterCompletion()에 예외 정보( ex )를 포함해서 호출된다.
'김영한님 인강듣고 > 스프링 MVC' 카테고리의 다른 글
| RequestMappingHandlerAdapter, HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler, HttpMessageConverter (1) | 2024.06.05 |
|---|---|
| 세션, 쿠키 (0) | 2024.05.27 |
| 스프링 MVC 전체 구조 (0) | 2024.05.17 |
| 서블릿 (0) | 2024.05.17 |
| 웹 시스템 구성( HTTP, WEB, WAS, DB ) (0) | 2024.04.20 |