스프링 인터셉터(Interceptor)란?

oh_eol·2024년 4월 3일
0

Spring MVC

목록 보기
2/2

인터셉터란?

컨트롤러의 핸들러를 호출하기 에 요청과 응답을 참조하거나 가공할 수 있는, 일종의 필터이다.

로그인 된 계정만 실행 가능한 Controller 핸들러를 작성한다고 가정하자.
그럼 우리는 계정이 로그인 되었는지를 확인하는 세션 검증 코드를 해당하는 모든 핸들러에 각각 작성해야 한다.

핸들러가 많아질수록 서버의 부하가 늘어나고, 실수로 세션 검증을 적용하지 않은 핸들러가 생기는 누락의 문제가 발생할 수도 있다.

이 때 스프링이 제공하는 인터셉터를 이용하면, 한 번의 작성으로 여러 컨트롤러에 세밀하게 접근하는 것을 가능케 한다.

스프링 인터셉터의 호출 흐름

  • 디스패처 서블릿이 요청을 처리하고 응답하기까지의 과정
  • 인터셉터의 흐름
  • 스프링이 제공해주는 HandlerInterceptor 인터페이스와 HandlerInterceptorAdapter 추상클래스에 정의되어 있는 메서드에는 preHandle(), postHandle(), afterCompletion() 3가지가 있다.

스프링 인터셉터의 메서드

1. preHandle()

  • 디스패처 서블릿이 핸들러 목록에서 핸들러를 조회한 뒤에 호출된다.
  • 아직 컨트롤러(핸들러)는 호출되지 않았다.
  • 실행되어야 할 '핸들러'에 대한 정보를 인자값으로 받기때문에 '서블릿 필터'에 비해 세밀하게 로직을 구성할수 있음
  • 리턴값이 boolean이다. 리턴이 true 일경우 preHandle() 실행후 핸들러에 접근한다. false일경우 작업을 중단하기 때문에 컨트롤러와 남은 인터셉터가 실행되지않는다.

2. postHandle()

  • 핸들러가 실행은 완료 되었지만 아직 View가 생성되기 이전에 호출된다.
  • ModelAndView 타입의 정보를 인자값으로 받는다. 따라서 Controller에서 View 정보를 전달하기 위해 작업한 Model 객체의 정보를 참조하거나 조작할수 있다.
  • preHandle() 에서 리턴값이 fasle인 경우, 또 컨트롤러에서 예외가 발생한 경우에는 호출되지 않는다.

3. afterCompletion()

  • 모든 View에서 최종 결과를 생성하는 일을 포함한 모든 작업이 완료된 후에 실행된다.
  • 요청 처리중에 사용한 리소스를 반환해주기 적당한 메서드 이다.
  • preHandle() 에서 리턴값이 false인경우 실행되지 않는다.
  • 컨트롤러에서 예외가 발생해도 호출된다.

인터셉터 구현 방법

인터셉터를 적용하기 위한 큰 틀은 다음과 같다.
1. HandlerInterceptor 인터페이스 상속받은 클래스에서 원하는 로직을 구현한다.
2. WebMvcConfigurer 를 상속받은 Config 파일에 Bean 등록을 하고, 인터셉터 및 인터셉터를 적용할 url을 추가한다.

실습

로그인을 한 사람만 페이지 접속이 가능하도록 인증 체크 기능을 인터셉터로 개발해보자.

LoginCheckInterceptor

 import hello.login.web.SessionConst;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.servlet.HandlerInterceptor;
  
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
 @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() 만 구현하면 된다.
  • 만약 로그인하지 않은 사용자의 접근 요청이 오면, 디스패처 서블릿은 다음 순서로 처리한다.
    • 컨트롤러 목록에서 login 컨트롤러 조회
    • LoginCheckInterceptor 호출, 미인증 사용자 검증 후 로그인 화면으로 redirect 시키면서 false 리턴하여 login 컨트롤러와 남은 인터셉터의 호출을 막는다.
  • 만약 로그인 한 사용자의 접근 요청이 오면, 디스패처 서블릿은 다음 순서로 처리한다.
    • 컨트롤러 목록에서 login 컨트롤러 조회
    • LoginCheckInterceptor 호출, true 리턴
    • login 컨트롤러 호출 및 남은 인터셉터 호출
    • 여기서는 preHandle()만 구현했지만, postHandle()의 경우 컨트롤러에서 사용하는 ModelAndView 정보를 사용할 수도 있다.

참고
1. 김영한님 Spring MVC2 강의
2. https://popo015.tistory.com/115

profile
공부 중입니다.

0개의 댓글