Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
제이온

한국어

[Spring] Filter, Interceptor, Argument Resolver란?

  • 작성 언어: 한국어
  • 기준국가: 모든 국가country-flag

durumis AI가 요약한 글

  • 필터는 디스패처 서블릿에 요청이 전달되기 전후에 URL 패턴에 맞는 모든 요청에 대해 부가 작업을 처리할 수 있는 기능을 제공한다.
  • 인터셉터는 디스패처 서블릿이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공한다.
  • Argument Resolver는 요청에 들어온 값으로부터 원하는 객체를 만들어내는 역할을 한다.

필터(Filter)란?

필터는 J2EE 표준 스펙 기능으로 디스패처 서블릿(Dispatcher Servlet)에 요청이 전달되기 전/후에 url 패턴에 맞는 모든 요청에 대해 부가 작업을 처리할 수 있는 기능을 제공한다. 즉, 스프링 컨테이너가 아닌 톰캣과 같은 웹 컨테이너에 의해 관리가 되므로 디스패처 서블릿으로 가기 전에 요청을 처리하는 것이다.


Image


필터(Filter) 구현

필터를 추가하기 위해서는 javax.servlet의 Filter 인터페이스를 구현해야 하며, 이는 다음 3가지 메소드를 가지고 있다.


  • init 메소드
    • 필터 객체를 초기화하고 서비스에 추가하기 위한 메소드이다. 웹 컨테이너가 1회 init 메소드를 호출하여 필터 객체를 초기화하면, 이후 요청들은 doFilter() 메소드를 통해 처리된다.
  • doFilter 메소드
    • url-pattern에 맞는 모든 HTTP 요청이 디스패처 서블릿으로 전달되기 전에 웹 컨테이너에 의해 실행되고, 디스패처 서블릿에서 클라이언트에게 HTTP 응답이 가기 전에 웹 컨테이너에 의해 실행되는 메소드이다.
      doFilter()의 파라미터로는 FilterChain이 있는데, FilterChain의 doFilter() 를 통해 다음 대상으로 요청을 전달하게 된다. chain.doFilter() 전/후에 우리가 필요한 처리 과정을 넣어줌으로써 원하는 처리를 진행할 수 있다.
  • destory 메소드
    • 필터 객체를 서비스에서 제거하고 사용하는 자원을 반환하기 위한 메소드이다. 이는 웹 컨테이너에 의해 1번 호출되며, 이후에는 이제 doFilter() 에 의해 처리되지 않는다.


예제 코드 - Servlet 스펙

@WebFilter("/*")
public class dolphagoFilter implements Filter {

    @Override
      public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
      public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain filterChain) throws IOException, ServletException {
        //여기에 전처리
        request.setCharacterEncoding("UTF-8");
        System.out.println("doFilter() 전....");

        filterChain.doFilter(request, response);

        //여기에 후처리
        System.out.println("doFilter() 후....");
      }

    @Override
      public void destroy() {    }
}


예제 코드 - @Component

@Order(1)
@Component
public class CustomFilter 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() { }
}


  • @Component: Filter를 스프링 빈으로 등록할 수 있다.
  • @Order: 필터가 여러 개일 경우 순서를 정할 수 있다.
  • 서블릿 스펙에 해당하는 필터를 이렇게 스프링 빈으로 등록하게 되면, 스프링 스펙에 해당하는 다른 빈들을 이용할 수 있다.


예제 코드 - @Configuration

@Configuration
public class CustomRegistrationBean {

    @Bean
    public FilterRegistrationBean<CustomFilter> customFilterBean() {
        FilterRegistrationBean<CustomFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new CustomFilter());
        registration.setOrder(1);
        registration.addUrlPatterns("/api/*");
        return registration;
    }
}

만약 특정 URI에만 필터를 동작하게 하려면 FilterRegistrationBean을 사용하여 필터를 스프링 빈으로 등록할 수 있다.


필터(Filter) 용도

