Today's

길을 나서지 않으면 그 길에서 만날 수 있는 사람을 만날 수 없다

갑을병정이야기

Tomcat 서버 요청 로그와 디버깅 방법

Billcorea 2026. 8. 8. 00:07

tomcat 을 활용하는 방법

Tomcat 서버 요청 로그와 디버깅 방법

1. 기본 로그 확인

Tomcat은 logs 디렉터리에 다양한 로그를 남깁니다. 요청 내역은 보통 Access Log에 기록됩니다.

  • Access 로그: localhost_access_log.YYYY-MM-DD.txt
  • Catalina 로그: 서버 동작 및 에러 관련 메시지
  • 실시간 모니터링: tail -f logs/localhost_access_log.*

2. 헤더와 바디까지 확인하기

Access Log만으로는 부족합니다. 요청의 HTTP HeaderBody Payload를 확인하려면 다음 방법을 사용합니다.

  • RequestDumperValve 설정
  • Filter 구현하여 HttpServletRequest에서 직접 읽기
  • 프록시 서버(Nginx, Apache)에서 로깅
  • 디버깅 툴 (Wireshark, Fiddler, Postman)

3. RequestDumperValve가 없을 때

대안으로는 Custom FilterRequestWrapper를 활용합니다.

Map<String, String[]> params = request.getParameterMap();
for (String key : params.keySet()) {
    System.out.println(key + " = " + Arrays.toString(params.get(key)));
}

4. HttpServletRequestWrapper 사용법

요청 바디를 캐싱하여 여러 번 읽을 수 있도록 만드는 클래스입니다.

public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
    private byte[] cachedBody;

    public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        InputStream requestInputStream = request.getInputStream();
        this.cachedBody = requestInputStream.readAllBytes(); // Java 9 이상
    }

    @Override
    public ServletInputStream getInputStream() {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedBody);
        return new ServletInputStream() {
            @Override
            public int read() {
                return byteArrayInputStream.read();
            }
            @Override
            public boolean isFinished() {
                return byteArrayInputStream.available() == 0;
            }
            @Override
            public boolean isReady() { return true; }
            @Override
            public void setReadListener(ReadListener readListener) {}
        };
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
}

5. JSON 요청 로깅 필터 예시

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

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        CachedBodyHttpServletRequest wrappedRequest = new CachedBodyHttpServletRequest(httpRequest);

        // Content-Type 확인
        System.out.println("Content-Type: " + httpRequest.getContentType());

        // 요청 바디 출력
        String body = wrappedRequest.getReader().lines().collect(Collectors.joining("\n"));
        System.out.println("Request Body: " + body);

        // 파라미터 출력
        Map<String, String[]> params = wrappedRequest.getParameterMap();
        params.forEach((key, value) -> System.out.println(key + " = " + Arrays.toString(value)));

        chain.doFilter(wrappedRequest, response);
    }
}

6. 버전 관련 참고

  • InputStream.readAllBytes(): Java 9 이상에서 사용 가능
  • ReadListener: Servlet 3.1 (Java EE 7, Tomcat 8.0 이상)부터 지원

7. 필터 적용 문제 해결

필터가 적용되지 않는 경우는 보통 등록 문제입니다.

  • web.xml<filter><filter-mapping> 확인
  • Spring Boot에서는 FilterRegistrationBean으로 등록
  • URL 매핑: /*로 지정해야 전체 요청에 적용
  • chain.doFilter() 호출 누락 여부 확인

마무리

Tomcat에서 요청 파라미터와 바디를 디버깅하려면 RequestWrapper + LoggingFilter 조합이 가장 일반적입니다. 운영 환경에서는 보안과 성능을 고려해 제한적으로 사용하는 것이 좋습니다.

반응형