Akashic Records

Spring Boot Filter 사용법 본문

Spring.io

Spring Boot Filter 사용법

Andrew's Akashic Records 2023. 4. 15. 20:36
728x90

Spring Framework Web에서는 다양한 종류의 필터를 사용할 수 있습니다. 이 필터들은 HTTP 요청을 처리하기 전에 전처리를 수행하거나, 응답을 처리하기 전에 후처리를 수행하는데 사용됩니다. 아래에서 대표적인 필터들에 대해 설명하고, 각 필터의 사용 예시를 제공하겠습니다.

javax.servlet.Filter:
기본적인 서블릿 필터입니다. 요청 및 응답을 처리하기 전후에 로직을 실행할 수 있습니다. 이 필터를 구현하는 방법은 다음과 같습니다.

import javax.servlet.*;
import java.io.IOException;

public class MyServletFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 필터 초기화 작업
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 요청 전처리 작업

        chain.doFilter(request, response); // 필터 체인을 계속 실행

        // 응답 후처리 작업
    }

    @Override
    public void destroy() {
        // 필터 종료 시 작업
    }
}


org.springframework.web.filter.GenericFilterBean:
스프링에서 제공하는 추상 필터 클래스로, 스프링 빈에 대한 통합 및 설정 관리 기능을 제공합니다. 이를 상속하여 필터를 구현할 수 있습니다.

import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.*;
import java.io.IOException;

public class MySpringFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 요청 전처리 작업

        chain.doFilter(request, response); // 필터 체인을 계속 실행

        // 응답 후처리 작업
    }
}


org.springframework.web.filter.OncePerRequestFilter:
이 추상 클래스는 각 요청에 대해 한 번만 실행되는 필터를 구현하는 데 사용됩니다. 이를 상속하여 필터를 구현할 수 있습니다.

import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyOncePerRequestFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // 요청 전처리 작업

        filterChain.doFilter(request, response); // 필터 체인을 계속 실행

        // 응답 후처리 작업
    }
}

 

필터를 작성한 후에는 Spring Boot 프로젝트에 등록해야 합니다. 아래 예제는 FilterConfig 클래스를 사용하여 필터를 빈(Bean)으로 등록하는 방법을 보여줍니다.

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<MyServletFilter> myServletFilter() {
        FilterRegistrationBean<MyServletFilter> registrationBean = new FilterRegistrationBean<>();

        registrationBean.setFilter(new MyServletFilter());
        registrationBean.addUrlPatterns("/*"); // 모든 경로에 대해 필터 적용

        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean<MySpringFilter> mySpringFilter() {
        FilterRegistrationBean<MySpringFilter> registrationBean = new FilterRegistrationBean<>();

        registrationBean.setFilter(new MySpringFilter());
        registrationBean.addUrlPatterns("/*"); // 모든 경로에 대해 필터 적용

        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean<MyOncePerRequestFilter> myOncePerRequestFilter() {
        FilterRegistrationBean<MyOncePerRequestFilter> registrationBean = new FilterRegistrationBean<>();

        registrationBean.setFilter(new MyOncePerRequestFilter());
        registrationBean.addUrlPatterns("/*"); // 모든 경로에 대해 필터 적용

        return registrationBean;
    }
}


위 코드에서는 세 가지 필터를 각각 빈으로 등록하고 있습니다. 각 필터를 등록할 때 FilterRegistrationBean 인스턴스를 생성하고, setFilter() 메서드를 사용하여 필터 객체를 설정합니다. 그리고 addUrlPatterns() 메서드를 사용하여 필터가 적용되는 URL 패턴을 지정합니다.

이제 작성한 필터들이 각각 Spring Boot 프로젝트에 등록되었으며, 해당 URL 패턴에 대한 요청이 들어올 때 실행됩니다.

필터를 사용하면 다양한 목적으로 요청 및 응답을 처리할 수 있습니다. 예를 들어, 인증, 권한 검사, 로깅, CORS 처리 등의 기능을 구현할 수 있습니다. 필터를 통해 전처리 및 후처리를 적용하여 웹 애플리케이션의 보안 및 성능을 향상시킬 수 있습니다.

필터의 사용 사례를 몇 가지 추가로 제공하겠습니다.

인증 및 권한 검사:

사용자 인증과 관련된 로직을 필터로 구현할 수 있습니다. 예를 들어, 사용자의 인증 토큰이 유효한지 검사하고, 해당 사용자에게 요청한 리소스에 대한 접근 권한이 있는지 확인할 수 있습니다.

import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String authToken = request.getHeader("Authorization");

        if (isValidToken(authToken)) {
            // 인증 토큰이 유효한 경우 필터 체인을 계속 실행
            filterChain.doFilter(request, response);
        } else {
            // 인증 토큰이 유효하지 않은 경우 401 Unauthorized 응답
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
        }
    }

    private boolean isValidToken(String token) {
        // 토큰 유효성 검사 로직 구현
        return true; // 예제를 위해 항상 true를 반환
    }
}


CORS 처리:

Cross-Origin Resource Sharing (CORS) 관련 헤더를 추가하여 클라이언트 사이드에서 다른 도메인의 리소스를 요청할 수 있도록 할 수 있습니다.

import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CorsFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Max-Age", "3600");

        // Preflight 요청 처리
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            // 실제 요청 처리
            filterChain.doFilter(request, response);
        }
    }
}


이러한 필터들은 웹 애플리케이션에 다양한 기능을 제공할 수 있습니다. 필요한 로직에 따라 커스텀 필터를 구현하여 웹 애플리케이션의 보안, 성능 및 기능을 개선할 수 있습니다. 필터의 실행 순서를 조절하려면 FilterRegistrationBean의 setOrder() 메서드를 사용하여 순서를 지정할 수 있습니다. 작은 값이 먼저 실행 됩니다. 예를 들어, 두 개의 필터가 있고 순서를 지정하려면 다음과 같이 FilterConfig 클래스에서 setOrder() 메서드를 사용할 수 있습니다.

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<AuthenticationFilter> authenticationFilter() {
        FilterRegistrationBean<AuthenticationFilter> registrationBean = new FilterRegistrationBean<>();

        registrationBean.setFilter(new AuthenticationFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 가장 높은 우선 순위로 실행

        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();

        registrationBean.setFilter(new CorsFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE + 1); // AuthenticationFilter 다음으로 실행

        return registrationBean;
    }
}


위 코드에서 AuthenticationFilter의 실행 순서를 가장 높은 우선 순위로 설정하고, CorsFilter는 AuthenticationFilter 다음으로 실행되도록 설정하였습니다. 필터의 실행 순서를 조절하면 요청 처리에 필요한 순서대로 필터를 적용할 수 있습니다.

필터 외에도 Spring에서는 HandlerInterceptor를 사용하여 요청을 처리하기 전후에 로직을 실행할 수 있습니다. 필터와 비슷하지만, HandlerInterceptor는 Spring의 컨트롤러 메서드 실행 전후와 완료 시점에 로직을 추가할 수 있습니다. 이를 사용하면, 필터보다 세밀한 제어가 가능합니다.

필터와 인터셉터를 함께 사용하면, 웹 애플리케이션에서 요청 및 응답 처리에 대한 고급 제어가 가능합니다. 적절한 기능을 구현하여 웹 애플리케이션의 보안, 성능 및 기능을 향상시킬 수 있습니다.




728x90
Comments