2026/08/08

오늘의 이야기

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 조합이 가장 일반적입니다. 운영 환경에서는 보안과 성능을 고려해 제한적으로 사용하는 것이 좋습니다.





댓글 없음:

댓글 쓰기

오늘의 이야기

#스하리1000명프로젝트, ¿Perdido en Corea? Incluso si no hablas coreano, esta aplicación te ayuda a moverte fácilmente. Simplemente hable su idiom...