카테고리 없음

[Spring]Filter와 Interceptor

찬란한 2023. 5. 25. 06:32

공통관심사

어플리케이션 전반에서 여러 로직에 공통적으로 관심이 있는 것들을 공통관심사라고 한다.

 

어느 웹서비스를 이용하기 위해서 로그인(회원 인증)이 되었는지 확인하는 것을 여러 기능에서 필요로 하는 것이 있다.

상품의 구매, 변경, 취소 이 3가지의 기능만 예로 들어도 3가지 기능 모두 인증이 되었는지 확인한다.

공통관심사에 해당하는 부분이 서비스 로직 시행 전 위치함으로써 필요한 기능을 수행하게 되는 것이다.

 

 Filter와 Interceptor의 기반

이 때 사용할 수 있는 것이 Filter(servlet Filter)와 Interceptor이다.

 

Filter는 J2EE 표준스펙에서 제공하는 기술로써 가장 앞단에 존재하는 프론트 컨트롤러인 디스패처 서블릿의 전후에서 필요한 기능을 수행하게 한다. (J2EE는 Java 2 EnterPrise Edition)

 

InterCeptor는 스프링이 제공하는 Dispatcher Servlet이 Controller를 호출하기 전에 요청을 가로채서(InterCept) 필요한 기능을 수행한다.

 

Servlet Filter와 InterCeptor는 웹과 관련된 공통관심사를 처리하기에 용이하다.

웹 관련 공통관심사에는 보통 URL 혹은 Header의 정보들이 필요한 경우가 많은데 이를 처리하기 위한 HttpServletRequest를 Filter와 Intercoptor가 제공하기 때문이다.

 

아래 이미지에서는 Servlet Filter와 Interceptor가 어느 위치에서 공통관심사를 처리하는지를 잘 보여준다.

 

 

 

 

Filter의 메소드

사용자 Filter를 구현하기 위해서 javax.sevlet의 Filter 인터페이스를 구현해야한다. 이 인터페이스의 메소드는 다음 3가지가 있다.

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

보통 필터를 구현할 때 핵심이 되는 메소드이다. 필요한 혹은 원하는 기능을 구현한 후 FilterChain 파라미터를 통해 다음 대상으로 요청을 넘겨준다.

 

destroy

필터를 제거하고 자원을 반환하기 위한 메소드이다.

 

 

Filter의 적용

@configuration 애노테이션이 붙여진 클래스의 빈으로 등록한다.

@Bean
  public FilterRegistrationBean loginCheckFilter() {
      FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
      filterRegistrationBean.setFilter(new LoginCheckFilter());
      filterRegistrationBean.setOrder(2);
      filterRegistrationBean.addUrlPatterns("/*");
      return filterRegistrationBean;
}

 

 

 

Interceptor의 메소드

사용자 Interceptor를 구현하기 위해서 스프링의 HandlerInterceptor를 구현해야한다. 구현 메소드는 3가지가 있다.

default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
	return true;
}

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 {

}

메소드 호출 시점

preHandle

Controller 호출 전 호출(더 정확히는 핸들러 어댑터 호출 전에 호출)

preHandle 의 리턴 값이 true이면 다음으로 진행하고, false이면 더 이상 진행하지 않는다.

false일 경우, 나머지 인터셉터와 핸들러 어댑터도 호출되지 않는다.

 

postHandle

Controller 호출 후에 호출

 

afterCompletion

뷰가 렌더링 된 이후에 호출

 

 

 

InterCeptor의 적용

interceptor도 filter와 마찬가지로 WebConfig로 등록을 해두어야한다.

WebMvcConfigurer 클래스를 상속받아 addInterceptors 메소드를 오버라이딩하여 적용시킨다.

@Configuration
  public class WebConfig implements WebMvcConfigurer {
      @Override
      public void addInterceptors(InterceptorRegistry registry) {
          registry.addInterceptor(new LogInterceptor())
                  .order(1)
                  .addPathPatterns("/**")
                  .excludePathPatterns("/css/**", "/*.ico", "/error");
     }
//...
}