2 분 소요


소개

스프링 인터셉터도 서블릿 필터와 같이 웹 관련 공통 관심 사항을 효과적으로 해결할 수 있는 기술이다. 서블릿 필터는 서블릿이 제공하는 기술, 스프링 인터셉터는 스프링 MVC가 제공하는 기술이다.
서블릿 필터와는 적용되는 순서와 범위, 사용법이 다르다.

흐름

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러
  • DispatcherServlet과 컨트롤러 사이에서 컨트롤러 호출 직전에 호출된다.
  • URL 패턴을 적용할 수 있는데, 서블릿 URL 패턴과는 다르며, 매우 정밀하게 설정할 수 있다.

제한

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

체인

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

인터셉터 인터페이스

public interface HandlerInterceptor {

    default boolean preHandle(
        HttpServletRequest request, HttpServletResponse response, Object handler) 
        throws Exception {}

    default void postHandle(
        HttpServletRequest request, HttpServletResponse response,
        Object handler, @Nullable ModelAndView modelAndView) throws Exception {}
    
    default void afterCompletion(
        HttpServletRequest request, HttpServletResponse response, Object handler, 
        @Nullable Exception ex) throws Exception {}
}
  • 서블릿 필터는 doFilter()하나만 제공되지만, 인터셉터는 컨트롤러 호출 전(preHandle), 호출 후(postHandle), 요청 완료 이후(afterCompletion)와 같이 단계적으로 세분화 되어 있다.
  • 서블릿 필터의 경우 request, response만 제공했지만, 인터셉터는 어떤 컨트롤러(handler)가 호출되는지 호출 정보도 받을 수 있다.
  • 또한, 어떤 ModelAndView가 반환되는지 응답 정보도 받을 수 있다.

인터셉터 호출 흐름

interceptor

정상 흐름

  • preHandle: 핸들러 어댑터 호출 전에 호출.
    • preHandle의 응답값이 true면 진행, false면 더는 진행하지 않는다.
    • false인 경우 나머지 인터셉터는 물론이며, 핸들러 어댑터도 호출되지 않는다.
  • postHandle: 핸들러 어댑터 호출 후에 호출.
  • afterCompletion: 뷰가 렌더링 된 이후에 호출.

인터셉터 예외 상황

interceptor2

예외 발생시

  • postHandle: 컨트롤러에서 예외 발생시 postHandle은 호출X
  • afterCompletion: afterCompletion은 항상 호출된다.
    • 이 경우 예외를 파라미터로 받아서 로그로 출력할 수 있다.
    • try-catch문의 finally같은 느낌.
    • 예외와 무관하게 공통 처리를 하려면 afterCompletion을 사용해야 한다.

정리

인터셉터는 스프링 MVC 구조에 특화된 필터 기능을 제공하기 때문에, 스프링 MVC를 사용하고, 특별히 필터를 사용해야 하는 상황이 아니라면 인터셉터를 사용하는 것이 더 편리하다.


인증 체크

LoginCheckInterceptor

@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(
        HttpServletRequest request, HttpServletResponse response, Object handler) 
        throws Exception {

        String requestURI = request.getRequestURI();
        log.info("인증 체크 인터셉터 실행 {}", requestURI);

        HttpSession session = request.getSession(false);

        if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
            log.info("미인증 사용자 요청");

            //로그인으로 redirect
            response.sendRedirect("/login?redirectURL=" + requestURI);
            return false;
        }
        return true;
    }
}

인증은 컨트롤러 호출 전에만 호출되면 되기 때문에 preHandle만 구현하면 된다.

WebConfig

세밀한 설정 가능

순서 주의, 세밀한 설정 가능
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        // LogInterceptor 생략..

        registry.addInterceptor(new LoginCheckInterceptor())
        .order(2)
        .addPathPatterns("/**")
        .excludePathPatterns(
            "/", "/members/add", "/login", "/logout",
            "/css/**", "/*.ico", "/error"
        );
    }
}

WebMvcConfigurer가 제공하는 addInterceptors를 사용해서 인터셉터를 등록할 수 있다.

  • registry.addInterceptor(...): 인터셉터 등록
  • order(): 인터셉터의 호출 순서 지정. 낮을 수록 먼저 호출된다.
  • addPathPatterns: 인터셉터를 적용할 URL 패턴을 지정.
  • excludePathPatterns(...): 인터셉터에서 제외할 패턴을 지정.

PathPattern 공식 문서 [링크]
‘?’ 한 문자 일치
‘*’ 경로(/) 안에서 0개 이상의 문자 일치
‘**’ 경로 끝까지 0개 이상의 경로(/) 일치
(생략)…


<출처 : 인프런 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술(김영한)>

댓글남기기