TIL

[TIL] 버퍼를 읽는 것이란 무엇일까...?... Wrapper class를 써보았다.

봄봄로그 2023. 6. 20. 19:15

오늘 또 하나 배웠다...

사실 전 부터 배웠는데 오늘 좀 생각을 정리했다...? 여러 번 듣고 여러 번 책에서 본 내용인데도 제대로 개념을 이해 못했던 것이지....

전 부터 buffer를 한 번 사용해서 빈다 <- 라는 말을 자주 들었다. 이게 무슨 의미인지 이번에 코드를 짜보고 null이 찍히는 것을 보며 무엇인지 확실히 알게 되었다.

 

[ 순서 ] 

클라이언트단에서 요청이 들어온다.

-> spring Controller에 도달하기 전, filter에서 buffer를 한번 사용하고 빈다.-> Controller에 도달하는 response body가 없다-> Error : Required request body is missing

 

이럴 때 wrapper 를 사용하는데, 내가 계속 사용했던 것은 ContentCachingResponseWrapper,
ContentCachingRequestWrapper
class이다.

당연하게 ContentCachingRequestWrapper 를 이용했는데 디버깅을 돌려보면 자꾸 캐싱이 되지 않았다. 

알고보니 이것은 dofilter를 하고 사용을 하고 났을 때.. 그 뒤에서 또 사용할 수 있게 만들어 주는 클래스라고 했다.

그러니까 dofilter를 하고 또 사용할 수 있게 cashing이 되는 것이다.

그런데 나는 이미 inputstream을 한번하고 dofilter를 했으니 cashing되지 않았던 것이다.

 

public class LoggingFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
        //custom해서 만든 request wrapper class
        CachingRequestWrapper cachingRequestWrapper = new CachingRequestWrapper((HttpServletRequest) request);
        ContentCachingResponseWrapper cachingResponseWrapper = new ContentCachingResponseWrapper((HttpServletResponse) response);

		// request body 읽어오기
        InputStream contentInputStream = cachingRequestWrapper.getInputStream();
        String requestBody = StreamUtils.copyToString(contentInputStream, StandardCharsets.UTF_8);
        Map<String,String> map = new ObjectMapper().readValue(requestBody, Map.class);
                
		//method, uri 등 필요한 값 가져올 때
        cachingRequestWrapper.getMethod(),
        cachingRequestWrapper.getRequestURI()

		// doFilter
        chain.doFilter(cachingRequestWrapper, cachingResponseWrapper);

        cachingResponseWrapper.copyBodyToResponse();
    }
}

이렇게 request wrapper class를 만들어주고 사용하면 doFilter이전에 버퍼가 비워져도 상관없다!