서블릿 vs 필터 - Hot-stock/backend GitHub Wiki
필터(Filter)
필터는 서블릿 컨테이너 단계에서 요청과 응답에 대해 전처리 및 후처리를 수행합니다. 서블릿이 실행되기 전후에 작동하며, **요청(Request)**과 응답(Response) 모두를 변경하거나 가로챌 수 있습니다.
특징:
- 다음 필터 필수 호출: 필터 체인은 연결된 순서대로 실행되며, 다음 필터를 호출하지 않으면 요청이 서블릿에 도달하지 않습니다.
- 요청 흐름:
클라이언트 요청 -> 필터1 -> 필터2 -> 서블릿 -> 응답 -> 필터2 -> 필터1 -> 클라이언트 응답
- 바꿔치기 가능: 요청과 응답 객체를 다른 것으로 교체할 수 있습니다.
장점:
- WAS 수준에서 필터링하므로 모든 요청과 응답을 전역적으로 처리할 수 있습니다.
- 특정 서블릿, JSP, 정적 리소스 등 모든 종류의 요청에 적용할 수 있습니다.
단점:
- 필터를 사용하면 예외가 발생한 경우 다시 WAS까지 돌아가야 하며, 중복된 필터 호출이 일어날 수 있습니다.
- 이를 해결하기 위해 ServletRequestType이 있지만 인터셉터처럼 정교하게 처리하기 어렵습니다.
인터셉터(Interceptor)
인터셉터는 스프링 프레임워크에서 제공하며, 주로 핸들러(컨트롤러) 전/후 처리에 사용됩니다. 필터보다 더 높은 추상화 수준에서 동작하며, 요청이 특정 컨트롤러와 매핑되었을 때 개입합니다.
특징:
- 핸들러 실행 전후 처리 및 완료 후 처리 지원:
- preHandle: 컨트롤러 실행 전에 호출됩니다.
- postHandle: 컨트롤러 실행 후, 뷰 렌더링 전에 호출됩니다.
- afterCompletion: 요청 처리가 끝난 후(뷰 렌더링 완료 후) 항상 호출됩니다.
- 예외 처리:
- 예외 발생 시 postHandle은 호출되지 않지만, afterCompletion은 항상 호출됩니다.
- PathPattern 지원: 특정 URL 패턴에 대해 인터셉터를 걸 수 있어 관심사 분리가 쉽습니다.
요청 흐름:
클라이언트 요청 -> preHandle -> 컨트롤러 -> postHandle -> 뷰 렌더링 -> afterCompletion
- 예외 발생 시:
preHandle -> (예외 발생) -> afterCompletion
장점:
- 정교한 처리 시점 제어가 가능하여, 요청-응답 흐름에 대한 세밀한 개입이 가능합니다.
- PathPattern을 사용해 특정 경로에만 적용할 수 있습니다.
단점:
- 필터와 달리 정적 리소스와 같은 서블릿 단의 요청을 직접 가로채지 못합니다.
- 필터와 인터셉터가 중첩되면 흐름 관리가 복잡해질 수 있습니다.
필터와 인터셉터의 처리 시점 비교
구분 | 필터(Filter) | 인터셉터(Interceptor) |
---|---|---|
처리 시점 | 서블릿 이전 / 이후 | 컨트롤러 이전 / 이후 |
적용 범위 | 모든 종류의 요청 (정적 리소스 포함) | 컨트롤러에 매핑된 요청 |
전후 처리 | 요청과 응답 모두 가로채기 가능 | 요청 전처리, 후처리, 완료 후 처리 세분화 가능 |
관심사 분리 | 전역적인 처리 (모든 서블릿에 일괄 적용) | 특정 경로별로 처리 가능 (PathPattern 사용) |
예외 처리 | 필터 체인 전체가 다시 호출될 수 있음 | afterCompletion으로 정리 가능 |
교체 가능 여부 | 요청 및 응답 객체 교체 가능 | 요청/응답 교체 불가 |
필터와 인터셉터의 단점 및 해결 방안
필터의 단점:
- 필터는 오류 발생 시 필터 체인을 모두 다시 통과해야 하는 불필요한 오버헤드가 발생할 수 있습니다.
- 개발자의 오류로 nextChain호출을 안하면 디스페쳐서블렛에 요청이 도달이 안됨
인터셉터의 단점:
- 정적 리소스에 대해서는 필터처럼 직접적인 개입이 어렵습니다.
- 필터와 인터셉터를 함께 사용할 경우, 요청 흐름 관리가 복잡해질 수 있습니다.
결론 및 선택 기준
- 필터는 모든 요청(정적 리소스 포함)에 대한 전역 처리가 필요할 때 유용합니다.
- 인터셉터는 컨트롤러와 비즈니스 로직에 가까운 위치에서 세밀한 처리가 필요할 때 사용합니다. 특정 경로에만 적용하고, 로직을 깔끔하게 분리하고자 할 때 유리합니다.
정리:
필터와 인터셉터는 처리 시점과 사용 목적이 다릅니다. 글로벌한 요청 처리가 필요하면 필터를, 세부적인 로직 분리와 경로별 처리가 필요하면 인터셉터를 사용하는 것이 좋습니다.