[cs - Spring] 서블릿 Filter와 Spring Interceptor 차이, 예외처리

링딩·2023년 4월 28일
0

Computer Science

목록 보기
42/49

이전에 서블릿 필터와 스프링 인터셉터에의 차이에 대해 따로 정리는 여기에 있다!


질문에 대비해 차이 및 추가적으로 요약 정리를 더 해보자면




서블릿 필터와 스프링 인터셉터

스프링 MVC 2편 - 로그인 처리2 - 필터, 인터셉터에서 관련하여 글을 작성하였습니다.



📕 필터(Filter)와 인터셉터(Interceptor) 차이 정리

1. 관리되는 컨테이너

필터와 인터셉터는 관리되는 영역이 다르다. 필터는 스프링 이전의 서블릿 영역에서 관리되지만, 인터셉터스프링 영역에서 관리되는 영역이기 때문에
=> 필터는 스프링이 처리해주는 내용들을 적용 받을 수 없다.
=> 🚨 이로 인한 차이로 발생하는 대표적인 예시가 필터는 스프링에 의한 예외처리가 되지 않는다는 것이다.


+) 참고로 일부 포스팅 또는 자료에서 필터(Filter)가 스프링 빈으로 등록되지 못하며, 빈을 주입 받을 수도 없다고 하는데, 이는 잘못된 설명이다.
=> 이는 매우 옛날의 이야기이며🤔 , 필터는 현재 스프링 빈으로 등록이 가능하며, 다른 곳에 주입되거나 다른 빈을 주입받을 수도 있다.



2. 스프링의 예외 처리 여부

스프링을 사용한다면 ControllerAdviceExceptionHandler를 이용한 예외처리 기능을 주로 사용한다.

그래서 예외처리에 관한 예시로 만약 원하는 멤버를 찾지 못하여 로직에서 'MemberNotFoundException'을 던졌다면 404 Status로 응답을 반환하길 원할 것이다.

망나니 개발자님 코드 인용

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(MemberNotFoundException.class)
    public ResponseEntity<Object> handleMyException(MemberNotFoundException e) {
        return ResponseEntity.notFound()
            .build();
    }
    
    ...
}
  • 이처럼 예외처리기를 구현하여 예외가 서블릿까지 전달되지 않고 처리되어야 할 것이다.
    -> 그러나 '필터'는 스프링 앞의 서블릿 영역에서 관리되기 때문에 스프링의 지원을 받을 수 없다.

  • 그래서 만약 필터에서 MemberNotFoundException이 던져졌다면, 에러가 처리되지 않고 서블릿(여기서 말하는 필터 다음 과정인 서블릿은 Dispatcher Servlet을 뜻함)까지 전달된다. 서블릿은 예외가 핸들링 되기를 기대했지만, 예외가 그대로 올라와서 예상치 못한 Exception을 만난 상황이다.
    => 따라서 내부에 문제가 있다고 판단하여 500 Status로 응답을 반환한다.
    => 이를 해결하려면 필터에서 다음과 같이 응답(Response) 객체에 예외 처리가 필요하다.

public class MyFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse servletResponse = (HttpServletResponse) response;
        servletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
        servletResponse.getWriter().print("Member Not Found");
    }
}



3. Request/Response 객체 조작 가능 여부

  • 필터는 Request와 Response를 조작할 수 있지만 인터셉터는 조작할 수 없다.
    +) 여기서 조작한다는 것은 내부 상태를 변경한다는 것이 아니라 다른 객체로 바꿔진다는 의미이다.

필터는 위에도 나오다시피 Filter Chaining(다음 필터 호출) 이라는 기능이 있다. 그리고 이때 Request/Respsonse 객체를 넘겨줄 수 있다.(물론 NPE가 나겠지만서도)

ex) 필터에서는 이런 식으로 넣어줄 수 있다는 것이다.

public MyFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        // 개발자가 다른 request와 response를 넣어줄 수 있음
        chain.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse());       
    }
    
}

  • 반면에 인터셉터는 처리 과정이 필터와 다르다. Dispatcher Servlet이 여러 인터셉터 목록을 가지고 있고, for문으로 순차적으로 실행시킨다. 그리고 true를 반환하면 다음 인터셉터가 실행되거나 컨트롤러로 요청이 전달되며, false가 반환되면 요청이 중단된다.
    => 그래서... 우리가 다른 Request/Response 객체를 넘겨줄 수 없다.

그리고 이러한 부분이 필터와 확실히 다른 점이다. 👍



3. 필터와 인터셉터의 용도 및 예시


스프링에서의 Servlet Filter와 Spring Interceptor를 통한 예외처리 및 오류페이지에 관하여

스프링 MVC 2편 - 예외 처리와 오류 페이지
에 관하여

Q. Filter는 Servlet의 스펙이고, Interceptor는 Spring MVC의 스펙입니다. Spring Application에서 Filter와 Interceptor를 통해 '예외'를 처리할 경우 어떻게 해야 할까요?


'필터'는 WAS(웹컨테이너)에 의해 관리가 되는 영역이고, '인터셉터'는 DispatcherServlet(스프링의 프론트컨트롤러) 이후 영역이므로 스프링에 의해 관리되는 영역이다.

  • 공통점
    컨트롤러 진입전 실행로직을 작성할 수 있다는 것.

  • 차이점
    '필터'는... 스프링이 관리하지 않으므로, Spring Context를 사용할 수 없다는 것.



1) 인터셉터

@ControllerAdvice 로 스프링의 도움을 받아 객체지향적으로 예외처리를 할 수 있다.

2) 필터

¹직접 response에 접근하여 예외처리를 하거나, 톰캣의 경우 를 선언하여 처리하거나, ²인터셉터까지 계속 통과시켜 인터셉터에게 예외처리를 미뤄버려야 한다.

만약 인터셉터에게 미루지 않고 에러가 발생한 필터에서 doFilter()를 호출하여 다음필터로 전파하지 않고 바로 return 으로 클라이언트로 response 를 보내게 되면...
=> 프론트 컨트롤러인 'DispatcherServlet'에 서블릿 자체가 도달하지 않으므로 스프링에서는 알 방법이 없다...😥

그러므로

A. 답은

필터는 DispatcherServlet 외부에 존재하기 때문에 예외가 발생했을 때 ErrorController에서 처리해야 합니다.

인터셉터는 DispatcherServlet 내부에 존재하기 때문에 @ControllerAdvice를 적용해서 처리할 수 있습니다.

이 곳의 에러처리 방식이 좋은 정보가 되었다. 참고하면 좋을 것 같다.

이 곳

profile
초짜 백엔드 개린이

0개의 댓글