Tomcat과 Catalina
Tomcat은 Apache 재단에서 제공하는 Java 웹 애플리케이션 서버(WAS)다. 웹 서버 기능뿐만 아니라 Servlet/JSP 컨테이너, HTTP 커넥터, 클러스터링, JNDI 리소스 관리 등 다양한 기능을 포함한 전체 프레임워크를 의미한다.
Catalina는 Tomcat의 핵심 엔진으로, Servlet과 JSP를 실제로 실행하는 컨테이너다. Tomcat이 구동되면 Catalina 클래스(org.apache.catalina.startup.Bootstrap)가 JVM에서 시작되며, 웹 애플리케이션의 서블릿과 JSP를 관리한다.
Tomcat의 구성 요소
- Catalina: 서블릿/JSP 컨테이너
- Coyote: HTTP Connector, 요청/응답 처리
- Jasper: JSP Compiler, JSP → Servlet 변환
- Cluster: 세션 복제 관리
- Naming/JNDI: 리소스(DataSource 등) 관리
웹 애플리케이션 배포 구조
Tomcat에 웹 애플리케이션을 올릴 때는 대부분 WAR 파일을 사용한다. WAR 파일은 Catalina 엔진의 JVM 프로세스 안에서 실행된다. 각 웹 애플리케이션은 독립 JVM이 아니라 Catalina JVM 내부에서 동작하며, Catalina JVM의 힙을 공유한다.
요청 흐름
클라이언트 요청 → Coyote Connector(HTTP 요청 수신) → Catalina Engine(서블릿 매핑 및 실행) → Jasper(JSP를 Servlet으로 변환) → 웹 애플리케이션(실제 로직 수행)
주의사항
- WAR 파일 자체에는 JVM 옵션을 지정할 수 없다
- 모든 웹 애플리케이션은 Catalina JVM의
-Xmx,-Xms등 힙 설정을 공유한다 - 여러 웹 애플리케이션이 동시에 많은 메모리를 사용하면 힙 부족이 발생할 수 있다
Catalina 컴포넌트 계층 구조
Server → Service → Connector(Coyote) + Engine(Catalina) → Host → Context → Wrapper
Server
Tomcat 인스턴스 전체를 나타내는 최상위 컴포넌트다. 하나의 JVM에 하나의 Server가 존재하며, 여러 Service를 포함할 수 있다.
<Server port="8005" shutdown="SHUTDOWN">
<Service name="Catalina">
...
</Service>
</Server>
port="8005"는 shutdown 명령을 수신하는 포트다. 운영 환경에서는 보안을 위해 -1로 설정하여 비활성화하거나 방화벽으로 차단하는 것이 좋다.
Service
Connector와 Engine을 묶어주는 논리적 그룹이다. 하나의 Service는 여러 Connector를 가질 수 있지만, Engine은 하나만 가진다.
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1" />
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" />
<Connector port="8009" protocol="AJP/1.3" />
<Engine name="Catalina" defaultHost="localhost">
...
</Engine>
</Service>
Connector (Coyote)
클라이언트와의 네트워크 통신을 담당한다. HTTP 요청을 파싱하여 Request/Response 객체를 생성하고 Engine에 전달한다.
<Connector
port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
maxThreads="200"
minSpareThreads="10"
acceptCount="100"
maxConnections="8192"
URIEncoding="UTF-8"
/>
| 속성 | 설명 | 기본값 |
|---|---|---|
| maxThreads | 요청 처리 최대 스레드 수 | 200 |
| minSpareThreads | 유휴 상태로 유지할 최소 스레드 수 | 10 |
| acceptCount | maxThreads 초과 시 대기 큐 크기 | 100 |
| maxConnections | 동시 처리 가능한 최대 커넥션 수 | 8192 (NIO) |
| connectionTimeout | 커넥션 타임아웃 (ms) | 20000 |
실무에서 자주 하는 실수가 maxThreads만 늘리는 것이다. 동시 접속이 많은 환경이라면 maxConnections와 acceptCount도 함께 조정해야 한다.
Engine
Catalina의 핵심 엔진이다. Connector로부터 전달받은 요청을 적절한 Host로 라우팅한다.
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps" />
<Host name="api.example.com" appBase="api-webapps" />
</Engine>
defaultHost는 요청의 Host 헤더와 매칭되는 Host가 없을 때 사용할 기본 호스트를 지정한다.
Host
가상 호스트(Virtual Host)를 나타낸다. 하나의 Tomcat에서 여러 도메인을 서비스할 때 사용한다.
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Alias>www.example.com</Alias>
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
| 속성 | 설명 |
|---|---|
| appBase | 웹 애플리케이션이 위치할 디렉토리 |
| unpackWARs | WAR 파일 자동 압축 해제 여부 |
| autoDeploy | 런타임 중 자동 배포 활성화 여부 |
| deployOnStartup | 시작 시 자동 배포 여부 |
운영 환경에서는 autoDeploy="false"로 설정하는 것이 좋다. 의도치 않은 재배포를 방지하고 리소스 모니터링 오버헤드를 줄일 수 있다.
Context
하나의 웹 애플리케이션을 나타낸다. WAR 파일 또는 디렉토리 하나가 하나의 Context에 매핑된다.
<!-- conf/context.xml (전역 설정) -->
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Manager pathname="" /> <!-- 세션 persistence 비활성화 -->
<Resource name="jdbc/mydb"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@localhost:1521:orcl"
username="user"
password="pass"
maxTotal="20"
maxIdle="10"
maxWaitMillis="10000" />
</Context>
특정 애플리케이션에만 적용하려면 conf/Catalina/localhost/앱이름.xml 파일을 생성한다.
reloadable="true"로 설정하면 클래스 파일 변경 시 자동으로 Context를 리로드한다. 개발 환경에서는 편리하지만, 운영 환경에서는 반드시 false로 설정해야 한다.
Wrapper
서블릿 하나를 감싸는 컴포넌트다. 서블릿의 생명주기(init, service, destroy)를 관리한다. web.xml의 서블릿 매핑에 따라 자동 생성된다.
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
load-on-startup 값이 0 이상이면 Tomcat 시작 시 서블릿을 미리 초기화한다. 음수거나 지정하지 않으면 첫 요청 시 초기화된다.
설정 파일 구조
$CATALINA_HOME/
├── conf/
│ ├── server.xml # 서버 전역 설정 (Connector, Engine, Host)
│ ├── context.xml # Context 기본 설정 (모든 웹앱에 적용)
│ ├── web.xml # 서블릿 기본 설정 (모든 웹앱에 적용)
│ ├── tomcat-users.xml # Manager/Admin 사용자 인증 정보
│ ├── catalina.properties # 시스템 프로퍼티, 클래스로더 설정
│ ├── logging.properties # 로깅 설정
│ └── Catalina/localhost/ # 특정 앱의 Context 설정
├── webapps/ # 웹 애플리케이션 배포 디렉토리
├── logs/ # 로그 파일 디렉토리
├── temp/ # 임시 파일 디렉토리
└── work/ # JSP 컴파일 결과물 디렉토리
Context 설정 우선순위
conf/Catalina/호스트명/앱이름.xml(가장 높음)- 웹앱 내부의
META-INF/context.xml conf/context.xml(가장 낮음)
로그 구조
Catalina 로그
$CATALINA_HOME/logs/
├── catalina.out # 표준 출력/에러
├── catalina.2024-01-15.log # Catalina 엔진 로그 (일별 롤링)
├── localhost.2024-01-15.log # Host 레벨 로그
├── localhost_access_log.2024-01-15.txt # 접근 로그
└── host-manager.2024-01-15.log # Manager 앱 로그
catalina.out은 무한정 커질 수 있으므로 logrotate 설정을 권장한다:
# /etc/logrotate.d/tomcat
/opt/tomcat/logs/catalina.out {
copytruncate
daily
rotate 7
compress
missingok
size 100M
}
애플리케이션 로그
웹 애플리케이션 내부에서 Logback, Log4j2 등으로 설정한 로그는 별도로 관리된다.
JVM 옵션 설정
JVM 옵션은 $CATALINA_HOME/bin/setenv.sh에서 설정한다.
#!/bin/bash
# 메모리 설정
CATALINA_OPTS="$CATALINA_OPTS -Xms2g -Xmx2g"
CATALINA_OPTS="$CATALINA_OPTS -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
# GC 설정 (G1GC)
CATALINA_OPTS="$CATALINA_OPTS -XX:+UseG1GC"
CATALINA_OPTS="$CATALINA_OPTS -XX:MaxGCPauseMillis=200"
# GC 로깅 (Java 11+)
CATALINA_OPTS="$CATALINA_OPTS -Xlog:gc*:file=/opt/tomcat/logs/gc.log:time,uptime:filecount=5,filesize=100M"
# JMX 모니터링
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=9010"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=true"
# 힙 덤프 설정
CATALINA_OPTS="$CATALINA_OPTS -XX:+HeapDumpOnOutOfMemoryError"
CATALINA_OPTS="$CATALINA_OPTS -XX:HeapDumpPath=/opt/tomcat/logs/heapdump.hprof"
# 인코딩
CATALINA_OPTS="$CATALINA_OPTS -Dfile.encoding=UTF-8"
export CATALINA_OPTS
CATALINA_OPTS vs JAVA_OPTS
- CATALINA_OPTS: Tomcat 실행 시에만 적용
- JAVA_OPTS: shutdown 등 모든 Java 프로세스에 적용 (힙 튜닝에는 비권장)
실무 운영 팁
멀티 인스턴스 구성
하나의 Tomcat 설치본으로 여러 인스턴스를 실행할 수 있다.
/opt/tomcat/ # CATALINA_HOME (공유)
/var/tomcat/instance1/ # CATALINA_BASE (인스턴스 1)
/var/tomcat/instance2/ # CATALINA_BASE (인스턴스 2)
#!/bin/bash
export CATALINA_HOME=/opt/tomcat
export CATALINA_BASE=/var/tomcat/instance1
$CATALINA_HOME/bin/catalina.sh start
세션 관리
세션 클러스터링은 오버헤드가 크다. 가능하면 Redis 등 외부 세션 저장소를 사용하거나, Sticky Session + Session Persistence 조합을 권장한다.
모니터링 포인트
| 지표 | 확인 방법 | 주의 기준 |
|---|---|---|
| 스레드 풀 사용량 | JMX: Catalina:type=ThreadPool |
currentThreadsBusy > maxThreads * 0.8 |
| 힙 메모리 | JMX: java.lang:type=Memory |
지속적 증가 패턴 |
| GC 시간 | GC 로그 분석 | Full GC 빈도, STW 시간 |
| 요청 처리 시간 | Access Log 분석 | p99 응답시간 |
| 에러율 | 로그 분석 | 5xx 비율 |
마치며
Catalina의 계층적 구조(Engine → Host → Context → Wrapper)를 이해하면, 멀티 도메인 서비스, WAR 배포 전략, 성능 튜닝 등 다양한 운영 이슈에 체계적으로 대응할 수 있다. 특히 server.xml의 Connector 설정과 JVM 옵션은 서비스 특성에 맞게 반드시 튜닝해야 하며, 로그 관리와 모니터링 체계도 함께 갖추는 것이 중요하다.
'DEV > Web' 카테고리의 다른 글
| [HTTP] 상태 코드(Status Code) 설명 (11) | 2023.12.06 |
|---|