24.02.23 Spring Filter 와 Interceptor
1. 필터(Filter)
- 요청과 응답을 거른뒤 정제하는 역할을 함
- Dispatcher Servlet 에 요청이 전달되기 전 / 후에 URL 패턴에 맞는 모든 요청에 대해 부가 작업을 처리할 수 있는
기능을 제공함
- 스프링 컨테이너가 아닌 톰캣과 같은 웹 컨테이너에 의해 관리되는 것이고, 스프링 범위 밖에서 처리되는 것
(스프링 빈으로 등록 가능)
1) 필터의 메서드 종류
- 필터를 사용하기 위해서는 javax.servlet 의 Filter 인터페이스를 구현해야하며, 아래와 같은 메서드를 가짐
public interface Filter {
public default void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOExceptio, ServletException;
public default void destroy() {}
(1) init( )
- 필터 객체를 초기화하고 서비스에 추가하기 위한 메서드
- 웹 컨테이너가 1회 init( ) 을 호출하여 필터 객체를 초기화하면 이후 요청들은 doFilter( ) 를 통해 처리 됨
(2) doFilter( )
- url-pattern 에 맞는 모든 HTTP 요청이 디스패처 서블릿으로 전달되기 전에 웹 컨테이너에 의해 실행되는 메서드
- doFilter 의 파라미터로 FilterChain 이 있는데 FilterChain 의 doFilter 를 통해 다음 대상으로 요청을
전달할 수 있게 됨
- chain.doFilter( ) 로 전, 후에 우리가 필요한 처리 과정을 넣어줌으로써 원하는 처리를 진행할 수 있다
(3) destroy( )
- 필터 객체를 제거하고 사용하는 자원을 반환하기 위한 메서드
- 웹 컨테이너가 1회 destroy( ) 를 호출하여 필터 객체를 종료하면 이후에는 doFilter 에 의해 처리되지 않음
2. 인터셉터(Interceptor)
- 요청에 대한 작업 전 / 후로 가로챈다고 보면 됨
- Dispatcher Servlet 이 Controller 를 호출하기 전 / 후에 인터셉터가 끼어들어 요청과 응답을 참조하거나
가공할 수 있는 기능을 제공
- 웹 컨테이너에서 동작하는 필터와 달리 인터셉터는 스프링 컨텍스트에서 동작
- 디스패처 서블릿이 핸들러 매핑을 통해 컨트롤러를 찾도록 요청하는데 그 결과로
실행 체인(HandlerExecutionChain)을 돌려줌
- 여기서 1개 이상의 인터셉터가 등록되어 있다면 순차적으로 인터셉터들을 거쳐 컨트롤러가 실행되도록하고,
인터셉터가 없다면 바로 컨트롤러를 실행
- 실제로 Interceptor 가 직접 Controller 로 요청을 위임하는 것은 아님
2) 인테섭터의 메서드 종류
- 인터셉터를 추가히기 위해서 org.springframework.web.servlet 의 HandlerInterceptor 인터페이서를 구현해야하며
아래와 같은 메서드를 가짐
public interface HandlerInterceptor {
default bollean preHandel(HttpServletRequest request, HttpServletResponse respose, Object Handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse respose, Object Handler,
@Nullable ModelAndView modelAndView) throws Exception {
default void afterCompletion((HttpServletRequest request, HttpServletResponse respose, Object Handler,
@Nullable Exception ex) throws Exception {
}
(1) preHandle( )
- Controller 가 호출되기 전에 실행됨
- 컨트롤러 이전에 처리해야 하는 전처리 작업이나 요청 정보를 가공하거나 추가하는 경우에 사용
(2) postHandle( )
- Controller 가 호출된 후에 실행 (View 랜더링 전)
- 컨트롤러 이후에 처리해야하는 후처리 작업이 있을 때 사용
- 컨트롤러가 반환하는 ModelAndView 타입의 정보가 제공되는데 최근에는 JSON 형태로 데이터를
제공하는 RestAPI 기반의 컨트롤러 (@RestController) 를 만들면서 자주 사용되지 않음
(3) afterCompletion( )
- 모든 뷰에서 최종 결과를 생성하는 일을 포함해 모든 작업이 완료된 후에 실행 (View 렌더링 후)
- 요청 처리 중에 사용한 리소스를 반환할 때 사용할 수 있다
2) 인터셉터와 AOP 비교
- 인터셉터 대신에 컨트롤러들에 적용할 부가기능을 어디바이스로 만들에 AOP 를 적용할 수도 있다
- 아래와 같은 이유들로 컨트롤러의 호출 과정에 적용되는 부가기능들은 인터셉터를 사용하는 편이 좋다
(1) 컨트롤러는 타입과 실행 메소드가 모두 제각각이라 포인트컷(적용하 ㄹ메소드 선별)의 작성이 어려움
(2) 컨트롤러는 파라미터나 리턴 값이 일정하지 않다
- 즉 타입이 일정하지 않고 호출 패턴도 정해져 있지 않기 때문에 컨트롤러에 AOP 를 적용하려면 번거로운
부가 작업들이 생김
3. 필터와 인터셉터의 차이 및 비교
1) Request, Response 객체 조작 가능 여부
(1) 필터
- Request 와 Response 를 조작할 수 있다
- 필터가 다음 필터를 호출하기 위해서는 필터체이닝(다음 필터 호출) 을 해줘야함 이때
request, response 객체를 넘겨주므로 우리가 원하는 객체를 넣어줄 수 있다
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throw IOException, ServletException{
// 다른 request 와 response 를 넣어줄 수 있음
chain.doFilter(request, response);
}
}
(2) 인터셉터
- Request 와 Response 를 조작할 수없다
- 디스패처 서블릿이 여러 인터셉터 목록을 가지고 있고 순차적으로 실행시킴
- true 를 반환하면 다음 인터셉터가 실행되거나 컨트롤러로 요청이 전달되며 false 가 반환되면 요청이
중단되므로 다른 request, response 객체를 넘겨줄 수 없다
public class MyInterceptor implements HandlerInterceptor {
public boolean preHanle(ServletRequest request, ServletResponse response, Object handler)
throw Exception{
// Request, Response 를 교체할 수 없고 boolean 값만 반환 가능
return true;
}
}
2) 필터와 인터셉터의 사용사례
(1) 필터
- 기본적으로 스프링과 무관하게 전역적으로 처리해야 하는 작업들을 처리 할 수 있다
- 인터셉터보다 앞단에서 동작하기 때문에 보안검사(XSS 방어 등)를 하여 올바른 요처잉 아닐 경우 차단할 수 있다
이 경우 스프링 컨테이너까지 요청이 전달되지 못하고 차단되므로 안정성을 높일 수 있다
- 필터는 이미지나 데이터의 압축, 문자열 인코딩과 같이 웹 어플리케이션에 전반적으로 사용되는 기능을
구현하기에 적당하다
A) 사용 사례
- 보안 및 인증 / 인가 관련 작업
- 모든 요청에 대한 로깅 또는 검사
- 이미지 / 데이터 압축 및 문자열 인코딩
- Spring 과 분리되어야 하는 기능
(2) 인터셉터
- 클라이언트의 요청과 관련되어 전역으로 처리해야하는 작업들을 처리할 수 있다
- 대표적으로 세부적으로 적용해야하는 인증이나 인가와 같은 것
예) 특정 그룹의 사용자는 어떤 기능을 사용하지 못하는 경우가 있는데, 이러한 작업들을 컨트롤러로
넘어가기전에 검사해야 하는 것
- 필터와 다르게 HttpServletRequest 나 HttpServletResponse 등과 같은 객체를 제공 받으므로 객체 자체를
조작할 수 없으나 해당 객체가 내부적으로 갖는 값을 조작할 수 있으므로 컨트롤러로 넘겨주기 위한 정보를
가공하기에 용이
- 예) JWT 토큰 정보를 파싱해서 컨트롤러에게 사용자의 정보를 제공하도록 가공할 수 있다
그 외에도 여러 목적으로 API 호출에 대한 정보들을 기록해야 하는 상황에 클라이언트의 IP 나
요청 정보들을 기록하기에 용이
A) 사용 사례
- 세부적인 보안 및 인증 / 인가 공통작업
- API 호출에 대한 로딩 또는 검사
- Controller 로 넘겨주는 정보의 가공
4. 정리
- 필터와 인터셉터 모두 비지니스 로직과 분리되어 특정 요구사항(보안, 인증 인코딩 등)을 만족시켜야 할때 적용
- 필터는 특정 요청과 컨트롤러에 관계없이 전역적으로 처리해야하는 작업이나 웹 어플리케이션에
전반적으로 사용되는 기능을 구현할 때 적용
- 인터셉터는 클라이언트의 요청과 관련된 작업에 대해 추가적인 요구사항을 만족해야 할 때 적용