Spring Interceptor 동작 방식
강의에서 Spring 인터셉터를 사용하는 부분이 있었는데 정확한 동작 방식 사용법을 이해하지 못하였다.
이 내용을 정리하고 어떤 식으로 동작하는 한번 같이 알아보자
1. Spring Interceptor
Interceptor란 말을 그대로 해석 하면 가로챈다 라는 의미를 가진다.
이름 그대로 Spring MVC에서 인터셉터는 특정한 URI 호출을 가로채는 역할을 한다.
인터셉터를 활용하면 기존의 로직을 수정하지 않고, 사전 하우 제어를 수행 할 수 있다.
즉, 요청과 응답을 가로채서 원하는 동작을 추가할 수 있는 것이다.
가장 대표적인 예시로 세션을 통한 인증 구현이 있다.
요청을 받기 이전에 요청을 가로채서 세션에 로그인한 사용자가 있는지 확인하고 없으면 로그인 페이지로 보낼 수 있다.
이는 게시판이라면 글쓰기, 마이페이지 보기 등 작업에서 가능하다.
Interceptor가 없다고 생각하면 이를 구현하기 위해서 이 처리 로직을 원하는 컨트롤러 메서드마다 넣어야하는 작업이 필요하다.
개발을 할 떄 3번 이상 동일한 작업을 수행하면 그 작업을 대부분 새로운 것으로 분리하여 반복을 줄 일 수 있다
Spring은 거대한 생태계이기 때문에 이런 반복 작업이 있다면 Spring에서 아마 대부분의 기능을 지원할 것 이다.
2. Interceptor 동작 과정
👉 Interceptor
Dispatcher 서블릿이 컨트롤러를 호출하기 전/후에 인터셉터가 끼어들어서 요청/응답에 로직 수행
웹 컨테이너에서 동작하는 필터와 다르게 인터셉트는 Spring Context 에서 실행된다.
인터셉트에서는 2가지의 메서드를 통해서 요청/응답의 전/후 처리를 한다.
전체 요청 과정을 통해서 인터셉트를 한번 확인해보자
시작은 요청 수신 과정이기 때문에 생략하고 시작한다.
1️⃣ 인터셉트의 preHandle 메서드 실행
인터셉트의 preHandle 메서드를 실행한다. 이 메서드는 Spring MVC 요청 처리를 위한 핸들러(컨트롤러)를 찾기 전에 실행된다. 여기서 true를 반환하면 다음단계를 진행되고 false 면 요청이 중지된다.
2️⃣ 핸들러 매핑
preHandle 메서드 true를 반환하면 요청 처리가 가능한 핸들러를 찾는다
3️⃣ 핸들러 어댑터 호출
처리 가능한 핸들러가 발견되면 HandlerAdapter가 컨트롤러 메서드를 실행하기 위해서 호출
4️⃣ 매개변수 준비
HandlerMethodArgumentResolver를 순회해서 필요한 매개변수를 준비한다.
아래의 이전 포스팅에 해당 과정이 상세하게 설명되어 있다.
5️⃣ 컨트롤러 메서드 호출
모든 매개 변수가 준비된 이후 컨트롤러 메서드를 호출해서 요청 응답을 처리한다.
6️⃣인터셉터 postHandle 메서드 실행
컨트롤러의 메서드가 호출된 후 뷰가 렌더링 되기 전에 인터셉터의 postHandle 메서드가 실행된다.
7️⃣ view 렌더링 & 인터셉터 afterCompletion 실행
뷰가 렌더링된 이후에는 인터셉터의 afterCompletion 메서드가 실행 된다.
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Pre Handle method is Calling");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Post Handle method is Calling");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Request and Response is completed");
}
}
3. Interceptor vs Filter
인터셉터 필터 두가지 모두 요청과 응답의 전후에 사용하는 방식이기 때문에 많이 헷갈리는 것 같다.
필터에 대해서 가볍게 알아보고 인터셉트와 비교해보자
👉 Filter
Filter 는 DispatcherServlet의 처리 전/후 에 동작해서 사용자의 요청이 응답의 전방에 존재
여기서 필터는 스프링의 기술이 아닌 자바 서블릿에서 제공된다.
Dispatcher Servlet 에 요청이 전달되기 전/후 URL 패턴에 맞는 모든 요청에 대한 부가 기능을 제공한다.
그래서 스프링의 프론트 컨트롤러 역할인 Dispatcher 서블릿 이후가 아니기에 톰캣과 같은 웹 컨테이너에서 관리된다.
📌스프링 빈으로 등록이 가능
필터의 인터페이스 코드를 한번 확인해보자
public interface Filter {
public default void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
public default void destroy() {}
}
총 3가지의 메서드르 가지고 있다.
1️⃣ init()
필터 객체를 초기화 하고 서비스에 추가하기 위한 메서드
웹 컨테이너가 한번 호출하여 필터 객체를 초기화 하면 이후에는 doFilter() 를 통해서 처리
2️⃣ doFilter()
url 패턴에 맞는 모든 HTTP 요청이 Dispatcher Servlet 으로 전달하기 전에 웹 컨테이너에서 실행
doFilter로 파라미터로 FilterChain이 존재한다. 이 Filter Chain을 통해서 다음 대상으로 처리된 요청을 전달한다.
3️⃣ destory()
필터 객체를 제거하고 사용하는 자원을 반환 하는 메서드
웹 컨테이너가 1회 호출하면 필터 종료시 요청은 doFilter() 처리 X
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
System.out.println("CustomFilter 생성");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("CustomFilter 필터 시작");
chain.doFilter(request, response);
System.out.println("CustomFilter 필터 종료");
}
@Override
public void destroy() {
System.out.println("CustomFilter 삭제");
Filter.super.destroy();
}
}
✅ 필터와 인터셉터 차이
1. Request, Response 객체 조작 가능 여부
필터는 응답/요청을 조작 가능 하지만, 인터셉터는 불가능하다.
필터는 다음 필터 호출을 위해서 필터 체이닝 반드시 호출 필요하고 이때 응답/요청 객체로 넘겨주기 가능
하지만 인터셉터의 메서드는 리턴 값이 boolean 이기 때문에 다음으로 넘겨줄지 아닐지만 결정한다.
2. 사용하는 방식의 차이
👉 필터의 사용 사례
- 공통 보안/인증/인가
- 모든 요청에 대한 로깅 및 검사
- 이미지 , 데이터 압축, 문자열 인코딩
- Spring 과 분리되어야 하는 기능
스프링과 무관하게 처리되어야하는 작업들을 처리한다.
요청과 응답의 데이터를 처리할 수 있기 때문에 데이터 압축, 인코딩 등의 작업을 수행 하기에 적합
👉인터셉트 사용
- 세부 인증 작업
- API 호출 로깅 및 검사
- 컨트롤러 요청 데이터 가공
인터셉트는 클라이언트의 요청에 전역적인 처리를 수행한다.
특정 그룹 사용자의 권한 부여 같은 세부적인 인증/인가 처리를 컨트롤러로 넘기기 전에 인터셉트에서 처리
객체 자체를 조작할 수 없어 객체의 내부 값만 수정, 컨트롤러로 넘기기 전에 정보를 가공하기에 용이
대표적으로 JWT 토큰 정보를 파싱해서 컨트롤러에게 전달하는 방식으로 인증/인가 구현
4. 결론
인터셉트와 필터의 동작 자체는 비슷해 보이지만 처리되는 영역의 차이로 인한 역할의 차이가 존재한다.
또한 요청/응답 객체 자체를 수정할 수 있는지 없는지의 차이가 있다.
필터 같은 경우에는 스프링 시큐리티에서 필터 체인을 통한 보안 관련 처리를 하기 때문에 필터에 대한 포스팅을 추가로 할 예정이며 필터가 인터셉트와 어떻게 다른지를 반드시 기억할 필요가 있다.
'Spring' 카테고리의 다른 글
[Spring 핵심원리] @ControllerAdvice 예외처리 (0) | 2024.10.21 |
---|---|
[Spring 시큐리티] 사용자 인증 (0) | 2024.06.26 |
HandlerMethodArgumentResolver 동작 (1) | 2024.06.10 |
[Spring Petclinic]1. application properties (0) | 2024.04.27 |
Spring MVC - frontController (0) | 2024.03.14 |