주로 요청 파라미터 자체의 검증 및 처리를 담당한다.


  • 보안 관련 공통 작업
    • 필터는 웹 컨테이너에서 동작하기 때문에 보안 검사(XSS, CSRF 방어 등)를 하여 올바른 요청이 아닐 경우 차단할 수 있다. 스프링 컨테이너까지 요청이 전달되지 못하고 차단되므로 안정성을 더욱 높일 수 있다.
  • 모든 요청에 대한 로깅
  • 이미지/데이터 압축 및 문자열 인코딩
    • 필터는 이미지나 데이터의 압축이나 문자열 인코딩과 같이 웹 애플리케이션에 전반적으로 사용되는 기능을 구현하였다.
  • ServletRequest 커스터마이징
    • HttpServletRequest는 Body의 내용을 한 번만 읽을 수 있다. 따라서 Filter나 Interceptor에서는 Body를 읽을 수 없다. Body를 로깅하기 위해 커스텀한 ServletRequest를 생성할 수 있다.


인터셉터(Interceptor)

인터셉터(Interceptor)란?

인터셉터(Interceptor)는 J2EE 표준 스펙인 필터(Filter)와 달리 스프링이 제공하는 기술로서, 디스패처 서블릿이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공한다. 즉, 웹 컨테이너에서 동작하는 필터와 달리 인터셉터는 스프링 컨텍스트에서 동작을 하는 것이다.


디스패처 서블릿은 핸들러 매핑을 통해 적절한 컨트롤러를 찾도록 요청하는데, 그 결과로 실행 체인(HandlerExecutionChain)을 돌려준다. 그래서 이 실행 체인은 1개 이상의 인터셉터가 등록되어 있다면, 순차적으로 인터셉터를 거쳐 컨트롤러가 실행되도록 하고, 인터셉터가 없다면 바로 컨트롤러를 실행한다.


인터셉터(Interceptor) 구현

인터셉터를 추가하기 위해서는 org.springframework.web.servlet.HandlerInterceptor 인터페이스를 구현해야 하며, 이는 다음의 3가지 메소드를 가지고 있다.


  • preHandle 메소드
    • preHandle 메소드는 컨트롤러가 호출되기 전에 실행된다. 그렇기 때문에 컨트롤러 이전에 처리해야 하는 전처리 작업이나 요청 정보를 가공하거나 추가하는 경우에 사용할 수 있다.
    • preHandle 메소드의 3번째 파라미터인 handler 파라미터는 @RequestMapping이 붙은 메소드의 정보를 추상화한 객체이다.
    • preHandle 메소드의 반환 타입은 boolean인데, 반환값이 true이면 다음 단계로 진행이 되지만, false라면 작업을 중단하여 이후의 작업(다음 인터셉터 또는 컨트롤러)은 진행되지 않는다.
  • postHandle 메소드
    • postHandle 메소드는 컨트롤러를 호출된 후에 실행된다. 그렇기 때문에 컨트롤러 이후에 처리해야 하는 후처리 작업이 있을 때 사용할 수 있다.
  • afterCompletion 메소드
    • afterCompletion 메소드는 이름 그대로 모든 뷰에서 최종 결과를 생성하는 일을 포함해 모든 작업이 완료된 후에 실행된다.


예제 코드

@Component
public class CustomInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
        ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
        throws Exception {
    }
}

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomInterceptor());
        registry.addInterceptor(new LoggingInterceptor());
    }
}


  • 생성한 인터셉터를 빈으로 등록한다.
  • WebMvcConfigurer 인터페이스의 addInterceptors() 메소드에 생성한 인터셉터를 등록한다.
  • 인터셉터는 InterceptorRegistry에 등록한 순서대로 동작한다.


인터셉터(Interceptor) 용도

주로 서비스 로직을 활용하여 요청 정보 정합성 처리를 담당한다.


  • 인증/인가 등과 같은 공통 작업
    • 대표적인으로 인증이나 인가와 같이 클라이언트 요청과 관련된 작업들을 컨트롤러로 넘어가기 전에 검사할 수 있다.
  • API 호출에 대한 로깅
    • 전달 받는 HttpServletRequest, HttpServletResponse 객체를 통해 클라이언트의 정보를 기록할 수 있다.
  • Controller로 넘겨 주는 데이터 가공
    • 전달 받는 HttpServletRequest, HttpServletResponse 객체를 가공하여 컨트롤러에 넘겨줄 수 있다.
  • AOP 흉내
    • preHandle() 메소드의 3번째 파라미터인 HandlerMethod로 실행될 메소드의 시그니처 등 추가적인 정보를 파악해서 로직 실행 여부를 판단할 수 있다.


