일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 스프링 배치
- JPA
- 스프링 부트
- 스프링
- 컨테이너
- 도커
- 스프링 시큐리티
- 데이터베이스
- 백엔드
- CI/CD
- HTTP
- spring batch
- 가상화
- Spring
- Spring Security
- Java
- mysql
- spring cloud
- ORM
- 영속성 컨텍스트
- 자바
- 배포
- computer science
- spring boot
- web server
- vm
- virtualization
- CS
- 웹 서버
- Container
- Today
- Total
개발 일기
[Spring Boot] 필터(Filter)와 인터셉터(Interceptor) 본문
공부하게된 계기
스프링 시큐리티를 공부할때 인증, 인가 그리고 XSS, CSRF와 같은 공격을 방어해주는 기능을 필터를 통해 처리한다고 했는데 이 필터가 무엇인지 잘 알지 못했고 대충 검색해보니 필터와 함께 인터셉터라는 개념이 함께 나와서 정리해보게 됐다.
필터는 서블릿, 인터셉터는 스프링이 제공한다.
필터와 인터셉터 개념을 도입한 이유
그렇다면 왜 필터라는 개념을 도입했을까? 바로 공통 관심사 때문이다.
예를 들어서 로그인을 한 사람만 상품을 등록할 수 있어야 하고 상품 수정을 할때 해당 상품 등록자만 그 권한을 줘야 한다. 이럴때는 상품 관리의 모든 컨트롤러 로직에 공통으로 로그인 여부를 확인하면 된다. 예를들면 상품 등록 컨트롤러와 상품 관리 컨트롤러 등 모든 상품 관련 컨트롤러 마다 공통적으로 각각 로그인 여부 확인 로직을 추가해주는 것이다.
이러한 방식의 문제는 당연히 코드의 중복이다. 그렇기 때문에 만약 로그인 여부 확인 로직이 변경된다면? 해당 코드가 들어간 모든 컨트롤러를 찾아가 하나하나 수정해줘야 한다. 이러한 공통 관심사는 AOP로 처리해도 가능은하다. 그러나 웹과 관련된 공통 관심사는 서블릿 필터 또는 스프링 인터셉터를 활용하는 것이 좋다. 이때 웹과 관련된 공통관심사라하면은 특정 URL로 요청이 들어오면 어떻게 처리할지 이런 것들을 말한다. 그래서 HTTP 헤더와 URL 정보 등이 필요한데 그러한 웹과 관련된 정보들을 제공해주는 HttpServletRequest를 이 서블릿 필터나 스프링 인터셉터에서 지원하기 때문이다.
Servlet Filter - 서블릿 필터
필터라는 개념은 서블릿이 제공하는 것으로 수문장 같은 역할을 한다.
HTTP Request ➔ WAS ➔ Filter ➔ (Dispatcher) Servlet ➔ Controller 이러한 흐름으로 요청이 처리되는데 이를 통해 알 수 있듯이 Filter를 거친 후에 서블릿으로 들어간다.
Filter는 특정 URL을 지정하여 특정 요청에 어떠한 작업을 하도록 할 수 있다. 이러한 특성을 통해 필터 제한이 가능하다. Filter 까지 들어온 요청을 확인해서 만약 로그인되지 않은 유저 라면 Dispatcher Servlet으로 요청이 들어가는 것을 막을 수 있다.
또한 필터는 체인으로 구성 가능하다. HTTP Request ➔ WAS ➔ Filter1 ➔ Filter1 ➔ Filter3 ➔ Filter4 ➔ (Dispatcher) Servlet ➔ Controller과 같이 여러개의 필터를 나열하여 순서대로 펄터가 적용되도록 구성 가능하다.
- init() & destroy()
: 필터 초기화 및 소멸 메소드로 서블릿 컨테이너가 생성될때 필터를 싱글톤 객체로 생성하여 관리하다가 서블릿 컨테이너가 종료될때 같이 소멸시킨다. - doFilter()
: 고객의 요청이 올 때 마다 해당 메소드가 호출된다. 즉, doFilter 메소드는 URL 패턴에 맞는 모든 HTTP 요청이 디스패처 서블릿으로 전달되기 전에 웹 컨테이너에 의해 실행되는 메소드이다. doFilter의 파라미터로는 FilterChain이 있는데, FilterChain의 doFilter 통해 다음 대상으로 요청을 전달하게 된다. chain.doFilter() 전/후에 우리가 필요한 처리 과정을 넣어줌으로써 원하는 처리를 진행할 수 있다.
Spring Interceptor - 스프링 인터셉터
Spring Interceptor도 Servlet Filter와 마찬가지로 웹과 관련된 공통 관심 사항을 효과적으로 처리할 수 있는 기능이다. 적용되는 순서와 범위 그리고 방법이 다를 뿐이다.
Interceptor는 Spring MVC가 지원한다.
기존에 필터의 흐름은 HTTP Request ➔ WAS ➔ Filter ➔ (Dispatcher) Servlet ➔ Controller 다음과 같았는데 Spring Interceptor를 포함한 흐름은 HTTP Request ➔ WAS ➔ Filter ➔ (Dispatcher) Servlet ➔ Interceptor ➔ Controller 다음과 같다. 디스페처 서블릿과 컨트롤러 사이에서 컨트롤러 호출 직전에 작동한다.
인터셉터에서도 적절하지 않은 요청이라면 Controller로 요청을 보내지 않고 중단할 수 있고 인터셉터 또한 체인으로 구성되기 때문에 다음과 같이 구성 가능하다. HTTP Request ➔ WAS ➔ Filter ➔ (Dispatcher) Servlet ➔ Interceptor1 ➔ Interceptor2 ➔ Interceptor3 ➔ Controller
사용하려면 HandlerInterceptor 인터페이스를 구현하면 된다.
필터의 경우 doFilter() 하나로 처리하지만 인터셉터는 위에서 보는 것과 같이 컨트롤러 호출 전(preHandle()), 컨트롤러 호출 후(postHandle()), 요청 완료 이후 - 뷰 렌더링 이후(afterCompletion()) 이렇게 3가지 단계로 세분화 되어 있다.
위 그림과 같은 순서로 동작하게 된다.
postHandle()과 afterCompletion()의 차이점은 postHandle()은 핸들러 어댑터가 실행된 후이고 afterCompletion()은 뷰가 렌더링 된 이후이며 또 하나의 차이점은 만약 컨트롤러로 들어가서 에러로 인한 예외가 터졌을때 postHandle()은 실행되지 않고 afterCompletion()만 실행된다.
'Back-End > Spring' 카테고리의 다른 글
[Spring Security] SecurityFilterChain 내부 구조 (0) | 2024.05.02 |
---|---|
[Spring Security] 스프링 시큐리티 - Filter, DelegatingFilterProxy, FilterChainProxy, SecurityFilterChain (1) | 2024.05.02 |
[Spring Boot] CGI, Servlet, Front Controller, Spring Web MVC (0) | 2024.05.02 |
[Spring Boot] Spring MVC - 구조 이해 (0) | 2024.05.02 |
[Spring Boot] Spring 3대 특징(Spring 삼각형) 3 - 관점 지향 프로그래밍(AOP) (0) | 2024.03.13 |