홈 › 웹 서버 › 03 / 8

Tomcat 인스턴스와 JVM 옵션

섹션 7진행 0 / 8

2. 핵심 원리

2.1 CATALINA_HOME 과 CATALINA_BASE

CATALINA_HOME 은 Tomcat 을 압축 해제한 실행 파일 위치(bin·lib)이고, CATALINA_BASE 는 인스턴스별 설정과 로그가 있는 위치입니다. 지정하지 않으면 두 값이 같아 인스턴스가 하나뿐인 구성이 됩니다.

구분 CATALINA_HOME CATALINA_BASE
위치 $BASE/tomcat/current $BASE/tomcat-inst/<이름>
내용 bin·lib(공유 실행 파일) conf·logs·temp·webapps·work
인스턴스 수 서버당 1개 서버당 여러 개 가능
업그레이드 current 링크만 전환 손대지 않음

2.2 인스턴스 폴더 구조

CATALINA_BASE 는 다섯 폴더로 이뤄집니다. 없는 폴더가 있으면 Tomcat 이 기동 시 자동으로 만들지만, 미리 만들어 권한을 통제하는 편이 안전합니다.

폴더 용도
conf server.xml·context.xml·web.xml
logs catalina.out·access 로그
temp 임시 파일·catalina.pid
webapps war·배포된 앱
work JSP 컴파일 산출물

2.3 로그를 심볼릭 링크로 중앙화

인스턴스가 늘어나면 로그가 tomcat-inst/<이름>/logs 아래 흩어져 백업 스크립트가 복잡해집니다. $BASE/logs/<이름> 을 실제 위치로 두고 인스턴스의 logs 를 그리로 심볼릭 링크(symlink)하면 로그 백업 경로가 한 곳으로 모입니다.

catalina.out 백업은 logrotate 의 copytruncate 방식으로 압축·삭제합니다(리눅스 운영 06 참조).

2.4 포트 겹침 피하기

한 서버에서 인스턴스를 여러 개 띄우면 server.xml 의 HTTP 포트와 종료 포트가 겹치지 않아야 합니다. 겹치면 두 번째 인스턴스가 기동 시 포트 바인딩에 실패합니다.

인스턴스 HTTP 포트 종료 포트
app1 8080 8005
app2 8180 8105
app3(추가 시) 8280 8205

2.5 server.xml 은 인스턴스마다 별도 파일

CATALINA_HOME 의 conf 는 손대지 않고, 각 CATALINA_BASE 의 conf/server.xml 을 인스턴스별로 관리합니다. Engine·Host 이름은 인스턴스끼리 같아도 되고, 앱을 구분하는 것은 포트와 appBase 경로입니다.

2.6 setenv.sh 는 CATALINA_BASE 기준으로 읽힌다

catalina.sh 는 시작할 때 $CATALINA_BASE/bin/setenv.sh 를 먼저 찾고, 없으면 $CATALINA_HOME/bin/setenv.sh 를 씁니다. 인스턴스마다 다른 JVM 옵션을 주려면 반드시 CATALINA_BASE 쪽에 파일을 둬야 합니다.

01-tomcat-install 레슨의 setenv.sh 는 CATALINA_HOME 공용 파일로 JAVA_HOME·CATALINA_PID 만 최소로 뒀습니다. 이번 레슨은 인스턴스별 setenv.sh 에 힙·GC 등 JVM 튜닝 옵션을 넣습니다.

2.7 힙 크기는 Xms=Xmx

-Xms(초기 힙)와 -Xmx(최대 힙)를 같게 두면 런타임 중 힙을 늘리고 줄이는 리사이즈가 없어져 지연이 줄어듭니다. 서버용 JVM 에서는 사실상 표준 설정입니다.

2.8 GC 옵션 명시

JDK 21 은 기본 GC 가 G1 이지만, -XX:+UseG1GC 를 명시하면 JDK 버전이 올라가 기본값이 바뀌어도 동작이 그대로 유지됩니다. 지연에 민감한 앱은 별도로 ZGC 등을 검토합니다.

2.9 시간대와 인코딩 시스템 프로퍼티

-Duser.timezone=Asia/Seoul, -Dfile.encoding=UTF-8 을 인스턴스마다 넣어둡니다. OS 로케일이 다른 이미지에서 옮겨와도 로그 시각과 한글 처리가 흔들리지 않습니다.

2.10 OOM 발생 시 힙 덤프

-XX:+HeapDumpOnOutOfMemoryError 와 -XX:HeapDumpPath=... 를 함께 지정하면 메모리 부족(OOM)이 터졌을 때 원인 분석용 덤프 파일이 남습니다. 경로를 지정하지 않으면 프로세스의 현재 작업 디렉터리에 떨어져 못 찾기 쉽습니다.

2.11 JNDI DataSource 와 context.xml

context.xml 에 Resource 를 선언하면 애플리케이션은 JDBC URL·비밀번호를 몰라도 JNDI 이름(java:comp/env/jdbc/AppDB)만으로 커넥션 풀을 얻습니다. 비밀번호를 평문으로 두지 않는 방법은 실무 확장 13 암호화를 참고합니다.

드라이버 jar 는 CATALINA_BASE/lib(인스턴스 전용)에 둡니다. CATALINA_HOME/lib(공용)에 두면 인스턴스마다 다른 드라이버 버전이 필요할 때 충돌합니다.

2.12 systemd 템플릿 유닛

[email protected] 는 %i 로 인스턴스 이름을 받는 템플릿 유닛입니다. systemctl enable --now tomcat@app1 처럼 인스턴스 이름을 붙여 기동하며, 인스턴스마다 유닛 파일을 복붙할 필요가 없습니다.