필터(Filter) vs 인터셉터(Interceptor)

  • 필터는 웹 컨텍스트에서 실행되고, 인터셉터는 스프링 컨텍스트에서 실행되므로 실행 시점이 다르다.
  • 필터는 디스패처 서블릿의 전후를 다룰 수 있고, 인터셉터는 컨트롤러의 전후를 다룰 수 있다.
  • 필터는 스프링과 무관하게 전역적으로 처리해야 하는 작업을 하거나, 입력으로 들어온 파라미터 그 자체에 대해 검증을 하거나, HttpServletRequest 대신에 ServletRequest를 이용하는 경우 사용하는 것이 좋다.
  • 인터셉터는 스프링 단으로 들어온 클라이언트의 요청과 관련되어 전역적으로 처리해야 하거나, 서비스 로직을 섞어야 할 때 사용하는 것이 좋다.
  • 인터셉터는 @ControllerAdvice와 @ExceptionHandler를 사용하여 예외 처리가 가능하지만, 필터는 이를 사용하여 예외 처리를 할 수 없다.
    • 필터는 주로 doFilter() 메소드 주변을 try~catch 구문으로 감싸서 그 시점에서 발생한 예외를 곧바로 핸들링한다.


Argument Resolver

Argument Resolver란?

Argument Resolver는 어떠한 요청이 컨트롤러에 들어왔을 때, 요청에 들어온 값으로부터 원하는 객체를 만들어 내는 일을 간접적으로 해줄 수 있다.


Argument Resolver 용도

예를 들어, JWT 토큰과 함께 요청이 들어왔다고 가정하자. 우리는 이 토큰이 유효한 토큰인지 검증을 거친 후에 토큰에 저장된 id를 꺼내 로그인 유저 객체로 만들어 내는 과정이 필요하다.

이러한 경우, Argument Resolver를 사용하지 않는다면, 토큰을 검증하고 로그인 유저 객체로 변환하는 과정을 모든 컨트롤러마다 구현해야 한다. 그러면 사용자 검증이 필요한 컨트롤러에 중복 코드가 생기고, 컨트롤러의 책임이 증가하게 된다. 이러한 문제를 Argument Resolver가 해결해 줄 수 있다.


Argument Resolver 구현

ArgumentResolver는 HandlerMethodArgumentResolver를 구현함으로써 사용할 수 있다. 그리고 이 인터페이스는 아래 두 메소드를 구현하도록 명시하고 있다.


boolean supportsParameter(MethodParameter parameter);

@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;


  • supportsParameter 메소드
    • ArgumentResolver가 실행되길 원하는 Parameter의 앞에 특정 어노테이션을 생성해 붙인다. supportsParameter() 메소드는 요청받은 메소드의 인자에 원하는 어노테이션이 붙어있는지 확인하고 원하는 어노테이션을 포함하고 있으면 true를 반환한다.
  • resolveArgument 메소드
    • supportsParameter에서 true를 받은 경우, 즉, 특정 어노테이션이 붙어있는 어느 메소드가 있는 경우 parameter가 원하는 형태로 정보를 바인딩하여 반환하는 메소드이다.


이렇게 ArgumentResolver를 사용했을 때 컨트롤러의 구현은 아래와 같다.


@GetMapping("/me")
public ResponseEntity<MemberResponse> findMemberOfMine(@AuthenticationPrincipal LoginMember loginMember) {
    MemberResponse memberResponse = memberService.findMember(loginMember.getId());
    return ResponseEntity.ok().body(memberResponse);
}


