[Spring] Filter vs Interceptor

땡글이·2023년 6월 6일
1

Spring Framework

목록 보기
6/8

목차

  • Filter
  • Interceptor
  • Filter와 Interceptor의 차이점
  • 결론

스프링부트 프로젝트로 인증/인가를 구현하게 되면 Filter 와 Interceptor를 만나게 된다. 이들에 대해 어떤 차이점이 있는지 알아보자.

Filter

Filter는 사실 SpringSecurity 프레임워크를 사용해본 사람들에게는 익숙할 것이다. SpringSecurity는 내부적으로 Filter로 구현되어 있고 커스터마이징을 하게되면 Filter를 직접 만들어서 SpringSecurity 필터 체인에 삽입하는 방식으로 구현하게 된다.

우선, Filter는 스프링과 연관된 기술이 아닌, 서버 기술에 속한다. 즉 스프링에 종속된 기술이 아니라는 뜻이다. 그래서 들어오는 요청에 대해 Filter를 사용하여 Request가 Servlet에 도달하지 못하도록 조작하고 차단할 수도 있습니다. 반대로 Response가 클라이언트에 도달하지 못하도록 차단할 수도 있습니다.

Filter를 만들어서 필터 체인에 등록하려면, 다음과 같이 구현해볼 수 있다. 우선 javax.servlet.Filter 인터페이스를 구현하고 doFilter 메서드를 오버라이딩해줌으로써 필터를 만들 수 있다.

@Component
public class LogFilter implements Filter {

    private Logger logger = LoggerFactory.getLogger(LogFilter.class);

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException {
        logger.info("Hello from: " + request.getLocalAddr());
        chain.doFilter(request, response);
    }

}

만약 SpringSecurity 프레임워크를 사용하면 Filter를 만들어서 등록해주면 내 Filter가 동작하게 된다. Filter의 삽입 위치는 SpringSecurity 의 필터체인을 참고하여 정해주자. Filter Chain은 아래 그림처럼 필터 여러 개가 묶여서 동작하는 것을 의미한다.

그렇지만 SpringSecurity 프레임워크는 사실 DelegatingFilterProxy 의 기술을 도입해서 Spring 프로젝트 내에서 FilterChain이 동작하도록 구현되어 있다.

DelegatingFilterProxy 란?

DelegatingFilterProxy는 Spring Application Context에 액세스할 수 있는 Filter 클래스에 제어를 전달할 수 있는 서블릿 필터이다.

앞서 말했듯이, Spring Security는 이 기술로 FilterChain 을 만들어냈다. SpringSecurity 공식문서에서도 확인 가능하다. 아래 그림은 공식문서에서 SpringSecurity FilterChain을 표현한 그림이다. 그림의 FilterChainProxy는 특수한 Filter로서, SpringSecurity 프레임워크 내에서의 FilterChain을 빈으로 등록한 프록시를 의미한다.

DelegatingFilterProxy을 한줄로 설명하자면, Filter 인터페이스를 구현하는 Spring Bean에 요청을 위임하는 Servlet Filter에 대한 프록시이다.

DelegatingFilterProxy 예시

public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    // some other methods here
 
    @Override
    protected javax.servlet.Filter[] getServletFilters() {
        DelegatingFilterProxy delegateFilterProxy = new DelegatingFilterProxy();
        delegateFilterProxy.setTargetBeanName("loggingFilter");
        
        return new Filter[]{delegateFilterProxy};
    }
}

위의 코드처럼 DelegatingFilterProxy를 등록해주면, 어플리케이션이 시작될 때, "loggingFilter"라는 이름의 빈을 가진 Filter를 찾게 되고 Spring Servlet에 전달되는 요청을 미리 받아 데이터를 가공할 수 있다.


Interceptor

Interceptor 또한 Filter와 마찬가지로, 서블릿에 전달되는 요청을 가로채서 부가적인 작업들(로깅, 인증/인가 등)을 해줄 수 있다.

아래와 같이 Interceptor를 커스터마이징하여 만들 수 있고 등록할 수 있다.

public class LogInterceptor implements HandlerInterceptor {

    private Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
      throws Exception {
        logger.info("preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 
      throws Exception {
        logger.info("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 
      throws Exception {
        logger.info("afterCompletion");
    }

}
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(final InterceptorRegistry registry) {
        registry.addInterceptor(new LoggerInterceptor());
        registry.addInterceptor(new UserInterceptor());
        registry.addInterceptor(new SessionTimerInterceptor());
    }
}

Filter 와 Interceptor의 차이

FilterInterceptor의 가장 큰 차이점은 그림에서 알 수 있듯이, DispatcherServlet 보다 앞에서 요청을 처리하는지 뒤에서 처리하는지에 있다.

결론! 두두등장

Filter는 DispatcherServlet에 도달하기 전에 요청을 가로채서 다음과 같은 대략적인 작업에 이상적이라고 볼 수 있다.

  • Authentication (인증)
  • 로깅 및 auditing
  • 이미지 및 데이터 압축
  • Spring MVC에서 분리하려는 모든 기능

반면에 Intercepor는 DispatcherServlet과 컨트롤러 간의 요청을 가로챈다. 이는 Handler 및 ModelAndView 개체에 대한 액세스를 제공하는 Spring MVC 프레임워크 내에서 수행한다. 이렇게 하면 중복이 줄어들고 다음과 같은 보다 세분화된 기능이 가능하다.

  • Application Logging과 같은 Cross-cutting 처리
  • Detailed Authorization(인가)
  • Spring Context 또는 Model(엔티티 또는 비즈니스 로직) 조작

Reference

https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-filters-review
https://docs.spring.io/spring-framework/reference/6.1-SNAPSHOT/web/webmvc/mvc-config/interceptors.html#page-title
https://www.baeldung.com/spring-mvc-handlerinterceptor-vs-filter
https://www.baeldung.com/java-servlets-containers-intro

profile
꾸벅 🙇‍♂️ 매일매일 한발씩 나아가자잇!

0개의 댓글