본문 바로가기
개발자 일지/Spring

필터와 인터셉터 차이, 개념, 예제

by 네빌링 2024. 9. 20.
반응형

스프링 개발시 자주 사용되는 필터와 인터셉터의 차이와 개념을 알아보려고 합니다. 둘다 비슷한 용도에 비슷하게 작동하기 때문에 헷깔릴 수 있는 개념이기 때문에 정리해보려고 합니다.

 

 

목차


 

1. 필터 개념, 예제

 

필터(Filter)는 서블릿 컨테이너에서 동작하는 자바 기술로, 요청 및 응답을 가로채서 공통의 로직을 미리 처리할 때 사용합니다.  보통 로깅, 인증 등에 많이 사용됩니다. 필터는 javax.servlet 패키지에 있는 라이브러리입니다.

 

스프링 개발시에도 많이 사용하는데 스프링 컨테이너의 문지기 역할을 하는 디스패처 서블릿(DispatcherServlet)으로 요청이 가기 전에 필터가 호출됩니다.

 

참고로 필터는 최초 1번 생성됩니다. 서블릿 컨테이너 기술이기 때문에 서블릿 컨테이너 생성 시점에 1회 호출됩니다.

 

필터를 구현하기 위해서 우선 javax.servlet.Filter 인터페이스를 구현합니다. 해당 인터페이스는 init(), doFilter(), destroy() 메서드를 포함하고 있습니다.

 

아래는 예제코드입니다.

 

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
public class LoggingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    	log.info("LoggingFilter init");
        //서블릿 컨테이너 생성시 1회 호출. 미리 설정 정보를 로딩하는 등 작업을 여기서 처리.
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
		
        try {
            // 요청 처리 전 로직
            log.info("Request URL: {}", httpRequest.getRequestURI());

            // 다음 필터 또는 서블릿으로 요청 전달
            chain.doFilter(request, response);

            // 응답 처리 후 로직
            log.info("Response Status: {}", httpResponse.getStatus());
        } catch (Exception e) {
			//적절한 예외 처리
		}
    }

    @Override
    public void destroy() {
    	log.info("LoggingFilter destroy");
        // 필터 종료 시 처리 코드
    }
}

 

그리고 web.xml 파일에 필터를 등록합니다. 이후 요청을 보내면 doFilter가 작동합니다.

 

<filter>
    <filter-name>LoggingFilter</filter-name>
    <filter-class>com.example.LoggingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>LoggingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

 

2. 인터셉터 개념, 예제

 

인터셉터(Interceptor)는 스프링 기술로 org.springframework.web.servlet.handler 패키지를 사용합니다. 그리고 인터페이스명은 HandlerInterceptor이며 보통 인터셉터라고 부릅니다.

 

필터처럼 요청을 처리하기 전, 후 작업을 지원합니다. 다만 인터셉터는 스프링 컨테이너 내부에서 작동하며 디스패처서블릿이 컨트롤러에 요청을 전달하기 전에 작동됩니다.

 

사용하기 위해서는 HandlerInterceptor를 구현해야 합니다. 해당 인터페이스에는 preHandle(), postHandle(), afterCompletion() 메서드가 정의되어 있어서 해당 메서드들을 오버라이드 하여 사용해야 합니다.

 

아래 예제코드입니다.

 

import org.springframework.web.servlet.HandlerInterceptor;

@Slf4j
public class LoggingInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();
        String method = request.getMethod();
        // 요청 처리 전에 수행할 작업
        log.info("LoggingInterceptor preHandle - Request URI: {}, Method: {}", uri, method);
        
        
        return true; // true를 반환시 다음 인터셉터 또는 컨트롤러 진행
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 요청 처리 후 수행할 작업
        log.info("LoggingInterceptor postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 요청 처리가 완료된 후 수행할 작업
        log.info("LoggingInterceptor afterCompletion");
        
        if (ex != null) {
        	log.error("Request completed error", ex);
        }
        
        
    }
}

 

그리고 인터셉터를 등록하는 설정을 해야 하는데 여러가지 방법이 있지만 여기서는 스프링 자바 설정을 이용하여 구현하였습니다. 아래와 같습니다.

 

 

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggingInterceptor())
                .addPathPatterns("/**")  // 모든 경로에 인터셉터 적용
                .excludePathPatterns("/login", "/resources/**"); // 특정 경로 제외
    }
}

 

위 설정 코드에서 registry는 메서드 체이닝 기술로 인터셉터 적용을 어떻게 할지 정의할 수 있습니다.

 

3. 필터와 인터셉터 차이

 

자바의 필터와 스프링의 인터셉터 모두 요청을 처리하기 전에 로깅, 인증 등 처리를 하는 용도로 사용합니다. 어떤 차이가 있을까요?

 

아래에 정리해봤습니다.

 

  필터 인터셉터
패키지 javax.servlet org.springframework.web.servlet.handler 
작동 위치 서블릿 컨테이너 스프링 컨테이너
작동 순서 스프링 컨테이너의 디스패처 서블릿에 요청 전달하기 전 Filter 동작 디스패처 서블릿이 요청을 컨트롤러에 넘겨주기 전, 후 동작
기타 FilterChain의 chain.doFilter()를 이용해서 필터를 연계해서 사용 가능 preHandle() 호출시 return true가 반환되어야 동작

 

그럼에도 용도에 대한 차이가 있을 것 같아서 고민을 해보고 찾아봤는데, 보통 필터는 스프링에 종속된 기술이 아닌만큼 일반적인 작업에 적합하고 인터셉터는 MVC 요청 처리 흐름에 맞는 처리에 적합하다고 합니다.


지금까지 필터와 인터셉터에 대해 간단하게 살펴봤습니다. 또 비슷한 것 같은 느낌의 AOP도 추후에 같이 비교 포스팅 해보려고 합니다.

 

감사합니다!

반응형