Interceptor 사용해보기

PostController

간단하게 실험용으로 Get 요청 시 Hello World 를 반환하는 컨트롤러를 만든다.

@GetMapping("/hello")
public String hello() {
    return "Hello World";
}

AuthIntercepteor

인터셉터를 구현하기 위해 우선 HandlerInterceptor 를 상속받는 인터셉터 클래스를 하나 만든다.

윈도우 기준 ctrl + i 를 누르면 구현할 수 있는 아래 사진처럼 메서드 목록이 나온다.

전부 다 구현하고 어떻게 동작하는지 확인할겸 로그를 찍어볼것이다.

@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info(">> preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info(">> postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info(">> afterCompletion");
    }
}

 preHandle

이 글에서 설명했듯 prehandle 은 boolean 값을 return 값으로 반환한다.

true 면 다음 단계를 진행하고 false 면 해당 요청을 거기서 중단한다.

WebMvcConfig

인터셉터를 적용하기 위해 아래처럼 Config 를 설정해준다.

이렇게 설정하면 모든 컨트롤러에 대해 인터셉터가 동작할것이다.

애플리케이션을 실행하거나 Mock 테스트를 수행하고 로그를 확인하면 아래처럼 동작하는걸 확인할 수 있다.

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor());
    }
}

 


ControllerTest

위에서 작성한 AuthIntercepteor 의 preHandle 값에 따른 인터셉터 호출을 비교해보기 위해 간단한 Mock 테스트를 수행한다.

@DisplayName("/hello 요청시 Hello World 를 출력한다.")
@Test
void hello() throws Exception {
    mockMvc.perform(
        MockMvcRequestBuilders.get("/hello")
        )
        .andExpect(status().isOk())
        .andExpect(content().string("Hello World"))
        .andDo(print());
}

ㄴ preHandle - true

prehandle, postHandle, afterCompletion 모두 호출된다.

ㄴ preHandle - false

preHandle 만 호출된다.

'백엔드 > Spring' 카테고리의 다른 글

@ConfigurationProperties로 환경 변수 관리  (0) 2023.10.08
ArgumentResolver  (0) 2023.09.29
Filter  (0) 2023.09.29
Interceptor  (0) 2023.09.29
BeanValidation 써보기  (0) 2023.09.22

인터셉터

사용자 인증과 같은 웹과 관련된 공통 관심 사항을 효과적으로 처리할 수 있도록 스프링 MVC 가 제공하는 기능이다.

서블릿 필터 서블릿이 제공하는 기능이라면 스프링 인터셉터 스프링 MVC 가 제공하는 기능이다.

 

공통 관심사는 스프링의 AOP로도 해결할 수 있지만 아래와 같은 이유로 웹과 관련된 공통 관심사는

서블릿 필터 또는 스프링 인터셉터를 사용하는 것이 좋다. 

  • 웹과 관련된 공통 관심사를 처리할 때는 쿠키나 세션을 확인해야 하기 때문에 HTTP의 헤더나 URL의 정보들이 필요하다.
  • 서블릿 필터나 스프링 인터셉터는 HttpServletRequest 를 제공하기 때문에 이를 처리하기 용이하다

 

스프링 인터셉터 흐름

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러

 

스프링 인터셉터의 흐름은 위와 같다. 스프링을 사용하기 때문에 위 흐름에서 표시된 서블릿은 DispatcherServlet 이다.

인터셉터는 스프링 MVC 가 제공하는 기능이기 때문에 서블릿을 지난 다음 적용된다.

 

스프링 인터셉터 제한

로그인 사용자
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러       

비 로그인 사용자                                              
HTTP 요청 -> WAS -> 필터  -> 서블릿 -> 스프링 인터셉터 <<< 적절하지 않은 요청, 컨트롤러 호출 X    

 

인터셉터에서 적절하지 않은 요청이라고 판단하면 서블릿을 호출하지 않고 거기에서 끝낼수도 있다. 

 

인터셉터 체인

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 인터셉터1 -> 인터셉터2 -> 인터셉터3 -> 컨트롤러

 

스프링 인터셉터는 체인으로 구성되는데 중간에 인터셉터를 자유롭게 추가할 수 있다.

예를 들어서 로그를 남기는 인터셉터를 먼저 적용하고 그 다음에 로그인 여부를 체크하는 인터셉터를 만들 수 있다.

 


필터와의 차이점

위까지만 보면 사실 필터와 크게 다른 차이를 못느낄것이다.

필터는 서블릿(DispatcherServlet ) 호출 전에 적용되기 때문에 Response 와 Request 정도만 조정할 수 있지만

인터셉터는 서블릿 호출 이후에 적용되므로 컨트롤러 호출 전, 호출 후, 요청 완료 이후 까지 세분화해서 조정할 수 있다.

 

인터셉터 호출 흐름

1. 정상 흐름

 

  1. preHandle
    - 컨트롤러 전에 호출된다.
    - preHandle 의 응답값이 true 면 다음으로 진행하고, false 면 요청을 여기서 끝낸다.
      false 일 경우 체인된 나머지 인터셉터는 물론이고 핸들러 어댑터도 호출되지 않는다.
  2. postHandle
    - 컨트롤러 호출 후에 호출된다. (정확히는 핸들러 어댑터 호출 후)
  3. afterCompletion
    - 뷰가 렌더링 된 이후에 호출된다.
    - 항상 호출되며, 예외 상황 시 예외 정보를 포함해서 호출된다.

2. 스프링 인터셉터 예외 상황

 

  1. preHandle
    - 컨트롤러 전에 호출된다.
  2. postHandle
    - 컨트롤러에서 예외가 발생하면 postHandle 은 호출되지 않는다.
  3. afterCompletion
    - 항상 호출되며, 예외 상황 시 예외 정보를 포함해서 호출된다.

위처럼 afterCompletion은 예외가 발생해도 호출된다.

예외가 발생하면 postHandle() 은 호출되지 않으므로 예외와 무관하게 공통 처리를 하려면

afterCompletion() 을 사용해야 한다.

 

 

참고자료)

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의

웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있

www.inflearn.com

 

'백엔드 > Spring' 카테고리의 다른 글

Interceptor 써보기  (0) 2023.09.29
Filter  (0) 2023.09.29
BeanValidation 써보기  (0) 2023.09.22
@ModelAttribute 와 @RequestBody 써보기  (0) 2023.09.21
DispatcherServlet  (0) 2023.08.01

+ Recent posts