코딩 하는 가든

spring - 스프링에서의 필터 개념 및 예제 본문

Spring (boot)

spring - 스프링에서의 필터 개념 및 예제

가든리 2020. 8. 31. 21:58

블로그에서 사용한 소스코드는 https://github.com/97e57e/BLOG 에서 보실 수 있습니다.

 

Filter 란?

 

사실 필터는 스프링의 독자적인 기능이 아닌 자바 서블릿에서 제공하는 기능입니다. 스프링 프레임워크에서 필터로 인증 등 다양한 작업을 하는 데 사용하니 스프링 프레임워크에서의 필터에 대해 기록 해 보고자 합니다.

 

(출처:https://justforchangesake.wordpress.com/2014/05/07/spring-mvc-request-life-cycle/)

아마 스프링 필터와 연관지어 검색을 하면 많이 보는 그림 중 하나 일 것입니다.

 

위 그림은 스프링 프레임워크에서 요청에 대한 라이프 사이클을 나타낸 그림입니다.

 

스프링 프레임워크는 들어온 요청이 DispatcherServlet에 의해 컨트롤러에 매핑됩니다.

 

Filter는 요청이 DispatcherServlet에 의해 다뤄지기 전, 후에 동작합니다.

 

또한 Filter는 FilterChain(필터 체인)을 통해 여러 필터가 연쇄적으로 동작하게 할 수 있습니다.

 

Filter는 어디에 쓰이나?

필터는 주로 요청에 대한 인증, 권한 체크 등을 하는데에 쓰입니다. 구체적으로 들어온 요청이 DispatcherServlet에 전달되기 전에 헤더를 검사해 인증 토큰이 있는지 없는지, 올바른지 올바르지 않은지 등을 검사할 수 있을 것입니다.

 

저는 개인 게시판 프로젝트에서 SpringSecurity와 Jwt를 이용한 인증을 구현하는 데에 있어 Filter를 사용한 경험이 있습니다.

코드 : 보러 가기

 

97e57e/springboot-garden-board-api

spring boot rest api practice. Contribute to 97e57e/springboot-garden-board-api development by creating an account on GitHub.

github.com

 

 

Filter, 어떻게 사용 하나?

그럼 이제 스프링에서 필터를 어떻게 사용하는지 알아보겠습니다.

 

먼저 필터 클래스를 만들어야 하는데 필터 클래스는 servlet의 Filter 인터페이스를 구현하여 만들 수 있습니다.

public class FirstFilter implements Filter {}

 

필터 인터페이스는 3가지 메소드를 갖고 있는데 각각 다음과 같습니다.

  1. init() : 필터 가 생성될 때 수행되는 메소드
  2. doFilter() : Request, Response가 필터를 거칠 때 수행되는 메소드
  3. destroy() : 필터가 소멸될 때 수행되는 메소드

위의 세 가지 메소드를 아래와 같이 구현하면 필터가 됩니다.

@Slf4j
public class FirstFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("FirstFilter가 생성 됩니다.");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("==========First 필터 시작!==========");
        filterChain.doFilter(servletRequest, servletResponse);
        log.info("==========First 필터 종료!==========");
    }

    @Override
    public void destroy() {
        log.info("FirstFilter가 사라집니다.");
    }
}

 

필터 클래스를 만들면 이 필터를 Spring Bean으로 등록해야 합니다.

@Configuration
public class Config{

    @Bean
    public FilterRegistrationBean firstFilterRegister() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(new FirstFilter());
        return registrationBean;
    }
}

 

필터를 빈으로 등록하기 위해 스프링 설정에 FilterRegistrationBean을 이용해 직접 만든 필터를 등록할 수 있습니다.

 

우리는 방금 직접 만든 FirstFilter를 FilterRegistrationBean을 이용해 스프링의 필터로 등록했습니다.

 

등록된 필터가 어떻게 동작하는지 보기 위해 임시 컨트롤러를 하나 만들어 보겠습니다.

@Slf4j
@RestController
public class MyController {
    @GetMapping("/")
    public String hello() {
        log.info("Hello Garden!!!");
        return "Hello";
    }
}

 

위에 만든 컨트롤러의 hello 메소드가 수행되도록 요청을 한번 보내 보면!

 

스프링이 시작하면서 FirstFilter의 init 메소드가 수행된 것을 볼 수 있고 요청이 들어왔을 때, 필터 - 컨트롤러 - 필터로 예상한 대로 결과가 나왔음을 볼 수 있습니다.

 

그럼 두 개 이상의 필터가 있으면 어떻게 될지 한번 보겠습니다. FirstFilter와 비슷하게 SecondFilter 클래스를 만들었습니다.

@Slf4j
public class SecondFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("SecondFilter가 생성 됩니다.");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("==========Second 필터 시작!==========");
        filterChain.doFilter(servletRequest, servletResponse);
        log.info("==========Second 필터 종료!==========");
    }

    @Override
    public void destroy() {
        log.info("SecondFilter가 사라집니다.");
    }
}

 

이 SecondFilter 또한 빈으로 등록을 해줘야 합니다.

@Configuration
public class Config{

    @Bean
    public FilterRegistrationBean firstFilterRegister() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(new FirstFilter());
        registrationBean.setOrder(1);
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean secondFilterRegister() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(new SecondFilter());
        registrationBean.setOrder(2);
        return registrationBean;
    }
}

 

SecondFilet도 FirstFilter와 같은 방법을 통해 등록해주면 됩니다. 한 가지 추가된 것은 여러 개의 필터가 있을 때, 필터의 동작 순서를 FilterRegistrationBean의 setOrder() 메소드를 통해 결정할 수 있습니다.

 

FirstFilter가 처음으로, SecondFilter가 두 번째로 수행되게 설정을 하고 요청을 보내보겠습니다.

 

FirstFilter - SecondFilter - Controller - SecondFilter - FirstFilter 순으로 동작한 것을 볼 수 있습니다. 

 

이는 아까 위에서 보았던 그림을 다시 한번 보면 어떻게 동작하는지 확실하게 이해가 갈 것입니다.

 

지금까지 스프링 필터의 기본에 대해 알아보았습니다.