Interceptor

seongha_h·2024년 5월 8일

Spring

목록 보기
1/6

spring interceptor는 이름에서 가지는 의미처럼 무언가를 가로채서 원하는 동작을 추가하는 역할을 합니다.

interceptor를 이해하기 위해서 HandlerMapping의 역할을 알아야 합니다.
HandlerMapping은 URL과 Handler 메서드를 맵핑하는 것입니다.
이를 통해 알맞은 Handler를 찾고, 동작시킬 수 있습니다.
interceptor는 Handler로 Request 객체가 전달되기 전과 후에 가로채서 원하는 동작을 추가할 수 있습니다.

spring interceptor는 웹과 관련된 공통 관심사를 해결하기 위한 기술로 대표적으로 공통 로그 처리, 권한 체크에 사용될 수 있습니다.

Filter vs Interceptor 인증/인가에 어떤게 적합한가?

아래 그림에서 필터는 인증과 로깅, 데이터 압축, 그리고 spring과 분리하고 싶은 기능을 추가하는 것이 적합하다고합니다.
그리고 인터셉터에서는 상세 권한 체크(인가)와 스프링 모델을 조작하는 등의 역할을 한다고 합니다.

Filter

  • 보안 관련 공통 작업
  • 모든 요청에 대한 로깅
  • 이미지/데이터 압축 및 문자열 인코딩

Interceptor

  • 인증/인가 등과 같은 공통 작업
  • Controller로 넘겨주는 정보 가공
  • API 호출에 대한 로깅

하지만 필터와 인터셉터에서 모두 인증/인가 처리가 가능합니다. 그렇기에 개발자나 팀원이 익숙한 방법을 선택하여 사용한다고 합니다.

Handler Interceptor

스프링에서 Interceptor를 구현하기 위해서는 HandlerInterceptor 인터페이스를 implements 하여 구현할 수 있습니다.

이 인터페이스에는 3가지 메서드가 존재합니다.

preHandle

Controller가 호출되기 이전 실행됩니다.
따라서 사용자의 요청정보를 가공 (형변환, json파싱, 문자열 파싱등) 할 수 있고, 로그를 남기는 것도 가능합니다.

인터셉터는 체인 형식을 가지고 있습니다.

따라서 boolean 형식의 리턴값을 가지고, true이면 다음 인터셉터를 실행하고, false이면 다음 인터셉터나 컨트롤러를 호출하지 않게됩니다.

postHandle

Controller호출 이후, View 호출 이전에 실행됩니다.

Controller에서 modelandView객체를 받아 Model객체의 정보를 조작하거나 참조할 수 있습니다.

preHandle 이 False라면 동작하지 않습니다.

afterCompletion

View까지 모든 작업이 완료된 이후에 실행됩니다.

preHandle 이 False라면 동작하지 않습니다.

적용해보기

상품 조회(GET) (/product/{id}) 요청은 모두가 허용하게 하고,
상품 등록(POST) (/product) ,
상품 수정 및 변경(PUT) (/product/{id}) 은 인증된 관리자만 사용할 수 있도록 만들어 보게 되었습니다.

아래와 같이 GET 메서드로 요청이 올때 인증 과정을 거치지 않고 인터셉터를 통과할 수 있도록 하였습니다.

boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
										Object handler){

		if (request.getMethod().equals(HttpMethod.GET.name())){
            return true;
     }       
     
     // 인증 과정
}

Filter vs Interceptor

아래 그림과 같이 Filter는 DispatcherServlet 이전, 이후에 동작합니다.
Filter는 동일한웹 애플리케이션의 영역 내에서 필요한 자원들을 활용합니다. (자바 서블릿에서 제공)
웹 애플리케이션 내에서 동작하므로, 스프링의 Context를 접근하기 어렵습니다.
현재는 Bean을 통해서 등록도 가능하고 주입도 가능합니다.
대표적으로 spring Security가 Filter단에서 동작합니다.

Interceptor의 경우 스프링에서 관리되기 때문에 스프링 내의 모든 객체(빈)에 접근이 가능하다는 차이가 있습니다.
즉, 빈을 관리하는 스프링 컨텍스트 내에 있어서 생성된 빈들에 자유롭게 접근할 수 있습니다.
이와같은 특징으로 인하여 Interceptor에서 발생시킨 예외를 ExceptionHandler를 통해 처리할 수 있습니다.

차이점

다음과 같은 차이점을 찾을 수 있었습니다.

  1. 동작위치
  2. 예외처리
  3. 각자만 가능한 것

동작 위치

Filter는 DispatcherServlet 이전에 동작합니다.
Interceptor는 DispatcherServlet 이후에 동작합니다.
따라서 이 실행 시점차이에 의해 Filter는 스프링과 분리되어 사용될 수 있습니다.

예외처리

Filter단에서 발생하는 예외는 WebApplication 에서 처리해야합니다.
따라서 에러 페이지를 잘 선언하여 사용하거나, Filter 내에서 예외처리를 따로 진행해 주어야 합니다.

Interceptor에서 발생하는 예외는 DispatcherServlet 이후에 동작하므로 @ControllerAdvice 내의 @ExceptionHandler를 통해 예외처리를 공통적으로 처리할 수 있다는 장점이 있습니다.

Filter만 가능한 것

ServletRequest 와 ServletResponse 를 교체할 수 있습니다.

HttpServletRequest는 Body의 내용을 한번만 읽을 수 있습니다.
따라서 요청 내용을 로깅할 때 Filter나 Interceptor에서 내용을 읽어버리면 Controller에서는 body를 읽을 수 없게 됩니다.
이를 해결하기 위해 HttpServletRequset를 감싸는 래퍼 클래스(customServletRequest)를 생성하여 여러번 inputStream을 읽을 수 있도록 해야 합니다.

Interceptor만 가능한 것

AOP를 흉내낼 수 있습니다.
HandlerMethod는 @RequestMapping 이 붙은 메서드를 추상화한 객체입니다.
HandlerMethod로 메서드 시그니처 등 추가적인 정보를 파악해서 로직 실행 여부를 판단할 수 있습니다.

또한 view를 랜더링하기 전에 추가적인 작업을 진행할 수 있습니다. (postHandle)

출처

https://meetup.nhncloud.com/posts/151
https://mangkyu.tistory.com/173

profile
https://github.com/Fixtar

0개의 댓글