[스프링/Spring] 스프링 인터셉터(Interceptor)

dongbrown·2024년 6월 16일

Spring

목록 보기
3/23
post-thumbnail

인터셉터(Interceptor)란?

  • 서블릿 필터와 같이 공통 관심 사항을 효과적으로 해결할 수 있는 기술
  • Controller에 들어오는 요청(HttpRequest)응답(HttpResponse)를 가로채는 역할을 하는 컴포넌트이다.
  • 즉, 서버에 들어온 Request 객체를 Controller의 핸들러로 도달하기 전 가로채서 개발자가 원하는 추가적인 작업 후 핸들러로 보낸다.
  • 주로 인증과 권한 검사, 로깅, 트랜잭션 관리 등의 전역적인 작업을 처리하는데 사용된다.
  • 실행되어야 할 핸들러에 대한 정보를 인자값으로 받기 때문에 서블릿 필터보다 세밀한 로직 구성이 가능하다.
  • 비동기적 요청 처리 시에는 호출되지 않는다.


인터셉터(Interceptor) 작동 원리

1. HandlerInterceptor 인터페이스 구현

  1. preHandle()

    • Controller 호출 전 실행
    • 리턴이 true일 경우 preHandle() 실행 후 핸들러 접근
    • 적용중인 인터셉터가 여러 개인 경우, preHandle()은 설정된 순서대로 호출된다.
  2. postHandle()

    • Controller 호출 후, View 생성 전 실행
    • 리턴이 false일 경우 실행되지 않는다.
  3. afterCompletion()

    • 모든 View에서 최종 결과를 생성하는 일을 포함한 모든 작업이 완료된 후 실행

2. 인터셉터 동작 위치 및 순서

  1. HandlerMapping 검색

    • 클라이언트의 요청이 들어오면 먼저 스프링 컴포넌트인 HandlerMapping이 URL을 통해 컨트롤러를 찾는다.
  2. Interceptor 체인 생성

    • HandlerMapping은 해당 컨트롤러와 연결된 인터셉터 체인을 생성한다. Interceptor 체인은 여러 개의 Interceptor 객체로 구성될 수 있으며 각각의 인터셉터는 요청을 가로채고 처리하는 역할을 수행한다.
  3. 요청 처리

    • 인터셉터 체인에 의해 요청이 처리되고, 각 인터셉터는 preHandle(), postHandle(), afterCompletion() 메서드를 통해 요청과 응답을 처리한다.


장점과 단점

장점

  1. 중앙 집중적인 공통 기능 관리

    • Interceptor를 사용하면 로그인 체크, 권한 검사, 로깅, 예외 처리 등과 같은 공통 기능을 중앙에서 관리할 수 있다. 이는 중복 코드를 제거하고 유지보수성을 향상시킨다.
  2. 요청 처리 과정 제어

    • Interceptor는 요청 전(preHandle)과 후(postHandle)에 실행되는 메서드를 제공하여 요청 처리 과정을 세밀하게 제어할 수 있다. 예를 들어, 요청 전에 인증 체크를 수행하거나, 요청 후에 로깅 작업을 수행할 수 있다.
  3. 재사용성과 확장성

    • Interceptor는 여러 컨트롤러에 적용될 수 있으며, Interceptor 체인을 구성하여 여러 개의 Interceptor를 조합할 수 있다. 이로 인해 공통 기능을 간편하게 재사용하고, 필요에 따라 확장할 수 있다.
  4. 전역 예외 처리

    • Interceptor를 사용하면 예외 처리를 중앙에서 처리할 수 있다. 예외가 발생하면 Interceptor의 예외 처리 메서드를 활용하여 일관된 방식으로 예외를 처리하고 사용자에게 적절한 응답을 보낼 수 있다.

단점

  1. 성능 영향

    • Interceptor는 요청과 응답 사이에 위치하므로, 매 요청마다 Interceptor 체인이 실행되어야 한다. Interceptor가 많거나 복잡한 작업을 수행하는 경우 성능에 영향을 줄 수 있다. 따라서 Interceptor의 사용은 신중하게 고려되어야 한다.
  2. 컨트롤러와의 결합도

    • Interceptor는 컨트롤러와 긴밀하게 결합되어 있다. 이는 컨트롤러의 변경에 따라 Interceptor도 변경될 수 있음을 의미한다. 따라서 Interceptor의 사용은 컨트롤러와의 강한 결합도를 가질 수 있으므로 유지보수에 주의가 필요하다.
  3. 작업의 순서와 조건 제어

    • Interceptor 체인에서 Interceptor의 실행 순서와 조건 제어를 올바르게 설정해야 한다. 잘못된 순서나 조건 설정은 의도하지 않은 동작을 유발할 수 있으므로 주의가 필요하다.
  4. 제한된 범위

    • Interceptor는 주로 웹 요청을 처리하는 데 사용된다. 따라서 웹 애플리케이션에만 적용 가능하며, 다른 종류의 요청이나 서비스에는 사용할 수 없다.


인터셉터(Interceptor)의 활용 예시

1. 인증과 권한 검사

인터셉터를 사용하여 모든 요청에 대해 사용자의 인증 여부를 검사할 수 있다. 예를 들어, 사용자가 보호된 페이지에 접근하려고 할 때, 인터셉터는 요청을 가로채어 사용자가 로그인되어 있는지 확인하고, 로그인되어 있지 않다면 로그인 페이지로 리다이렉트할 수 있다.

public class AuthenticationInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute("user") == null) {
            // 사용자가 로그인하지 않은 경우 처리 로직
            response.sendRedirect("/login");
            return false;
        }
        return true;
    }
}

2. 로깅

인터셉터를 사용하여 요청과 응답에 대한 로깅을 수행할 수 있다. 예를 들어, 특정 요청이 들어올 때 요청 정보를 로그에 남기거나, 응답을 생성할 때 응답 정보를 로그에 기록할 수 있다.

public class LoggingInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("Request URL: {}", request.getRequestURI());
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        logger.info("Response Status: {}", response.getStatus());
    }
}

3. 트랜잭션 관리

인터셉터를 사용하여 트랜잭션을 관리할 수 있다. 예를 들어, 특정 요청이 들어왔을 때 트랜잭션을 시작하고, 요청 처리가 완료되면 트랜잭션을 커밋하거나 롤백할 수 있다.

public class LoggingInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("Request URL: {}", request.getRequestURI());
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        logger.info("Response Status: {}", response.getStatus());
    }
}

0개의 댓글