Argument Resolver와 인터셉터(Interceptor) 차이점

  • ArgumentResolver는 인터셉터 이후에 동작을 하며, 어떠한 요청이 컨트롤러에 들어왔을 때, 요청에 들어온 값으로부터 원하는 객체를 반환한다.
  • 반면, 인터셉터는 실제 컨트롤러가 실행되기 전에 요청을 가로채며, 특정 객체를 반환할 수 없다. 오직 boolean 혹은 void 반환 타입만 존재한다.


출처


예상 면접 질문 및 답변

필터란?

필터는 디스패처 서블릿에 요청이 전달되기 전/후에 url 패턴에 맞는 모든 요청에 대해 부가 작업을 처리할 수 있는 기능을 제공하며 서블릿 컨테이너 단에서 동작한다.


필터의 사용 시기는?

필터에서는 스프링과 무관하게 전역적으로 처리해야 하는 작업들을 처리할 수 있다. 혹은, 요청 파라미터를 중심으로 검증할 때 사용된다.

대표적으로 보안 관련 공통 작업, 모든 요청에 대한 로깅, 이미지/데이터 압축 및 문자열 인코딩, ServletRequest 커스터마이징 작업을 처리한다.


인터셉터란?

인터셉터는 디스패처 서블릿이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공하며, 즉, 스프링 컨테이너 단에서 동작한다.


인터셉터의 사용 시기는?

인터셉터는 클라이언트의 요청과 관련되어 전역적으로 처리해야 하는 작업들을 처리할 수 있고, 검증 시 서비스 로직을 호출할 때 주로 사용된다.

대표적으로 인증/인가 등과 같은 공통 작업, API 호출에 대한 로깅, Controller로 넘겨주는 데이터 가공 작업을 처리한다.


필터와 인터셉터의 차이는?

필터는 서블릿 컨테이너 단에서 실행되고 인터셉터는 스프링 컨테이너 단에서 실행된다.

필터는 디스패처 서블릿의 전후를 다룰 수 있고, 인터셉터는 컨트롤러의 전후를 다룰 수 있다.

따라서, 필터는 스프링과 무관하게 전역적으로 처리해야 하는 작업을 하는 것이 좋고, 인터셉터는 클라이언트의 요청과 관련되어 전역적으로 처리해야 하는 작업을 하는 것이 좋다.


Argument Resolver란?

ArgumentResolver는 어떠한 요청이 컨트롤러에 들어왔을 때, 요청에 들어온 값으로부터 원하는 객체를 만들어내는 일을 간접적으로 해준다.


Argument Resolver의 사용 시기는?

JWT 토큰과 함께 요청이 들어왔을 때, 유효한 토큰인지 검증을 거친 후에 토큰에 저장된 id를 꺼내 LoginMember라는 객체로 만들어내는 작업을 할 때 사용할 수 있다.


인터셉터와 Argument Resolver의 차이는?

ArgumentResolver는 어떠한 요청이 컨트롤러에 들어왔을 때, 요청에 들어온 값으로부터 원하는 객체를 반환한다. 반면에 인터셉터는 위 처럼 객체를 반환할 할 수가 없으며, 인터셉터가 실행된 후에 Argument Resolver가 실행된다.

제이온
제이온
제이온
[이펙티브 자바] 아이템 1. 생성자 대신 정적 팩터리 메서드를 고려하라정적 팩터리 메서드는 이름을 가지고 객체 생성을 제어할 수 있어 편리합니다. 인스턴스 생성 시 매번 새로 만들지 않고 기존 인스턴스를 반환할 수 있어 효율적입니다. 상속이 어렵다는 단점이 있지만, 불변 객체 생성에 적합합니다. JDBC와 같은 프레임워크에서 정적 팩터리 메서드를 활용하여 유연성과 확장성을 높입니다.

2024년 4월 27일

[Spring] @Async 사용 방법Spring의 @Async를 사용하면 동기 메서드를 간단히 비동기로 전환할 수 있습니다. 스레드 풀 설정으로 성능 향상도 가능하며, 비동기 결과를 Future, ListenableFuture, CompletableFuture로 받을 수 있습니다. @Async는 유지보수성이 높지만 AOP 제약이 있으므로 주의가 필요합니다.

