[Tomcat] 버전 업그레이드 과정에서의 트러블슈팅 회고

DEV/TroubleShooting

[Tomcat] 버전 업그레이드 과정에서의 트러블슈팅 회고

BI3A 2026. 5. 28. 17:49

반응형

안되는 이유는 모르겠고 되는 이유는 더더욱 모르겠을 때


환경

  • WAS: Apache Tomcat 9.0.71 → 9.0.118
  • Framework: Spring Boot (WAR 배포)
  • ORM: MyBatis
  • OS: Windows
  • 실행 방식: Windows 서비스 등록

문제 1. MyBatis typeHandler 패키지 스캔 오류

증상

Caused by: java.io.IOException: Failed to parse config resource: class path resource [mybatis-config.xml]
...
Caused by: java.lang.IllegalArgumentException: 
리소스 경로 [/WEB-INF/classes/com/icis/ireo/db/type/IREOCLOBTypeHandler.class/龕봅\u0000\u0000\u00004\u0000r]
이(가) [null](으)로 정규화되어 있는데, 이는 유효하지 않습니다.

원인

mybatis-config.xml에서 typeHandler를 패키지 스캔 방식으로 등록하고 있었음.

<typeHandlers>
    <package name="com.icis.ireo.db.type" />
</typeHandlers>

MyBatis DefaultVFS가 패키지 스캔 시 .class 파일 바이너리 데이터가 경로 문자열에 섞여 비정상 경로가 생성됨. Tomcat StandardRoot.validate()가 이를 차단하면서 오류 발생.

StandardRoot.validate()의 경로 null 체크는 Tomcat 8.0.x부터 존재했고, 이 충돌은 특정 버전이 아닌 구조적으로 존재하는 문제임.

해결

<package> 스캔 제거 후 typeHandler 직접 명시.

<!-- Before -->
<typeHandlers>
    <package name="com.icis.ireo.db.type" />
</typeHandlers>

<!-- After -->
<typeHandlers>
    <typeHandler handler="com.icis.ireo.db.type.IREOLongTypeHandler"
                 jdbcType="LONGVARCHAR" javaType="java.lang.String"/>
    <typeHandler handler="com.icis.ireo.db.type.IREOCLOBTypeHandler"
                 jdbcType="CLOB" javaType="java.lang.Object"/>
    <typeHandler handler="com.icis.ireo.db.type.IREONCLOBTypeHandler"
                 jdbcType="NCLOB" javaType="java.lang.Object"/>
    <typeHandler handler="com.icis.ireo.db.type.IREODateTypeHandler"
                 jdbcType="DATE" javaType="java.util.Date"/>
</typeHandlers>

패키지 내 typeHandler 누락 시 런타임 타입 매핑 오류 발생하므로 전부 명시할 것.

대안

vfsImpl을 JBoss6VFS로 교체해서 우회 가능.

<settings>
    <setting name="vfsImpl" value="org.apache.ibatis.io.JBoss6VFS"/>
</settings>

문제 2. stdout 로그 인코딩 깨짐

증상

[INFO ][EmbeddedMariaDB] Ű ? db/schema_basel2.sql
[INFO ][EmbeddedMariaDB] ũ Ʈ Ϸ : db/schema_basel2.sql

원인

Windows 서비스로 실행 시 setenv.bat이 읽히지 않음. Tomcat을 서비스로 등록하면 Procrun(tomcat9.exe) 이 JVM을 직접 구동하므로 setenv.bat의 JVM 옵션이 무시됨.

해결

{TOMCAT_HOME}/bin/tomcat9w.exe 실행 → Java 탭Java Options에 추가 후 서비스 재시작.

-Dfile.encoding=UTF-8

참고. Windows vs Linux Tomcat 로그 구조 차이

Linux (startup.sh)

catalina.sh 내부에서 stdout을 catalina.out으로 리다이렉트함.

>> "$CATALINA_OUT" 2>&1 &

Tomcat 내부 로그 + 앱 로그(System.out, slf4j ConsoleAppender) 전부 catalina.out 하나에 찍힘.

Windows 서비스 (Procrun)

Procrun이 stdout/stderr를 분리해서 씀.

catalina.log         → Tomcat 컨테이너 자체 로그
tomcat9-stdout.log   → 앱 콘솔 출력 (System.out, slf4j ConsoleAppender)
tomcat9-stderr.log   → 에러 및 스택트레이스

Windows startup.bat

stdout이 콘솔 창으로 출력됨. catalina.log에는 Tomcat 내부 로그만 찍힘.

요약

항목 Linux startup.sh Windows startup.bat Windows 서비스
실행 주체 java 직접 java 직접 Procrun(tomcat9.exe)
앱 로그 행선지 catalina.out 콘솔 창 tomcat9-stdout.log
setenv 적용 ❌ (tomcat9w.exe에서 설정)
콘솔 창

운영 환경에서는 slf4j FileAppender로 별도 파일에 직접 쓰도록 구성하는 게 나음. stdout 로그에 의존하지 말 것.

반응형