Post

(Spring)필터와 인터셉터

필터와 인터셉터

필터

필터란?

  • DispatcherServlet에 요청이 전달되기 전/후에 url 패턴에 맞는 모든 요청에 대 부가작업을 처리할 수 있는 기능을 제공하는 J2EE 표준 스팩 기능
  • DispatcherServlet이 Spring에 가장 앞단에 존재하는 Controller 이기 때문에 필터는 스프링의 밖에서 처리가 된다.
  • 스프링 컨테이너에서 관리되는 것이 아니라 톰캣과 같은 웹 컨테이너 안에서 관리된다.

필터의 메서드

1
2
3
4
5
6
7
8
9
10
11
import javax.servlet.Filter; //Filter라는 이름을 가진 인터페이스가 몇개 더 있다. 헤깔리지말고 이걸 import해야한다.

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {}

    @Override
    public void destroy() { ... }
  • import: javax.servlet.Filter
  • init: init 메서드는 필터 객체를 초기화하고 서비스에 추가하는 기능을 하는 메서드, 웹 컨테이너가 1회 init 메서드를 호출하여 필터 객체를 초기화 하면 이후의 요청들은 doFilter를 통해 처리된다.
  • doFilter: URL 패턴에 맞는 모든 HTTP 요청이 디스패처 서블릿으로 전달되기 전에 웹 컨테이너에 의해 실행되는 메서드, chain.doFilter() 전/후에 작성되어 있는 필요한 로직을 넣어줌으로 원하는 처리를 진행할 수 있다. - 파라미터 - FilterChain: FilterChain의 doFilter를 통해 다음 대상으로 요청을 전달
  • destroy: 필터 객체를 서비스에서 제거하고 사용하는 자원을 반환하기 위한 메서드, 웹서버에 의해 1번 호출되며 이후 doFilter에 의해 처리되지 않는다.

필터 Config

  • 예전에는 필터가 스프링 컨테이너에서 관리되는 것이 아니라 Bean으로 등록하는게 불가능 했다고 한다. 하지만 지금은 Bean으로 등록이 가능하며, 더욱 편리하게 사용할 수 있게 되었다.
1
2
3
4
5
6
public class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    public void onStartup(ServletContext servletContext) throws ServletException {
    	super.onStartup(servletContext);
    	servletContext.addFilter("FirstTestFilter", DelegatingFilterProxy.class);
    }
}
  • Spring에서 Filter를 등록하는 방법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {

    @Bean
    public FilterRegistrationBean<FirstTestFilter> firstFilterRegister() {
        FilterRegistrationBean<FirstTestFilter> registrationBean = new FilterRegistrationBean<>(new FirstTestFilter());
        registrationBean.setOrder(1);
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean<SecondTestFilter> secondFilterRegister() {
        FilterRegistrationBean<SecondTestFilter> registrationBean = new FilterRegistrationBean<>(new SecondTestFilter());
        registrationBean.setOrder(2);
        return registrationBean;
    }
}
  • Spring Boot에서 Filter를 등록하는 방법
  • 여러개의 필터를 사용할때는 setOrder() 를 사용해서 순서를 정해 줄 수 있다.

필터 이미지

filter_image

  • 필터의 작동 과정을 이미지로 표현

인터셉터

인터셉터란?

  • Spring이 제공하는 기술, 디스패처 서블릿이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공

인터셉터의 메서드

1
2
3
4
5
6
7
8
9
10
11
12
public class FirstTestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

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

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
}
  • imporit: org.springframework.web.servlet
  • preHandle: 컨트롤러가 호출되기 전에 실행되며, 컨트롤러 이전에 처리해야하는 전처리 작업이나 요청정보를 가공, 추가하는데 사용된다.
  • postHandle: 컨트롤러 호출된 후에 실행된다. 컨트롤러 이후에 처리해야 하는 후처리 작업이 있을때 사용
  • afterCompletion: 모든 뷰에서 최종 결과를 생성하는 일을 포함, 모든 작업이 완료된 후에 실행된다. 요청 처리 중에 사용한 리소스를 반환할 때 사용하기에 적합하다.

