์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

getReader() has already been called for this request

๋ณธ๋ฌธ

์ƒํ™ฉ

2026-01-07T08:09:10.277+09:00 ERROR 5032 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.IllegalStateException: getReader() has already been called for this request] with root cause
java.lang.IllegalStateException: getReader() has already been called for this request


๋ฐœ์ƒ ์›์ธ

LoggingFilter ์—์„œ request body๋ฅผ ์ฝ์€ ํ›„ Spring ์ด ๋‹ค์‹œ ์ฝ์œผ๋ ค๊ณ  ํ•ด์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜ 

@Slf4j
@Component
public class LoggingFilter implements Filter{

  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {

    if(request instanceof HttpServletRequest httpServletRequest){
      String url = httpServletRequest.getRequestURI();
      String method = httpServletRequest.getMethod();
      String body = getRequestBody(httpServletRequest);

      log.info("Incoming Request: URL = {}, Method = {}, Body = {}", url, method, body);
    }

    chain.doFilter(request, response); // ๋‹ค์Œ ํ•„ํ„ฐ ๋˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์š”์ฒญ ์ „๋‹ฌ
  }

  private String getRequestBody(HttpServletRequest request){
    try (BufferedReader reader = request.getReader()) {
      return reader.lines().collect(Collectors.joining(System.lineSeparator()));
    } catch (IOException e){
      log.error("Failed to read request body", e);
      return "Unable to read request body";
    }
  }

}

 

HttpServletRequest์˜ InputStream/Reader๋Š” ํ•œ ๋ฒˆ๋งŒ ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค. 

1. LoggingFilter์—์„œ request.getReader()๋กœ body๋ฅผ ์ฝ์Œ

2. chain.doFilter()๋กœ ์š”์ฒญ ์ „๋‹ฌ

3. Spring์ด @RequestBody๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์‹œ body๋ฅผ ์ฝ์œผ๋ คํ•จ 

4. ์ด๋ฏธ ์ฝ์€ stream์„ ๋‹ค์‹œ ์ฝ์œผ๋ ค๊ณ  ํ•ด์„œ IllegalStateException ๋ฐœ์ƒ 

 


ํ•ด๊ฒฐ๋ฐฉ์•ˆ

  ContentCachingRequestWrapper ๋˜๋Š” ์ปค์Šคํ…€ Wrapper๋ฅผ ์‚ฌ์šฉํ•ด์„œ body๋ฅผ ์บ์‹ฑ

 

@Slf4j
@Component
public class LoggingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {

        if (request instanceof HttpServletRequest httpServletRequest) {
            ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(httpServletRequest);

            chain.doFilter(wrappedRequest, response);

            String url = wrappedRequest.getRequestURI();
            String method = wrappedRequest.getMethod();
            String body = new String(wrappedRequest.getContentAsByteArray(), StandardCharsets.UTF_8);

            log.info("Request: URL = {}, Method = {}, Body = {}", url, method, body);
        } else {
            chain.doFilter(request, response);
        }
    }
}

 

  1. ContentCachingRequestWrapper: Spring์ด ์ œ๊ณตํ•˜๋Š” ๋ž˜ํผ ํด๋ž˜์Šค๋กœ, request body๋ฅผ ๋‚ด๋ถ€์— ์บ์‹ฑ
  2. ๋กœ๊น… ์‹œ์  ๋ณ€๊ฒฝ: chain.doFilter() ํ›„์— ๋กœ๊น…ํ•ด์•ผ getContentAsByteArray()์— ๋ฐ์ดํ„ฐ๊ฐ€ ์ฑ„์›Œ์ง
  3. ๋ž˜ํ•‘๋œ request ์ „๋‹ฌ: chain.doFilter(wrappedRequest, response)๋กœ ๋ž˜ํ•‘๋œ ๊ฐ์ฒด ์ „๋‹ฌ

 

 


 

 

 

 

728x90

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