Http RequestBody 로깅처리하기
자바 진영에서 HttpServletRequest
에서 body
는 InputStream
에 저장되어 스프링 어플리케이션이 한번 바디를 읽고 나면 버퍼가 비워져 읽어 올 수가 없기 때문에 이를 읽기 위해서는 다음과 같은 방법을 사용할 수 있다.
HttpServletRequest Wrapping
가장 간단한 방법으로는 HttpServletRequest
를 랩핑하여 버퍼를 복제하는 방법이다. 특정 프레임워크에 종속되진 않지만 바디를 읽어오는데 번거로워 뭔가 코드가 깔끔한 느낌이 나지는 않는다.
다음과 같이 Wrapper를 통해 InputStream을 카피해두면 된다.
java
1 | public CustomHttpServletRequestWrapper(HttpServletRequest request) throws IOException { |
버퍼가 스프링 프레임워크에 읽히기 전에 먼저 읽어 버퍼를 복제해 한 후에 복제한 버퍼에서 바디를 읽으면 된다. 읽어올땐 다음과 같이 사용한다.
java
1 |
|
- 장점
- 특정 프레임워크에 종속되지 않는 자바진영 코드로만 개발
- 모든 요청에 대한 버퍼를 복사해야 하는 추가 IO 발생
단점
- 바디를 불러오기 위한 코드가 깔끔하지 못함
ref
RequestBodyAdvice
RequestBody를 읽고 난 후에 Advice를 통해서 읽은 요청 본문을 RequestScope
빈에 저장해둔 후에 꺼내다 쓰는 방식이다.
java
1 |
|
RequestBodyAdviceContextHelper
빈에 바디를 저장했으므로 필요한 곳에서 꺼내 사용하면 된다.
java
1 |
|
- 장점
- 스프링진영에서 공식적으로 지원하는 기능들을 사용한
RequestBody
추적
- 스프링진영에서 공식적으로 지원하는 기능들을 사용한
단점
- 모든 RequestBody에 대해서 Advice가 동작하는 추가 비용 발생
ref
RequestBodyHijacking
AOP
를 통해 RequestBody
의 로깅이 필요한 곳에만 선별적으로 요청 본문을 가져와 사용한다.
java
1 |
|
이 또한 RequestScope
빈에 저장하므로 다음과 같이 필요에 꺼내 따라 사용할 수 있다.
java
1 |
|
- 장점
- 개발자가 의도한 영역에서만
RequestBody
에 대한 추적이 가능
- 개발자가 의도한 영역에서만
단점
reflection
을 통한method signature parameter
와pointcut argument
의class type
을 비교하므로 요청 모델 외에 동일한 클래스 타입이 메소드 시그니처에 있는 경우 의도하지 않은대로 동작 할 여지가 있음- 하지만 해당 케이스가 현 HTTP 스펙상 지원하지 않고 매우 드물기 때문에 문제가 없다고 판단됨
ref
결론
필요와 상황에 따라 각기 다른 방법을 사용해 RequestBody
를 로깅할 수 있다.
개발한 소스코드는 여기에서 확인할 수 있습니다.