필터와 인터셉터

뾰족머리삼돌이·2023년 12월 30일
0

Spring

목록 보기
6/14

필터와 인터셉터 모두 특정시점의 동작 전후에 처리할 작업을 수행하는데 사용된다
Spring AOP와 함께 세 가지가 자주 비교된다

외부에서 요청이 들어왔을 때, 해당 요청은 Filter - Interceptor - AOP의 순서대로 거치게되며 응답시에는 반대의 순서를 겪게된다

Spring의 기준으로 필터의 동작시점은 DispatcherServlet의 접근 전후에 동작한다
따라서 필터는 Spring MVC에 종속적이지 않다는 특징이 있다

이러한 점 때문에 Spring Security에서는 Filter를 기반으로 동작한다

반면 Interceptor의 경우 DispatcherServlet에서 Controller로 접근 전후에 동작한다
따라서 Interceptor는 Spring의 기능( Bean 주입 등 ) 을 사용할 수 있다

필터의 경우, Spring에 종속적이지 않기때문에 사용자 인증이나 전역적인 로깅, 인코딩 등 Spring에서 분리하고싶은 작업을 처리하는데 주로 사용된다

인터셉터의 경우, 인가내역을 확인하거나 서비스 접근 시에 공통적으로 처리할 작업을 수행하는데 사용된다

Interceptor와 AOP의 동작시점은 유사하나, AOP에서는 주로 비즈니스 로직과 관련된 공통관심사를 처리한다

Servlet Filter

public class SampleFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 필터 동작 이전에 처리할 작업
        
        chain.doFilter(request, response);
        
        // 필터 동작 이후에 처리할 작업
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

init()의 경우 필터의 생성시점에 한번 동작하고
doFilter()의 경우 매 요청마다 동작하며,
destory()는 필터가 소멸할 때 동작한다

추가적으로, 원래 Filter의 경우 Spring Bean으로 등록이 불가능하다
하지만, DelegatingFilterProxy가 등장하고 Spring Boot에 이르면서 이제 Bean주입과 등록이 모두 가능하다

DelegatingFilterProxy의 경우 Filter 인스턴스를 가지고 WebApplicationContext를 이용하여 해당 인스턴스를 초기화하는 방식의 proxy이다

SpringBoot는 내장 WAS를 관리하기 때문에 Filter의 Bean주입과 등록이 자유롭다

Spring의 HandlerInterceptor

HandlerMapping에 설정하여 mapping되는 Handler마다 적용되게 할 수 있다

public class SampleInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

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

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

메서드 동작시점

  • preHandle ⇒ 요청 처리 이전
  • postHandle ⇒ view 랜더링 직전
  • afterCompletion ⇒ view 랜더링 모두 끝난 후

[ Interceptor가 여러개일때 실행 순서 ]

preHandle 1
preHandle 2

요청 처리
postHandle 2
postHandle 1

뷰 랜더링
afterCompletion 2
afterCompletion 1


package javax.servlet;

import java.io.IOException;

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

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    default void destroy() {
    }
}

HandlerInterceptor에서는 Servlet Filter보다 좀 더 구체적인 정보가 제공된다

Handler의 정보, ModelAndView 정보가 필요한 처리에서는 HandlerInterceptor를 사용하고 이러한 정보가 필요하지 않을때는 Filter를 사용하는게 타당하다고 볼 수 있다


Interceptor 등록

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SampleInterceptor())
                .addPathPatterns("/hello");

        registry.addInterceptor(new Sample2Interceptor())
                .addPathPatterns("/hello");
    }
}

Configuration에서 addInterceptors를 사용하여 커스텀한 Interceptor를 추가할 수 있다

주의사항
Configuration에 @EnableWebMvc를 사용하면 Spring Boot의 자동설정이 꺼진다

0개의 댓글

관련 채용 정보