인터셉터 Config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(interceptor)
                .addPathPatterns("/")
                .addPathPatterns("/member/")
                .excludePathPatterns("/login").order(1);
        registry.addInterceptor(subInterceptor)
                .addPathPatterns("/")
                .excludePathPatterns("/login2").order(2);
	}
}
  • addPathPatterns: 인터셉터가 동작할 URL 패턴
  • excluedPathPatterns: 인터셉터가 동작하지 않을 URL 패턴
  • order: 다중 인터페이스 사용 시 순서를 정해준다.

인터셉터 이미지

interceptor_Image

  • 인터셉터가 위치하는 곳과 처리순서를 이미지로 간략하게 표현

필터(Filter)와 인터셉터(Interceptor) 차이 및 용도

대상필터(Filter)인터셉터(Intercepter)
관리되는 컨테이너웹 컨테이너스프링 컨테이너
Request/Response</br>객체 조각 가능 여부가능불가능
용도- 공통된 보안 및 인증/인가 관련 작업
- 모든 요청에 대한 로깅 또는 감사
- 이미지/데이터 압축 및 문자열 인코딩
- Spring과 분리되어야 하는 기능
- 세부적인 보안 및 인증/인가 공통작업
- API 호출에 대한 로깅 또는 감사
- Controller로 넘겨주는 데이터 가공

Request/Response 객체 조작 가능 여부

  • 필터는 Request/Response를 조작할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class FirstTestFilter implements Filter {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("FirstFilter 생성: {}", this.getClass());
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("FirstFilter 실행: {}", this.getClass());
        chain.doFilter(request, response);
        ((HttpServletResponse) response).sendError(HttpServletResponse.SC_BAD_REQUEST); // response를 조작하여, 어떤 request가 들어오던 400을 반환
        log.info("FirstFilter 종료: {}", this.getClass());
    }

    @Override
    public void destroy() {
        log.info("FirstFilter 삭제: {}", this.getClass());
    }
}
  • 위에 보이는 코드처럼 response를 조작하여, 어떤 request가 들어오던 400을 반환시킬 수 있다.
  • 이렇게 response와 request를 조작할 수 있는것이 인터셉터와 가장 큰 차이점이다.

  • 인터셉터는 필터와 처리 과정이 다르기 때문에 Request/Response객체를 조작하여 넘겨줄수 없다.
    • 인터셉터는 디스패처 서블릿이 여러 인터셉터의 목록을 가지고, 반복문을 통해 순차적으로 실행시킨다. 그 후 true를 반환하면 다음 인터셉터가 실행되거나 컨트롤러로 요청이 전달된다.(false가 반환되면 요청이 중단된다.)
1
2
3
4
5
6
7
8
9
10
public class FirstTestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (...) {
            ...
            return true;
        }
        return false;
    }
}
  • 위에 보이는것처럼 true와 false 두가지만 반환이 가능하고, 그 결과로 다음 인터셉가 실행되거나, 컨트롤러로 요청이 전달되기 때문에 request나 response의 조작이 불가능하다.

필터의 용도 및 예시

1
2
3
4
- 공통된 보안 및 인증/인가 관련 작업
- 모든 요청에 대한 로깅 또는 감사
- 이미지/데이터 압축 및 문자열 인코딩
- Spring과 분리되어야 하는 기능
  • 필터에서는 기본적으로 스프링과 무관하게 전역적으로 처리해야 하는 작업들을 처리할 수 있다.
  • 이미지나 데이터의 압축, 문자열 인코딩과 같이 웹 애플리케이션에 전박적으로 사용되는 기능을 구현하기 좋다.

인터셉터의 용도 및 예시

1
2
3
- 세부적인 보인 및 인증/인가 공통작업
- API 호출에 대한 로깅 또는 감사
- Controller로 넘겨주는 데이터의 가공
  • 클라이언트의 요청과 관련되어 전역적으로 처리해야 하는 작업들을 처리할 수 있다.
  • 특정 그룹의 사용자마다 사용할 수 있는 기능을 나눌때 사용하면 좋다.
  • JWT토큰 정보를 파싱해서 컨트롤러에 사용자의 정보를 제공하는 등 컨트롤러로 넘겨주기 위한 정보를 가공하기 용이하다.

REFRENCE

[Spring] 필터(Filter) vs 인터셉터(Interceptor) 차이 및 용도 - (1)

spring - 스프링에서의 필터 개념 및 예제

This post is licensed under CC BY 4.0 by the author.