2024년 4월 25일

[Java] Reflection 개념 및 사용 방법리플렉션은 클래스의 정보에 접근하고 동적으로 객체를 생성할 수 있게 해줍니다. 장점은 유연성이지만, 캡슐화를 저해하고 성능이 느려질 수 있습니다. 주로 프레임워크에서 사용되며, Spring의 Bean Factory와 같이 동적인 의존 관계 관리에 활용됩니다. 다만 필요한 경우가 아니라면 단순히 필드와 메서드를 호출하는 것이 더 나은 선택일 수 있습니다.

2024년 4월 25일

[비전공, 개발자로 살아남기] 14. 신입 개발자 자주 묻는 기술면접 내용 요약신입 개발자를 위한 기술면접 대비 가이드. 메모리 구조, 자료구조, RDBMS/NoSQL, 절차/객체지향, 알고리즘, 프로세스/스레드, 네트워크 프로토콜 등 면접에 자주 나오는 핵심 개념을 정리했습니다. 실무에 필요한 기술을 확실히 이해하고 실전 면접에 대비하세요.
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

2024년 4월 3일

Flitter 1.0.0 출시: D3를 대체할 svg 라이브러리데이터 시각화 라이브러리 Flitter가 제공하는 선언적 코드 작성과 고급 레이아웃 계산 기능으로, 개발자들이 쉽고 빠르게 차트와 다이어그램을 구현할 수 있습니다. SSR 지원 강화, 제스처 인식 기능 향상, z-index 위젯 추가 등의 새로운 기능과 성능 개선이 이뤄졌습니다.
Meursyphus
Meursyphus
Meursyphus
Meursyphus

2024년 5월 1일

[비전공, 개발자로 살아남기] 16. 신입 개발자 포트폴리오 작성 꿀팁비전공자도 개발자가 될 수 있다! 개발자 포트폴리오 작성 '핵심' 팁을 소개합니다. 프로젝트 경험 상세 설명, 담당 업무 명시, 기술적 구현 내용까지 보여주면 개발 실력을 효과적으로 어필할 수 있습니다. 이런 방식으로 포트폴리오를 작성하면 취업에 도움이 될 것입니다.
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

2024년 4월 3일

슬롯 필링(Slot-Filling)이란?슬롯 필링(Slot-Filling)은 챗봇이 질문에 답변하기 위해 필요한 정보를 모두 수집하는 과정입니다. 예를 들어 커피 주문 시 필수값인 음료 종류와 잔 수를 확인하는 것입니다. 필수값이 입력되지 않으면 계속해서 동일한 질문을 반복하게 됩니다. 슬롯 필링을 효과적으로 처리하기 위해서는 탈출 단어를 만들어 주는 등의 방법이 필요합니다.
꿈많은청년들
꿈많은청년들
슬롯 필링이라고 크게 쓰인 이미지
꿈많은청년들
꿈많은청년들

2024년 5월 13일

[Javascript] Object의 구조 (V8)JavaScript의 Object는 다양한 상황에 따라 구조가 변화하는 내부 구조를 가지고 있습니다. 처음에는 빠른 구조체 형태의 'Fast 모드'로 동작하지만, 새로운 키가 추가되거나 복잡한 동작이 필요하면 'Dictionary 모드'의 해시테이블로 전환됩니다. 이를 통해 상황에 맞는 최적화를 꾀하고 있습니다. 이러한 Object의 내부 구조와 작동 원리에 대해 자세히 설명하고 있습니다.
곽경직
곽경직
곽경직
곽경직

2024년 3월 18일

[SI 개발자 이야기] 09. SI 프로젝트 투입 이후 본격적인 개발의 시작SI 개발자의 프로젝트 투입 이후 경험을 소개합니다. 고객사의 요구사항 변경이 잦아 유연한 설계가 필요하며, 효율성보다는 빨리 구현하는 것이 우선됩니다. 고객의 무지와 지나친 요구에 대처하는 방법도 공유합니다. SI 프로젝트에 필요한 자세와 유념할 사항을 210자 내로 정리했습니다.
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

2024년 4월 18일