Tomcat과 Catalina

DEV/Web

Tomcat과 Catalina

BI3A 2025. 11. 12. 17:38

반응형

Tomcat & Catalina

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만 늘리는 것이다. 동시 접속이 많은 환경이라면 maxConnectionsacceptCount도 함께 조정해야 한다.

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 &quot;%r&quot; %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 설정 우선순위

  1. conf/Catalina/호스트명/앱이름.xml (가장 높음)
  2. 웹앱 내부의 META-INF/context.xml
  3. 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