inblog logo
|
LifeLog, DevLog
    Spring

    Spring의 주요 강점 - 3, Interceptor

    KYJTHEYJ's avatar
    KYJTHEYJ
    Nov 25, 2025
    Spring의 주요 강점 - 3, Interceptor
    Contents
    InterceptorAspect와 차이점HandlerInterceptorSpring MVC에 등록

    Interceptor

    컨트롤러의 실행 전후를 가로채 처리하는 컴포넌트

    Aspect와 차이점

    Spring MVC

    MVC의 실행 순서로 보았을 때, Aspect (의 @Before) 보다 실행 순서가 전이다

    Controller의 레벨 자체의 접근과 접근 후를 처리하는 것이 Interceptor
    메서드의 실행 레벨에 접근하여 처리하는 것이 Aspect

    Aspect 의 잘못된 사용

    Aspect 가 파라미터의 값을 검증하는데 쓰이지만, 값도 바인딩 단계 이후에 처리된다
    즉, 이 파라미터 자체가 바인딩이 되었는지를 확인 하는 것은
    컨트롤러 레벨에 접근 하기 전에 하는 것이 맞다
    그러므로 Interceptor 가 맞다

    전체적인 흐름은 아래와 같다

    요청 → Filter → DispacterServlet → Interceptor.prehandle
    → AOP @Before → Controller 실행 → AOP @After → Interceptor.postHandle() → View의 렌더링 → Interceptor.afterCompletion()

    HandlerInterceptor

    컨트롤러의 실행 전, 실행 후, 요청 완료 후 세가지의 처리를 할 수 있는
    인터셉터 핸들러용 인터페이스

    보통 이 인터페이스를 임플리먼트 하여 Intercepor를 구현한다

    public interface HandlerInterceptor {
        
        // 1. Controller 실행 전
        boolean preHandle(HttpServletRequest request, 
                         HttpServletResponse response, 
                         Object handler) throws Exception;
        
        // 2. Controller 실행 후 (View 렌더링 전 or 데이터 전달 전)
        void postHandle(HttpServletRequest request, 
                       HttpServletResponse response, 
                       Object handler, 
                       ModelAndView modelAndView) throws Exception;
        
        // 3. 요청 완료 후 (View 렌더링 후 or 데이터 전달 후)
        void afterCompletion(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler, 
                            Exception ex) throws Exception;
    }

    HandlerMethod 와 같이 많이 쓰이는데,
    HTTP 요청을 처리할 때 매핑된 컨트롤러 메서드를 캡슐화하는 객체이다

    파라미터인 handler 가 실행될 컨트롤러의 메서드 정보를 담고 있는 객체이므로
    instanceof 가 true 라면 요청을 처리시 매핑된 컨트롤러 메서드 임을 증빙

    preHandle (전처리)

    요청이 식별되고 컨트롤러 레이어의 접근 전을 처리

    @Component
    @Slf4j
    public class preHandleSomethingInterceptor implements HandlerInterceptor {
        
        @Override
        public boolean preHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler
        ) throws Exception {
            
            log.info("preHandle 실행");
            
    		//현재 실행될 메서드가 컨트롤러 메서드인지 확인
    		//if(handler instanceof HandlerMethod) {
    			// 인증 등 수행
    
    		//	return true;
        	//}
    
            // true: Controller 실행
            // false: Controller 실행 안함 (여기서 끝)
    
    		// 영향 받지 않는 것들은 통과 되도록
            return true;
        }
    }

    postHandle (후처리)

    컨트롤러 레이어 접근 후 컨트롤러가 실행이 되고 난 뒤를 처리

    예외가 실행 중 발생했다면 postHandle은 처리되지 않는다
    렌더링 단계도 접근 가능하다

    @Component
    @Slf4j
    public class postHandleSomethingInterceptor implements HandlerInterceptor {
        
        @Override
        public void postHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler,
            ModelAndView modelAndView
        ) throws Exception {
            // 예외가 실행 중 발생했다면 postHandle은 실행되지 않음
            log.info("postHandle 실행");
            
            // Controller 실행 완료
    
            // View 렌더링 전이니 modelAndView 로 요소 접근 후 수정 가능
            }
        }
    }

    afterCompletion (모든 완료 후)

    컨트롤러 레이어 접근 후 컨트롤러와 렌더링도 실행이 되고 난 뒤를 처리
    finally 구문과 성질이 비슷하다

    예외가 발생해도 실행되는 것을 알아야한다, 예외 정보도 받아올 수 있다

    @Component
    @Slf4j
    public class LoggingInterceptor implements HandlerInterceptor {
        
        @Override
        public void afterCompletion(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler,
            Exception ex  // 예외 정보 (예외가 발생 했다면)
        ) throws Exception {
            // 항상 실행됨 (예외 발생해도)
            log.info("afterCompletion 실행");
            
            if (ex != null) {
                log.error("예외 발생: {}", ex.getMessage());
            }
            
            // 리소스 정리 등
        }
    }

    afterCompletion 을 통한 DB 리소스 정리

    @Component
    @Slf4j
    public class ResourceCleanupInterceptor implements HandlerInterceptor {
        
        private static final String DB_CONNECTION = "dbConnection";
        
        @Override
        public boolean preHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler
        ) throws Exception {
            
            // 리소스 획득
            Connection connection = getConnection();
            request.setAttribute(DB_CONNECTION, connection);
            
            log.info("DB 연결 획득");
            
            return true;
        }
        
        @Override
        public void afterCompletion(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler,
            Exception ex
        ) throws Exception {
            
            // 리소스 정리 (항상 실행)
            Connection connection = (Connection) request.getAttribute(DB_CONNECTION);
            
            if (connection != null) {
                connection.close();
                log.info("DB 연결 해제");
            }
            
            if (ex != null) {
                log.error("예외 발생으로 인한 정리: {}", ex.getMessage());
            }
        }
        
        private Connection getConnection() {
            // 실제 DB 연결
            return null;
        }
    }

    💡

    RestController 에서는 postHandle 을 쓸 일이 거의 없다
    modelAndView 를 처리할 일이 거의 없기 때문이다
    또한 예외가 발생하면 실행이 안되므로.. 주로 afterCompletion을 사용

    Spring MVC에 등록

    Spring MVC의 설정을 커스터마이징하는 설정 클래스

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
       @AutoWired
       private SomethingInterceptor somethingInterceptor;
       
    
       public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(somethingInterceptor);
        }
        
    }
    Share article
    Contents
    InterceptorAspect와 차이점HandlerInterceptorSpring MVC에 등록

    LifeLog, DevLog - https://github.com/KYJTHEYJ

    RSS·Powered by Inblog