본문 바로가기
SpringBoot

[SpringBoot] 필터, 인터셉터 호출 흐름, 적용 방법

by 오렌지마끼야또 2024. 5. 20.
728x90
반응형

 

 

 

 

필터 - 서블릿이 제공하는 기능

인터셉터 - 스프링이 제공하는 기능

 

웹과 관련된 공통 관심사항을 처리함

적용되는 순서와 범위, 사용방법이 다름

인터셉터가 더 편리하고 다양한 기능을 제공함

 

 

 

필터

 

필터 제한
HTTP 요청 -> WAS -> 필터 -> 디스패쳐 서블릿 -> 컨트롤러 //로그인 사용자
HTTP 요청 -> WAS -> 필터(적절하지 않은 요청이라 판단, 서블릿 호출X) //비 로그인 사용자

 

 

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

필터는 체인으로 구성되는데, 중간에 필터를 자유롭게 추가할 수 있다. 예를 들어서 로그를 남기는 필터를 먼저 적용하
고, 그 다음에 로그인 여부를 체크하는 필터를 만들 수 있다.

 

 

필터 인터페이스를 구현하고 등록하면 서블릿 컨테이너가 필터를 싱글톤 객체로 생성하고, 관리한다.
 - init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다.
 - doFilter(): 고객의 요청이 올 때 마다 해당 메서드가 호출된다. 필터의 로직을 구현하면 된다.
 - destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.

 

@Slf4j
public class MyFilter implements Filter {

    @Override // Filter 인터페이스를 보면 default로 되어 있어서 구현하진 않아도 됨
    public void init(FinterConfig filterConfig) throws ServletException {
        log.info("필터 초기화");
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException {
    
        // ServletRequest request는 HTTP 요청이 아닌 것까지 고려해서 만든 인터페이스
        // HTTP를 사용하려면 HttpServletRequest로 다운케스팅
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String requestURI = httpRequest.getRequestURI();
        
        chain.doFilter(request, response); // 다음 필터 호출. 없으면 서블릿 호출.
    
    }
    
    @Override // Filter 인터페이스를 보면 default로 되어 있어서 구현하진 않아도 됨
    public void destroy() {
        log.info("필터 종료");
    }
}

 

 

필터를 쓸 수 있게 등록해줘야 함

@Configuration
public class WebConfig {

    @Bean // 스프링 빈으로 등록해줘야 함. 스프링부트가 WAS를 실행할때 필터를 같이 넣어서 실행함
    public FilterRegistrationBean myFilter() {
    
        new FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new MyFilter());
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.addUrlPatterns("/*"); // 모든 요청에 대해서 필터 동작
        
        return filterRegistrationBean;
    }
}

 

 

 

 

 

 

 

인터셉터


스프링 인터셉터 흐름
HTTP 요청 -> WAS -> 필터 -> 디스패쳐 서블릿 -> 인터셉터1 -> 인터셉터2 -> 컨트롤러

 

 

HandlerInterceptor 인터페이스 구현하면 됨

 

preHandle : 컨트롤러 호출 전 (무조건 호출)

postHandle : 컨트롤러 호출 후 (에러나면 미호출)

afterCompletion : http 요청 완료 후(viewResolver 호출, view 랜더링 후) (무조건 호출)

 

 

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

 

@Slf4j
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    
        // 인터셉터는 HttpServletRequest를 바로 쓸 수 있음
        String requestURI = request.getRequestURI();
        
        return true; // false면 컨트롤러 호출도 안되고 종료
    }
    
    
    @Override
    public void postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    
        // modelAndView 확인 가능
        log.info("postHandler [{}]", modelAndView);
    }
    
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    
        // 에러 발생시 확인 가능
        if (ex != null) log.error("afterCompletion error!", ex)
    }

}

 

 

필터와 마찬가지로 등록해줘야 함

아까 config 파일에 추가

@Configuration          // 추가
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        
        registry.addInterceptor(new MyInterceptor())
                .order(1)
                .addPathPatterns("/**") // 모든 요청에 대해 인터셉터 동작
                .excludePathPatterns("/css/**", "/*.ico", "/error"); // 그 중에 해당 경로는 인터셉터 동작하지마
    }
    
    .
    .
    .
}

 

 

 

 

 

728x90
반응형

댓글