Controller에서 Request Body를 읽지 못하는 문제 해결 - Interceptor를 통한 RequestBody 로그 시도인 경우

2025. 4. 6. 14:56·IT 기술/Spring boot

Controller에서 Request Body를 읽지 못하는 문제 해결

Interceptor를 통한 RequestBody 로깅 시 발생하는 문제와 해결 방법

Spring Boot 프로젝트를 진행하면서 Interceptor를 사용해 요청과 응답을 로깅하는 경우가 많습니다. 특히, API 요청 시 Request Body를 로그에 남기는 것은 디버깅과 모니터링에 큰 도움이 됩니다. 그러나 때로는 Interceptor에서 Request Body를 읽으려다 Controller에서 다시 Request Body를 읽지 못하는 문제가 발생합니다. 이 글에서는 이러한 현상의 원인과 효과적인 해결 방법을 알아보겠습니다.

문제의 원인

Spring MVC에서 Request Body를 읽는 방법인 HttpServletRequest의 InputStream은 한 번만 읽을 수 있습니다. Interceptor나 Filter에서 이미 InputStream을 읽었다면, Controller에서는 다시 읽을 수 없는 상태가 되어 버립니다. 이로 인해 Controller에서 @RequestBody로 데이터를 바인딩하려고 하면 빈 값이나 에러가 발생합니다.

문제 상황 예시

Interceptor에서 다음과 같은 코드로 Request Body를 로깅했다고 가정해 봅시다.

@Component
public class RequestBodyLoggingInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        String body = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
        log.info("Request Body: {}", body);
        return true;
    }
}

위의 코드를 사용하면 InputStream이 비워져, Controller에서 RequestBody 데이터를 읽지 못하게 됩니다.

해결 방법: ContentCachingRequestWrapper 사용

이 문제를 해결하는 가장 효과적인 방법은 Spring에서 제공하는 ContentCachingRequestWrapper를 사용하는 것입니다. 이 클래스는 요청 내용을 캐시하고 여러 번 읽을 수 있도록 도와줍니다.

해결 예시 코드

다음과 같이 Interceptor 대신 Filter를 사용하여 ContentCachingRequestWrapper로 Request를 래핑합니다.

@Component
public class RequestBodyLoggingFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
        filterChain.doFilter(wrappedRequest, response);

        String requestBody = new String(wrappedRequest.getContentAsByteArray(), StandardCharsets.UTF_8);
        log.info("Request Body: {}", requestBody);
    }
}

이렇게 하면 요청이 Controller에 도달하기 전에 이미 읽힌 InputStream이 캐시되어 다시 읽을 수 있는 상태로 전달됩니다.

주의사항

  • Filter의 순서가 중요합니다. ContentCachingRequestWrapper를 적용하는 Filter는 Request Body를 읽는 다른 Filter보다 앞에 위치해야 합니다.
  • 로깅은 성능에 영향을 줄 수 있으므로, 프로덕션 환경에서는 로깅 레벨을 잘 관리하거나 일부 요청에 대해서만 로깅을 수행하도록 설정하는 것이 좋습니다.
  • HttpServletRequestWrapper를 활용한 로깅 방법도 있습니다.

정리

Interceptor에서 Request Body를 로깅할 때 발생하는 문제는 InputStream의 일회성 특성 때문입니다. ContentCachingRequestWrapper를 사용하면 Request Body를 여러 번 읽을 수 있게 하여 문제를 간단히 해결할 수 있습니다. 이 방법을 활용하면 보다 효율적으로 API 요청을 로깅하고 디버깅할 수 있습니다.

'IT 기술 > Spring boot' 카테고리의 다른 글

Spring vs Spring Boot: 차이점과 선택 기준  (1) 2025.03.18
Spring Boot에서 Security 적용 시 H2 Console(/h2-console) 접근 불가 문제 해결 방법  (0) 2025.03.05
Connection Pool과 @Transactional: 효율적인 데이터베이스 관리를 위한 핵심 개념  (0) 2025.02.25
/gradlew bootRun은 어떻게 동작하는가?  (1) 2025.02.22
'IT 기술/Spring boot' 카테고리의 다른 글
  • Spring vs Spring Boot: 차이점과 선택 기준
  • Spring Boot에서 Security 적용 시 H2 Console(/h2-console) 접근 불가 문제 해결 방법
  • Connection Pool과 @Transactional: 효율적인 데이터베이스 관리를 위한 핵심 개념
  • /gradlew bootRun은 어떻게 동작하는가?
시남
시남
개발하는 사람입니다. 하고 싶은 것들 사이에서 매번 선택하는 삶을 살고 있습니다.
  • 시남
    Refactor Life like code.
    시남
  • 전체
    오늘
    어제
    • 분류 전체보기 (26)
      • IT 기술 (19)
        • Spring boot (5)
        • Claude (1)
        • AWS (5)
        • n8n (2)
      • 이야기 (3)
      • 독서 (0)
      • 개발일기 (4)
        • 1D3Q (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    git@github.com
    root@localhost
    contentcachingrequestwrapper
    사이드프로젝트
    docker
    AWS
    n8n실습
    1인개발
    reverse tunnel
    n8n공부방법
    도커 토큰 503
    claudecode
    인프런n8n
    도커 미러
    gemini
    Apify
    java
    개발일지
    도커 503
    회고
    n8n자동화예제
    리버스 터널링
    1인기획
    자동화공부
    Ai
    claude marketplace
    기획
    1D3Q
    Spring
    Spring Boot
  • 최근 댓글

  • 최근 글

  • hELLO By정상우.v4.10.4 관리
시남
Controller에서 Request Body를 읽지 못하는 문제 해결 - Interceptor를 통한 RequestBody 로그 시도인 경우
상단으로

티스토리툴바