spring
spring OncePerRequestFilter 란

spring OncePerRequestFilter 란

하나의 요청에 한번의 호출을 보장하는 Filter

OncePerRequestFilter.doFilter 에는 호출된적 있는지 판별하는 flag 가 들어가있다 일반적으로 OncePerRequestFilter 를 상속받고 doFilterInternal 를 구현해서 사용한다

앞단 Filter -> MyFilter.doFilter -> MyFilter.doFilterInternal 이렇게 동작한다

왜 한번만 호출되어야하나?

요청이 왔고 요청 처리중 exception이 발생했다고 치면

  1. 요청
  2. 필터체인
  3. 요청 처리중에 exception 발생
  4. 서블릿 컨테이너까지 에러가 전파됨
  5. 서블릿이 에러 감지
  6. /error 페이지로 포워딩 시작
  7. 다시 필터체인
  8. /error 페이지 도착
  9. error 페이지 또는 error json(기본 등록된 BasicErrorController가 처리 ) 반환

자 위 단계를 보면 필터체인이 앞쪽에 한번 뒷쪽에 한번 총 두번 들어간다

그렇다면 한번의 요청에 동일 필터가 두번 동작할 수 있다는 것인데

예를들어 요청 한번에 요청 Log 를 남기는 RequestLoggingFilter 가 있다고 치자

요청이 한번 발생했는데 RequestLoggingFilter 가 두번 동작하면 불필요한 로그가 추가로 남게된다

이럴때 OncePerRequestFilter 를 상속받고 doFilterInternal 를 구현하면 두번 호출되지 않는다

한번만 실행된다면서 콜스택에 여러번 찍히는 이유는?

java 콜스택은 그 코드가 정의되어있는 class 를 기준 으로 찍는다

예를들어 MyFilterOncePerRequestFilter 를 상속 받았을때

필자는 처음에

  1. MyFilter.doFilter ~~~
  2. MyFilter.doFilterInternal ~~~

이렇게 찍힐줄 알았지만

콜스택을 보면

  1. OncePerRequestFilter.doFilter ~~~
  2. MyFilter.doFilterInternal ~~~

이렇게 찍힌다

MyFilter 에서 doFilter 는 오버라이드 하지 않았고

doFilterInternal 는 추상 함수니 이에 대한 구현은 MyFilter 에 존재하기 때문에

doFilter 호출부는 OncePerRequestFilter.doFilter ~~~ 와 같이 찍히는게 맞다