[Springboot] OncePerRequestFilter vs GenericFilterBean

유아 Yooa·2023년 6월 5일
2

Spring

목록 보기
8/18
post-thumbnail
post-custom-banner

Overview

SpringSecurity를 이용해서 서버 인증 방식을 구현하던 도중 Filter에 대해서 궁금증이 생겼다. 여러 레퍼런스를 참고하다 보면 필터링 로직 구현이 조금씩 다른 것을 확인할 수 있다.
OncePerRequestFilter를 사용하거나 GenericFilterBean을 사용하는 것이었다. 두 방식의 차이점을 알아보고 무엇을 사용하면 좋을지를 고민해보자.


GenericFilterBean

  • Spring MVC에서 request의 lirecycle을 나타내는 그림이다.
  • Filter
    • javax.servlet-apitomcat-embed-core를 사용하면 제공되는 Servlet Filter Interface이다.
    • DispatcherServlet가 요청을 받기 전 앞단에 Filter에서 먼저 request를 받는다.
package jakarta.servlet;

import java.io.IOException;

public interface Filter {
    default void init(FilterConfig filterConfig) throws ServletException {
    }

    void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException;

    default void destroy() {
    }
}
  • GenericFilterBean
    • Filter를 확장하여 Spring에서 제공하는 filter
    • 기존 Filter에서 얻어올 수 없는 정보였던 Spring의 설정 정보를 가져올 수 있게 확장된 추상 클래스
  public abstract class GenericFilterBean implements Filter, BeanNameAware, EnvironmentAware,
  EnvironmentCapable, ServletContextAware, InitializingBean, DisposableBean {

 /** Logger available to subclasses. */
 protected final Log logger = LogFactory.getLog(getClass());

 @Nullable
 private String beanName;

 @Nullable
 private Environment environment;

 @Nullable
 private ServletContext servletContext;

 @Nullable
 private FilterConfig filterConfig;

 private final Set<String> requiredProperties = new HashSet<>(4);
  ...
  public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }
  • 해당 Filter들은 서블릿마다 호출이 된다.
    • 서블릿은 사용자의 요청을 받으면 서블릿을 생성해 메모리에 저장해두고, 같은 클라이언트의 요청을 받으면 생성해둔 서블릿 객체를 재활용하여 요청을 처리한다.

  • 문제는 의도치 않은 경우에 Filter가 두번씩 적용되는 경우가 있을 수 있다.

    • Spring Security에서 인증과 인가 또한 Filter로 구현되어 있다.
    • 예를 들어, 그림과 같이 API 0에서 요청을 처리하고 API 1로 redirect 시킨다고 가정하자.
    • 클라이언트는 한번의 요청을 한 것 뿐이지만 흐름상 요청을 두번한 것과 같이 된다. 쓸데없는 자원만 낭비ㅏ는 셈이다.
  • 이러한 문제를 해결하기 위해 OncePerRequestFilter가 등장했다.


    OncePerRequestFilter

  • 모든 서블릿에서 일관된 요청을 처리하기 위해 만들어진 필터이다.

  • 이 추상 클래스를 구현한 필터는 사용자의 한번에 요청 당 딱 한번만 실행되는 필터를 만들 수 있다.

  • OncePerRequestFilter를 상속하여 구현한 경우 doFilter 대신 doFilterInternal 메서드를 구현하면 된다.

@Slf4j
@Component
public class FirstFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
		 // TODO 전처리
        filterChain.doFilter(request , response);
        // TODO 후처리
    }
}

참고
OncePerRequestFilter와 Filter의 차이
[Spring] OncePerRequestFilter란?
2) Springboot OncePerRequestFilter 와 GenericFilterBean의 차이
[Spring Boot] 나의 필터가 두 번 적용된 이유

profile
기록이 주는 즐거움
post-custom-banner

0개의 댓글