본문 바로가기
IT 트렌드/알아두면 좋은 IT 상식

Tomcat server.xml 설정 완벽 가이드: 운영/DevOps 실무 베스트 프랙티스

by KBerry 2025. 8. 26.

목차

     

    Tomcat은 전세계적으로 널리 사용되는 Java 웹 애플리케이션 서버로, 설정 파일 server.xml을 통해 주요 동작을 제어합니다. 그러나 Tomcat server.xml 설정은 처음 접하는 운영자나 DevOps 엔지니어에게 다소 복잡하게 느껴질 수 있습니다. 이 가이드에서는 Tomcat server.xml 구조를 쉽게 이해할 수 있도록 요소별 비유와 함께 설명하고, appBase vs docBase 차이, autoDeploy, deployOnStartup, unpackWARs 의미, Context XML을 이용한 명시적 배포 방법 등 핵심 설정을 다룹니다. 또한 운영 환경과 개발 환경에서의 설정 차이, 다양한 배포 방식별 디렉터리 구조와 전략 (WAR 자동 배포, 외부 디렉터리/WAR, 병렬 배포), 그리고 중복 배포를 피하는 Best Practice를 상세히 소개합니다. 이 글을 통해 Tomcat 실무 배포 전략을 익혀 안정적인 운영 환경을 구축하고, 개발 단계에서의 편의성도 높여보세요.

     

    Tomcat Server.xml 설정
    Tomcat Server.xml 설정

    Tomcat server.xml 구조 개요: 주요 요소와 역할 (쉽게 이해하기)

    Tomcat의 server.xml은 계층적 구조로 이루어져 있으며, 각 계층은 톰캣 서버의 한 부분을 담당합니다. 이를 건물에 비유하면 이해하기 쉬운데, Server는 건물 전체, Service는 건물 내 특정 서비스 단위, Connector는 건물의 출입구(문), Engine은 들어온 사람을 각 층으로 안내하는 안내 데스크, Host는 건물의 한 층(세입자 공간), Context는 각 층에 입주한 개별 가게나 사무실(웹 애플리케이션)이라고 볼 수 있습니다. 이제 각각의 요소를 살펴보겠습니다:

    • Server – Tomcat 전체 프로세스를 나타내며, 건물 전체에 해당합니다. 이 최상위 요소에는 <Service>들을 포함하고, 서버 포트(예: 종료 포트 8005 등)와 종료 명령(예: SHUTDOWN)이 정의됩니다.
    • Service – 여러 Connector(통신 포트)와 하나의 Engine을 묶는 서비스 단위입니다. 하나의 Tomcat Server 내에 여러 Service를 둘 수도 있지만, 일반적으로 하나의 Service(Catalina)만 사용합니다.
    • Connector – 클라이언트와 통신하는 연결 포트를 나타냅니다. 예를 들어 <Connector port="8080" protocol="HTTP/1.1" />는 8080 포트로 들어오는 HTTP 요청을 처리합니다. (건물의 현관문 역할로, 특정 포트를 통해 외부 요청을 받아들이는 입구입니다.)
    • Engine – Service 내에 단 하나 존재하며, 받은 요청을 적절한 Host로 라우팅하는 엔진입니다. 여러 가상호스트(도메인) 중 어디로 보낼지 결정하는 역할로, 건물 로비의 안내 데스크에 비유할 수 있습니다.
    • Host – 하나의 가상 호스트(Virtual Host)를 뜻하며, 도메인 단위 컨테이너입니다. 예를 들어 <Host name="localhost" ...>는 localhost 도메인을 처리하는 호스트입니다. 하나의 Host 안에 여러 웹앱(Context)을 가질 수 있으며, 건물의 한 층이나 한 세입자 공간으로 생각하면 됩니다.
    • Context – 개별 웹 애플리케이션(Context)을 의미합니다. 컨텍스트 경로(context path)와 실제 파일 경로(docBase)로 정의되며, Host 내부에 여러 Context가 배치될 수 있습니다. 예를 들어 context path가 /myapp이면 URL상 http://<host>:<port>/myapp으로 접근하는 하나의 웹 애플리케이션을 말합니다. (건물 층 안에 입주한 개별 매장/서비스로 볼 수 있습니다.)

    위 계층 구조를 요약하면, Server 아래 하나의 Service, 그 안에 다수의 Connector(포트)와 하나의 Engine, Engine 아래 여러 Host(도메인), 각 Host 아래 여러 Context(웹앱)들이 위치하는 트리 구조입니다. 이러한 구조를 이해하면 server.xml 파일을 읽고 편집하는 데 큰 도움이 됩니다.

    핵심 설정 항목에 대한 개념 설명

    Tomcat server.xml에는 배포와 관련된 중요한 설정들이 Host 및 Context 레벨에서 제공됩니다. 실무에서 자주 다루는 appBase vs docBase, autoDeploy, deployOnStartup, unpackWARs 옵션, 그리고 Context XML을 통한 배포 방법을 하나씩 설명하겠습니다.

    appBase와 docBase의 차이와 용도

    Tomcat의 Host 설정에서 appBase와 Context 설정에 나오는 docBase는 헷갈리기 쉬운 용어입니다. 간단히 말해:

    • appBase: 해당 Host(가상호스트)가 웹앱을 찾는 기본 디렉터리를 가리킵니다. 기본값은 $CATALINA_BASE/webapps로, 여기에 WAR 파일이나 디렉토리를 놓으면 자동으로 배치됩니다. 여러 Host를 사용하는 경우 Host별로 appBase를 다르게 지정해 도메인마다 별도 앱 디렉토리를 사용할 수 있습니다 (예: appBase="webapps.example" 등).
    • docBase: 개별 Context(웹앱)의 실제 위치를 가리킵니다. WAR 파일 자체이거나, 전개된 웹앱 디렉토리 경로가 될 수 있습니다. docBase는 절대경로로 지정할 수도 있고, Host의 appBase를 기준으로 한 상대경로로 지정할 수도 있습니다. (다만 Tomcat에서는 경로 혼동을 피하기 위해 절대경로 사용을 권장합니다.)

    즉, appBase는 탐색할 기본 루트 디렉토리이고, docBase는 실제 웹앱이 위치한 경로입니다. 예를 들어 Host 설정에 appBase="webapps"로 돼 있다면, Tomcat은 $CATALINA_BASE/webapps 폴더 아래의 WAR 파일이나 폴더를 자동으로 찾습니다. 여기서 특정 웹앱 Context를 명시적으로 등록하고 싶다면 <Context docBase="실제경로" ...>로 docBase를 지정할 수 있는데, 이때 그 경로는 appBase 바깥의 어떠한 디렉터리라도 될 수 있습니다.

    예시:

    • appBase="webapps"이고, webapps/ 아래에 myapp.war 파일이 있다면 Tomcat이 기동 시 자동으로 이를 읽어들여 /myapp 경로에 배치합니다. 이때 appBase는 webapps/ 폴더 자체이고, docBase는 Tomcat이 내부적으로 webapps/myapp.war를 풀어서 전개한 디렉터리(webapps/myapp/)입니다.
    • 만약 webapps 폴더가 아닌 다른 곳에 있는 애플리케이션을 배치하고 싶다면, <Context docBase="/data/apps/myapp" path="/myapp" />와 같이 Context 설정에 docBase 절대경로를 줄 수 있습니다. 이렇게 하면 appBase 아래에 해당 WAR/폴더가 없어도 지정한 외부 경로의 애플리케이션이 /myapp으로 서비스됩니다.

    정리하면, appBase는 톰캣이 자동 배포를 위해 들여다보는 폴더이고, docBase는 각 웹앱의 실제 위치입니다. Context XML 등을 사용하면 appBase 외부에 있는 경로도 자유롭게 사용할 수 있습니다.

    autoDeploy, deployOnStartup, unpackWARs: 의미와 동작 방식

    Host 요소에는 세 가지 배포 관련 속성이 자주 등장합니다: autoDeploy, deployOnStartup, unpackWARs. 각각 다음과 같은 의미와 동작 방식을 가집니다:

    • autoDeploy: 자동 배포 기능으로, Tomcat 실행 중에 Host의 appBase (또는 xmlBase) 경로를 모니터링하여 새로운 WAR 파일이나 디렉터리가 생기거나 변경되면 자동으로 배포해 줍니다. 예를 들어 Tomcat이 구동된 상태에서 webapps/ 폴더에 새로운 app.war를 떨어뜨리면, autoDeploy="true"일 경우 해당 WAR를 감지하여 자동으로 전개하고 애플리케이션을 띄웁니다. 이는 백그라운드에서 파일 변경을 폴링(polling)하는 방식으로 이루어집니다.
      실무 팁: 개발 편의성에는 유용하지만, 운영 환경에서는 예기치 않은 재배포를 피하기 위해 보통 autoDeploy="false"로 설정합니다 (자세한 내용은 아래 Best Practice 섹션 참고).
    • deployOnStartup: Tomcat 시작 시점에 appBase (및 xmlBase)를 스캔하여 해당 경로에 있는 모든 WAR 파일과 디렉터리 자동 배포를 수행할지 여부입니다. 기본값은 true이며, Tomcat을 기동할 때 appBase폴더에 있는 애플리케이션들을 모두 찾아 전개합니다. 만약 이를 false로 하면 기동시에는 자동 전개하지 않으며, 수동으로 Context를 지정한 경우에만 배포됩니다. 일반적으로 운영 환경에서도 deployOnStartup=true로 두어 재기동 시 애플리케이션이 모두 배치되도록 합니다.
    • unpackWARs: WAR 파일을 자동으로 풀어서 디렉터리로 전개할지 여부입니다. true로 하면 WAR 파일을 $CATALINA_BASE/webapps/앱이름/ 형태로 압축 해제하여 실행하고, false이면 WAR 파일을 압축 상태 그대로 로드하여 실행합니다. 기본값은 true이며, 보통 압축을 푸는 것이 앱 실행 성능에 유리합니다. false로 설정하면 WAR 파일을 일종의 읽기 전용 ZIP처럼 사용하여 메모리 상에서 클래스와 리소스를 로드하며, 디스크에 전개하지 않으므로 전개 시간은 줄지만 실행 중 변경이나 개별 파일 접근은 어려워집니다. (대부분 경우 unpackWARs=true를 사용하지만, 용량이 매우 큰 WAR를 빠르게 배포해야 할 때 false 옵션을 고려하기도 합니다.)

    이들 옵션은 조합되어 동작합니다. deployOnStartup=true이면 Tomcat 부팅시 지정한 appBase 경로를 훑어 WAR/폴더들을 배포하며, autoDeploy=true이면 실행 중에도 폴더 변화를 계속 반영합니다. unpackWARs=true이면 배포 시 WAR을 풀어서 디렉터리를 만들고, false이면 WAR 파일 그대로 둔 채로 서비스합니다. 예를 들어, autoDeploy="true"이고 unpackWARs="true"인 경우 실행 중 WAR 파일 교체가 감지되면, 기존 디렉터리를 지우고 WAR를 다시 풀어서 재배포하고, unpackWARs="false"였다면 WAR 파일 자체를 재로드하는 식으로 동작합니다.

    Context XML을 통한 명시적 배포 방식

    Tomcat에서는 Context Descriptor(XML)를 활용해 애플리케이션을 명시적으로 배포(정적 배포)할 수 있습니다. 이 방법은 WAR 파일 자동 전개와 대비되며, autoDeploy를 사용하지 않거나 특정 경로로 앱을 배치할 때 유용합니다. 주요 방법은 두 가지입니다:

    1. server.xml에 Context 직접 기술: <Host> 요소 안에 <Context> 요소를 넣어 애플리케이션을 지정하는 방법입니다. 예를 들어 <Host name="localhost" appBase="webapps" ...> <Context path="/myapp" docBase="/var/apps/myapp" reloadable="false" /></Host>처럼 server.xml에 컨텍스트를 작성하면 Tomcat 기동 시 해당 경로(/myapp)에 지정된 docBase 위치 (/var/apps/myapp)를 바로 매핑합니다. 이때 autoDeploy나 deployOnStartup와 관계없이 서버 기동과 동시에 바로 배치되며, Tomcat은 이를 정적(명시) 배치로 간주합니다. 단, server.xml 수정이 필요하고, 설정 변경 시 Tomcat 재시작이 필요하므로 운영 중 잦은 수정은 바람직하지 않습니다 (또한 server.xml에 Context 정의는 여러 애플리케이션 운용 시 복잡도를 높이므로, Tomcat 권장 사항은 개별 Context XML 파일 활용입니다).
    2. 개별 Context XML 파일 사용: Tomcat은 <CATALINA_BASE>/conf/[Engine 이름]/[Host 이름]/ 디렉터리 아래 XML 파일을 배치하면 자동으로 그 내용을 컨텍스트로 인식합니다. 예를 들어 기본 Engine이 "Catalina"이고 Host 이름이 "localhost"라면, $CATALINA_BASE/conf/Catalina/localhost/ 경로 아래 myapp.xml 파일을 두면 Tomcat은 이를 /myapp 컨텍스트로 배포합니다. 파일 이름이 곧 컨텍스트 경로로 매핑되는데, ROOT.xml은 루트 컨텍스트(/), foo.xml은 /foo, foo#bar.xml은 /foo/bar처럼 경로 구분자 /는 파일명에 # 문자로 표현합니다. 이 XML 파일 안에는 <Context> 태그를 사용하여 docBase, path(필요시) 등을 설정합니다. 예를 들어, $CATALINA_BASE/conf/Catalina/localhost/ROOT.xml 파일에 <Context docBase="/data/apps/myservice" reloadable="false" />라고 쓰면, Host의 appBase 안에 아무 파일이 없어도 해당 절대경로의 애플리케이션이 루트 컨텍스트(/)로 서비스됩니다. Tomcat 기동 시 이런 Context Descriptor를 가장 먼저 읽어 들이므로, 같은 경로에 대한 WAR 파일 자동배포보다 우선 적용됩니다.

    Context를 통한 명시 배포 시 주의사항도 있습니다. Host에 이미 자동 배포될 WAR이나 폴더가 있는데 같은 경로로 Context를 명시해버리면 "중복 배포" 충돌 오류가 발생합니다. Tomcat은 하나의 컨텍스트 경로에 두 개의 웹앱을 배치하지 못하도록 되어 있으므로, server.xml이나 conf에 Context를 명시했다면 appBase 폴더에 동일한 경로의 WAR/폴더를 두지 않는 것이 원칙입니다. 예를 들어 ROOT.xml로 루트 컨텍스트를 지정했는데 webapps/ROOT.war 파일도 존재하면 충돌하므로, 후자를 제거해야 합니다. 명시 배포를 사용할 경우 autoDeploy와 deployOnStartup를 false로 하여 완전 수동 배포 모드로 운영하기도 하지만, 실무에서는 혼용하기보다는 둘 중 한 가지 방식으로 일관되게 사용하는 것을 권장합니다.

    운영 환경 vs 개발 환경: server.xml 구성 방식 비교

    Tomcat 설정은 운영(Production) 환경과 개발(Development) 환경에서 최적값이 다를 수 있습니다. 각 환경의 요구사항에 맞게 server.xml을 구성하는 방법을 비교해 보겠습니다.

    • 운영 환경(Production): 안정성과 예측 가능성이 가장 중요합니다. 운영 중에는 웹앱이 빈번하게 바뀌지 않으며, 예상치 못한 재배포는 피해야 합니다. 따라서 자동 재배포 기능을 끄고(autoDeploy=false), Tomcat 기동 시 한 번만 배포하도록 설정하는 편이 좋습니다. 일반적으로 Host 설정을 autoDeploy="false", deployOnStartup="true"로 두고 운영하며, 새로운 WAR나 변경 사항을 반영하려면 일정 관리 하에 Tomcat을 재시작하여 배포를 완료합니다. 이때 WAR 파일을 교체할 때는 임시 파일로 업로드 후 원본 이름으로 원자적(atomic) 교체하는 방식을 사용하면 부분 파일 복사로 인한 문제를 예방할 수 있습니다. 운영 환경에서는 한 번 배포한 애플리케이션이 수시로 갱신되지 않으므로, unpackWARs=true로 설정해 WAR를 미리 풀어두고 실행 성능을 높이는 것이 일반적입니다. 또한, 개발 편의를 위한 reloadable 옵션 등은 성능에 영향을 줄 수 있으므로 항상 reloadable=false(기본값)로 유지합니다. 요약하면 "자동보다는 수동, 변경보다는 안정"에 초점을 맞춘 설정이 운영 환경에 적합합니다.
    • 개발 환경(Development): 빠른 피드백과 편리한 배포가 중요합니다. 코드 수정이나 리소스 변경이 빈번하기 때문에 Tomcat을 재기동하지 않고도 변화가 반영되도록 설정할 수 있습니다. 이를 위해 보통 autoDeploy="true"로 두어 실행 중 변경 감지를 활성화하고, WAR 대신 explode된 디렉터리 형태로 배포하여 수정 즉시 재로딩되게 활용하기도 합니다. 예컨대, 개발자가 JSP나 정적 파일을 수정하면 autoDeploy 및 unpackWARs가 켜져 있을 경우 일정 지연 후 자동으로 해당 웹앱을 재로드합니다. 추가로, 클래스 변경까지 즉각 반영하려면 Context에 reloadable="true"를 줄 수도 있는데, 이 옵션은 매번 클래스 변경을 감지하여 클래스로더를 재시작하므로 편리한 대신 CPU/메모리 오버헤드가 있습니다. 따라서 소규모 개발 단계가 아니라면 reloadable보다는 수동 재배포나 JRebel 같은 도구를 고려하기도 합니다. 개발 환경에서는 오류 확인을 위해 로깅을 자세히 하거나, Manager 애플리케이션을 활용해 웹에서 배포/리로드를 수행하기도 하므로, autoDeploy를 켜두고 Tomcat Manager로 수동 배포를 병행하는 경우도 있습니다. 핵심은 "개발 편의성과 속도"를 위해 자동 배포 기능을 활용하되, 그로 인해 발생하는 부하가 치명적이지 않은 선에서만 사용하는 것입니다.

    두 환경 모두에서 공통적으로 고려할 사항은 보안과 관리입니다. 예를 들어 운영 환경에서는 Manager, Host Manager 등 관리용 웹앱을 배포하지 않거나 접근을 제한하고, 불필요한 Connector (예: AJP나 공개되지 않을 포트)를 닫아두는 것이 좋습니다. 개발 환경에서는 반대로 이러한 툴을 적극 활용해 배포 편의를 얻을 수 있습니다.

    또한 실무에서 도메인별로 여러 개의 웹앱을 운영해야 할 경우, 한 인스턴스의 Tomcat에 여러 Host를 설정해 (appBase를 분리하여) 쓰기도 하지만, 가능하면 Tomcat 인스턴스를 아예 분리하여 구성하는 것이 서로 간섭을 줄이고 관리하기 수월합니다. 즉, 대규모 서비스에서는 도메인/서비스별로 Tomcat을 개별 운영하고, 소규모 서비스나 개발 단계에서는 한 Tomcat에 여러 앱을 올리는 식으로 구분하기도 합니다.

    요약하면, 운영 환경에서는 자동 배포 기능 최소화 및 안정성에 초점을 맞추고, 개발 환경에서는 빠른 반영과 편의성에 중점을 두어 server.xml을 구성하면 됩니다.

    배포 방식별 디렉터리 구조 예시 및 배포 전략

    Tomcat에서 웹 애플리케이션을 배포하는 방식에는 여러 가지가 있으며, 각각 파일을 배치하는 디렉터리 구조와 동작 방식에 차이가 있습니다. 여기서는 대표적인 세 가지 배포 방법에 대한 예시와 전략을 소개합니다: WAR 파일 자동 배포, 외부 경로의 디렉터리/WAR 배포, 병렬 배포(Parallel Deployment).

    1. WAR 파일 자동 배포 (기본 방식)

    가장 기본적인 방법으로, appBase 디렉터리에 WAR 파일을 넣어두면 Tomcat이 이를 자동으로 풀어서 배포하는 방식입니다. 예를 들어 기본 Host(localhost)의 appBase="webapps"일 때, $CATALINA_BASE/webapps 폴더에 ROOT.war나 myapp.war 파일을 넣으면 다음과 같이 동작합니다:

    • Tomcat 기동 시(deployOnStartup=true일 경우) webapps 디렉토리를 스캔하여 WAR 파일들을 발견하고 배포를 시작합니다. unpackWARs=true 설정이면 WAR을 동일한 이름의 폴더로 자동 압축 해제하며, 예컨대 ROOT.war → ROOT/ 디렉터리가 생성되고, 앱이 / 경로로 서비스됩니다. 마찬가지로 myapp.war → myapp/ 폴더로 풀려 /myapp 경로로 배치됩니다.
    • Tomcat 실행 중(autoDeploy=true인 경우) 해당 폴더에 새로운 WAR이 추가되거나 기존 WAR 파일이 교체되면, 백그라운드 스레드가 이를 감지하여 자동으로 재배포합니다. 예를 들어 실행 중 billing.war 파일을 새 버전으로 교체하면, 파일 타임스탬프/크기 변화를 감지하여 이전 애플리케이션을 폐기하고 새로 전개합니다. (운영 환경에서는 이 기능을 끌 수 있음)

    디렉터리 구조 예시: (기본 appBase가 webapps/인 경우)

    $CATALINA_BASE/webapps/
     ├── ROOT.war              # 배포할 WAR 파일 (루트 컨텍스트)
     ├── ROOT/                 # unpackWARs=true일 때 WAR 압축 해제된 폴더
     ├── myapp.war             # 배포할 WAR 파일 (/myapp 컨텍스트)
     ├── myapp/                # myapp.war가 풀린 폴더
     └── ... 
    $CATALINA_BASE/work/Catalina/localhost/
     └── _/ or myapp/ ...      # 각 애플리케이션별 임시 작업 폴더 (JSP 컴파일 결과 등)

     

    위와 같이 WAR 배포 시 Tomcat이 알아서 폴더 구조를 만들어주므로 관리가 간편합니다. 다만 WAR 업로드 시 주의할 점은, 큰 WAR 파일을 appBase에 복사하는 도중에 Tomcat이 감지하면 부분적으로 복사된 파일로 인해 오류가 날 수 있습니다. 이를 피하려면 일시적인 파일명으로 업로드한 뒤 다 올려지면 최종 이름으로 원자적으로 rename하는 방식을 사용하세요. (예: myapp.war.part로 업로드 완료 -> myapp.war로 파일명 변경)

    2. 외부 디렉터리 또는 외부 WAR 사용 (명시적 경로 배포)

    두 번째 방법은 애플리케이션을 Tomcat appBase 바깥 경로에서 운영하는 것입니다. 이 때는 앞서 설명한 Context 명시 배포를 활용하여, <Context>의 docBase에 절대 경로를 지정하는 방식으로 구현합니다. 이렇게 하면 WAR 파일을 webapps/에 놓지 않고도 원하는 경로의 파일을 Tomcat이 직접 가져다가 배포합니다. 대표적인 시나리오는 전개된 폴더를 외부에 두는 것WAR 파일 자체를 외부에 두는 것 두 가지입니다:

    • 전개된 디렉터리 외부 배포: WAR를 미리 풀어 전개한 상태로 특정 경로에 두고, Tomcat이 그 디렉터리를 그대로 읽어 서비스하는 방식입니다. 예를 들어 $CATALINA_BASE/conf/Catalina/localhost/ROOT.xml 파일에 <Context docBase="/data/apps/myservice" />라고 하면, /data/apps/myservice/ 폴더에 이미 완전히 전개되어 있는 웹앱을 Tomcat이 / 컨텍스트로 연결합니다. 이 경우 Host의 appBase 아래에는 아무 파일도 존재하지 않아도 동작하며, 애플리케이션 수정 배포시 일반적으로 Tomcat 재시작을 통해 반영합니다. (개발 환경이라면 autoDeploy를 켜서 외부 디렉터리 변경 시 reload도 가능하지만, 운영에선 비권장.)
    • 외부 WAR 파일 배포: WAR 파일을 풀지 않고 특정 경로에 두고, Tomcat이 그 WAR 파일을 직접 배포하도록 할 수도 있습니다. 예를 들어 <Context docBase="/deploy/bundles/ROOT.war" unpackWARs="true" />처럼 설정하면 Tomcat이 해당 WAR 파일을 읽어 내부에서 전개해 실행합니다. unpackWARs=true인 경우 Tomcat이 자체적으로 임시 디렉토리에 WAR를 풀어 놓고 실행하며, false인 경우 WAR 파일을 메모리상에서 읽어 직접 서비스합니다. 이 방식도 마찬가지로 컨텍스트가 명시적으로 정의됐으므로 autoDeploy 없이도 동작하며, 파일 교체 시 Tomcat을 재기동하거나 Context reload를 해줘야 합니다. 파일 변경 감지에 있어서는 앞의 디렉터리 외부 배포와 동일한 정책이 적용됩니다.

    디렉터리 구조 예시: (절대경로 /data/apps/myservice를 ROOT 컨텍스트로 배포하는 경우)

    $CATALINA_BASE/conf/Catalina/localhost/ROOT.xml   # Context 설정 (docBase 외부 경로 지정)
    $data/apps/myservice/       # 실제 웹애플리케이션 디렉터리 (웹 콘텐츠 및 WEB-INF 등)
    $CATALINA_BASE/webapps/     # 비어 있음 (appBase 사용 안 함)
    $CATALINA_BASE/work/Catalina/localhost/ROOT/ ...  # 임시 작업 폴더

     

    또는 (절대경로 WAR 파일 /deploy/bundles/ROOT.war를 ROOT 컨텍스트로 배포하는 경우):

    $CATALINA_BASE/conf/Catalina/localhost/ROOT.xml   # Context 설정 (docBase WAR 파일 지정)
    $deploy/bundles/ROOT.war      # WAR 파일 위치 (appBase 밖)
    $CATALINA_BASE/temp/ 또는 work/Catalina/localhost/_/  # WAR가 풀려 전개되는 임시 폴더 (unpackWARs=true일 때)
    $CATALINA_BASE/webapps/       # 비어 있음

     

    외부 경로 배포의 장점은 애플리케이션 아티팩트 관리가 Tomcat 디렉토리와 분리되어 깔끔하며, 운영 중 webapps 폴더를 건드릴 필요 없이 새 버전 디렉터리나 WAR을 준비해 두었다가 설정만 바꾸거나 심볼릭 링크 교체 등으로 배포를 제어할 수 있다는 점입니다. 특히 대용량 WAR의 경우 미리 풀어놓고 교체할 수 있어 downtime을 줄이는 전략으로도 사용됩니다. 단, 주의: Context XML을 잘못 설정하면 앞서 언급한 중복 배포 문제가 생길 수 있으므로, 반드시 appBase 내에 동일한 이름의 WAR/폴더가 없는지 확인해야 합니다.

    3. 병렬 배포 (Parallel Deployment) - 무중단 배포 전략

    병렬 배포는 Tomcat 7 이상에서 지원하는 고급 기법으로, 동일한 애플리케이션의 여러 버전을 동시에 배포하는 방법입니다. 이를 통해 무중단 배포(zero-downtime deployment)를 구현할 수 있습니다. 병렬 배포를 사용하려면 WAR 파일 이름에 특정한 버전 식별자를 포함시켜야 합니다. 형식은 웹앱이름##버전.war 형태로, ## 이후의 부분을 Tomcat이 버전으로 인식합니다.

    예시 시나리오: 앞서 자동 배포 예에서 billing.war 애플리케이션을 운영 중이라고 가정합니다. 새 버전을 배포하려면 파일명을 billing##20250825.war 같이 이중 해시(##)와 버전 태그를 붙여 appBase에 업로드합니다. 그러면 Tomcat은 이를 기존 billing 애플리케이션의 새로운 버전으로 인식하여 병렬로 배포합니다. 이때 URL 컨텍스트 경로는 여전히 /billing으로 동일하지만, 내부적으로 두 개의 버전이 함께 존재하게 됩니다. Tomcat은 새 버전을 로드하면서도 기존 버전의 세션을 유지시켜 주고, 새로 들어오는 요청은 새로운 버전으로 라우팅합니다. 이전 버전은 기존 세션이 지속되는 동안 내려가지 않고 유지되다가, 일정 시간이 지나거나 세션이 모두 소멸하면 자동 언데플로이될 수 있습니다 (세션 유지 정책은 세션 매니저 설정에 따름). 운영자는 새 버전 배포 후 문제가 없으면 이전 버전 WAR(billing##이전버전.war)을 삭제하여 정리하면 됩니다.

    병렬 배포의 장점: 배포 시 애플리케이션 재시작으로 인한 서비스 중단 시간이 0에 가깝게 된다는 점입니다. 사용자 입장에서는 /billing 서비스가 계속 동작하고, 백엔드에서는 새 버전으로 슬쩍 교체됩니다. 다만 모든 환경에서 완전 무중단을 보장하는 것은 아니므로(예: 세션 호환성 문제 등은 개발자가 해결해야 함), Tomcat의 병렬 배포는 무중단 배포를 도와주는 도구로 생각해야 합니다. 또한 버전 간 공존이 오래되면 메모리를 두 버전이 차지하므로, 안정화 후에는 이전 버전을 언로드하는 것이 좋습니다. 병렬 배포는 자동 배포(autoDeploy)가 켜져 있어야 동작하며, 이를 끈 환경에서는 의미가 없습니다. 운영 환경에서 autoDeploy를 끄는 대신 병렬 배포를 활용하려면, 새로운 WAR을 올리고 수동으로 Tomcat Manager를 통해 "deploy?update=true" 등의 명령을 보내는 방법도 있습니다.

    Tip: 병렬 배포는 편리하지만, Tomcat 단일 인스턴스에 의존하므로 그 Tomcat 자체를 재기동해야 하는 설정 변경에는 여전히 중단이 필요합니다. 완전한 무중단을 원한다면 두 대 이상의 Tomcat 인스턴스를 Load Balancer 뒤에서 번갈아가며 배포하는 Active-Active 배포 전략이 일반적으로 더 활용됩니다. 병렬 배포는 그러한 여건이 안 될 때 보완적으로 쓰거나, 아주 짧은 중단시간도 아끼고 싶을 때 사용하는 기능입니다.

    Best Practice: Tomcat server.xml 설정 운용 팁

    끝으로, 실무에서 유용한 Tomcat server.xml 설정 Best Practice를 정리합니다. 운영 환경에서는 안정성과 일관성을 높이는 설정이, 개발 환경에서는 편의성과 빠른 반영이 핵심입니다. 또한 중복 배포를 피하고 혼선을 줄이기 위한 유의사항을 함께 살펴보겠습니다.

    운영 환경 설정 Best Practice (안정성 중심)

    • 자동 배포 비활성화: 운영 중에는 의도치 않은 재배포가 없도록 autoDeploy="false"로 설정하는 것이 좋습니다. 이렇게 하면 Tomcat 구동 후에 appBase 변화를 감시하지 않으므로, 모든 배포 행위는 관리자에 의해 통제됩니다. (새 버전 배포 시 Tomcat 재시작이나 Manager 툴을 통한 수동 배포 필요)
    • 기동 시 배포 활성화: deployOnStartup="true"로 두어 Tomcat 시작시 지정된 appBase 혹은 Context들의 애플리케이션을 빠짐없이 배포하도록 합니다. 이 옵션을 켜두면 autoDeploy를 꺼도 초기 기동시 WAR/폴더가 올라옵니다. 만약 이마저 끄면(deployOnStartup=false) 모든 앱을 server.xml에 명시해야 하므로, 특수한 경우 아니면 권장되지 않습니다.
    • 안정적인 배포 절차 수립: 운영 환경 배포는 표준화된 절차로 관리합니다. 예를 들어 "새 버전 WAR 교체 → Tomcat 재기동 → 서비스 상태 점검"과 같은 프로세스를 문서화해 두고, 배포 시마다 지침대로 수행합니다. autoDeploy를 끄면 반드시 재시작 후 배포를 확인해야 하므로, CI/CD 파이프라인에서도 Tomcat 재기동을 트리거하거나, 배포 후 Health Check를 통해 성공 여부를 검증하도록 합니다.
    • 병렬 배포 전략 검토: 만약 서비스 중단을 최소화해야 하지만, 다중 인스턴스 구성은 어렵다면 앞서 설명한 병렬 배포(버전 붙은 WAR)도 고려해볼 수 있습니다. 다만, 이는 임시방편일 뿐 완전한 HA 구성만큼 안전하지 않을 수 있으므로, 가능하면 무중단 배포는 인스턴스 레벨에서 구성하는 게 정석입니다 (예: 2대 이상의 Tomcat을 번갈아 배포하여 교대 운영).
    • 불필요한 앱/기능 제거: 운영 Tomcat에는 불필요한 예제 앱, 문서, 관리자 앱 등을 삭제하거나 주석 처리하여 보안과 성능을 확보합니다. server.xml에서 사용하지 않는 Connector(AJP 등)도 막아둡니다. 이러한 정리는 server.xml 설정이라기보다 배포폴더 관리에 가깝지만, 실무 운영 안정성에 매우 중요합니다.
    • 설정 관리 분리: $CATALINA_HOME와 $CATALINA_BASE를 분리하여(instances별 conf/, logs/, temp/, webapps/를 분리) 사용하는 것을 권장합니다. 이렇게 하면 Tomcat 이진 파일과 설정/배포파일이 분리되어 Tomcat 업그레이드나 여러 인스턴스 운영 시 충돌을 막을 수 있습니다.

    개발 환경 설정 Best Practice (효율성 중심)

    • 자동 배포 활성화: 개발 중에는 수정 사항이 즉시 반영되도록 autoDeploy="true"로 설정하는 것을 권장합니다. 이렇게 하면 서버 재시작 없이도 변경한 파일을 곧바로 테스트할 수 있어 개발 효율이 높아집니다. 단, 대용량 프로젝트에서는 autoDeploy로 재배포하는 데도 시간이 걸릴 수 있으므로, 변경 모니터 간격(backgroundProcessorDelay) 등을 조정할 수도 있습니다.
    • Exploded Deployment 활용: WAR 파일을 매번 만들지 않고, webapps/ 아래 디렉터리 형태로 배포하면 (예: webapps/myapp/ 폴더 자체에 변경을 가함) 변경 즉시 반영됩니다. 이 경우 unpackWARs는 의미가 없고(이미 풀려 있으므로), JSP나 HTML, JS 변경 시 autoDeploy에 의해 재로드되거나, 필요하다면 <Context reloadable=true> 설정으로 클래스 변경까지 캐치할 수 있습니다. 이 방식은 IDE와 Tomcat 연동 시에도 많이 쓰이며, Eclipse, IntelliJ 등의 톰캣 플러그인이 소스 변경을 자동으로 해당 디렉터리에 반영해주기도 합니다.
    • 개발용 유틸리티 사용: 개발 단계에서는 Tomcat Manager 웹어플리케이션을 활용해 수동 리로드배포를 할 수도 있습니다. 이를 위해 server.xml에 <User>를 추가해 Manager 접근 계정을 만들고, context.xml의 <Valve>로 IP 제한을 풀어놓으면 브라우저에서 버튼 클릭만으로 리로드가 가능합니다. 잦은 재시작이 번거롭다면 이러한 툴을 쓰거나, 아예 JRebel 같은 핫디플로이 도구를 이용하는 것도 고려됩니다.
    • 로그 및 디버그 모드: 개발 환경에서는 loglevel="DEBUG" 등으로 Tomcat 로그를 자세히 보고, server.xml의 <Context reloadable> 기능을 켜서 자잘한 클래스 변경까지 캐치하며, 필요하면 JMX나 Debugger를 붙여 사용할 수 있습니다. 운영과 분리된 별도의 개발용 Tomcat 인스턴스를 두고 마음껏 조작해 보는 것이 좋습니다.

    중복 배포 방지와 Context 사용 시 주의사항

    • 하나의 컨텍스트는 하나의 배포만: 동일한 컨텍스트 경로에 2개의 배포물을 놓지 않는 것이 철칙입니다. 만약 appBase 폴더에 ROOT.war가 있는데 server.xml이나 conf에 <Context path="" docBase=...>를 추가하면, Tomcat 기동 시 "Context path '/' is already in use" 류의 오류가 발생합니다. 반드시 중복을 제거하고 한 곳에서만 해당 경로를 다루도록 합니다. (예: 명시 배포를 선택했다면 webapps/ROOT.war 파일 삭제)
    • autoDeploy와 수동 Context 혼용 주의: autoDeploy를 활성화한 상태에서 수동 Context 배포를 병행하면 예기치 못한 동작이 일어날 수 있습니다. 예를 들어 수동 Context 설정 후 autoDeploy=true로 두면, Context 설정 파일 수정 시 Tomcat이 이를 실시간 반영하려 하거나, 반대로 WAR 파일을 잘못 올리면 충돌할 수 있습니다. 가급적 운영에선 둘을 혼용하지 말고, 개발에서는 혼용하더라도 충돌하는 상황이 없도록 신경 써야 합니다.
    • Context path 지정 규칙: <Context path="...">를 server.xml 등에 사용할 때는 몇 가지 규칙이 있습니다. path=""는 루트 컨텍스트만 의미하며, /로 끝나거나 중복 슬래시는 안 되고, 중첩 경로는 지원하지 않습니다 (nested path는 conf 파일명에 #으로 표현하는 방식만 지원). 또한, <Context path>를 명시하려면 해당 WAR/디렉터리가 appBase 아래 존재하지 않거나, Host의 autoDeploy와 deployOnStartup를 false로 해야 합니다. 이러한 규칙을 어기면 Tomcat 문서상 "double deployment is likely to result" (이중 배포 발생 가능)과 같은 경고가 있습니다. 따라서 Context를 직접 정의할 때는 Tomcat 공식 문서의 컨텍스트 경로 지정 가이드를 준수하세요.

    Best Practice를 따르면 Tomcat server.xml 설정으로 인한 시행착오를 줄이고, 운영 환경에서는 안정성을, 개발 환경에서는 효율성을 크게 높일 수 있을 것입니다.

    요약 및 결론

    Tomcat server.xml 설정은 서버 구조 이해에서 출발하여, 배포 옵션 튜닝, 환경별 설정 전략, 배포 방법 선택, 주의사항 관리까지 폭넓게 고려해야 합니다. 이번 가이드에서는 Server/Service/Connector/Engine/Host/Context 각 요소의 역할을 알아보고, appBase와 docBase 차이, autoDeploy & deployOnStartup & unpackWARs 옵션의 의미, Context XML을 활용한 배포 방법을 상세히 다뤘습니다. 그리고 운영 환경과 개발 환경에 맞게 이러한 설정을 어떻게 달리 적용해야 하는지, WAR 자동 배포 vs 외부 경로 배포 vs 병렬 배포의 전략적 활용, 마지막으로 중복 배포를 피하고 안전하게 톰캣을 운영하기 위한 팁들을 정리했습니다.

    요약하면, 운영 환경에서는 자동 기능을 최소화하고 검증된 절차에 따라 배포함으로써 예측 가능한 안정성을 얻을 수 있고, 개발 환경에서는 Tomcat의 자동 배포/리로드 기능을 최대한 활용하여 빠르게 개발 사이클을 돌릴 수 있습니다. 또한 배포 방식은 조직의 규모와 요구에 맞게 선택하되, 일관성 있는 원칙(예: 명시 배포 vs 자동 배포)을 정하는 것이 좋습니다.

    이제 Tomcat server.xml 설정에 대한 개념과 실무적인 팁을 얻었으니, 실제 환경에 적용해 보세요. 작은 설정 하나가 큰 영향을 미칠 수 있으므로, 변경 시에는 반드시 테스트 환경에서 검증하고 진행하는 것을 권장합니다. 지금 바로 자신의 Tomcat 설정을 점검하여 불필요한 autoDeploy가 켜져 있지는 않은지, 앱 배포 경로가 올바르게 설정되어 있는지 확인해 보십시오. 올바른 설정과 전략을 통해 Tomcat을 더욱 신뢰성 있고 효율적으로 운영할 수 있을 것입니다.

    (이 가이드가 도움이 되었다면 주변 동료들과 공유하거나, 추가 궁금한 점을 아래 FAQ에서 확인하세요. 여러분의 Tomcat 운영이 한층 수월해지기를 바랍니다!)

    FAQ (자주 묻는 질문)

    Q1. Tomcat에서 autoDeploy 설정을 운영과 개발에 어떻게 하는 것이 좋나요?
    A: 운영 환경에서는 가능한 autoDeploy를 끄는 것(false)이 좋습니다. 자동 배포를 끄면 런타임 중 새로운 WAR 투입이나 변경으로 인한 예기치 않은 재배포가 발생하지 않아 안정성이 높아집니다. 대신 애플리케이션 업데이트 시 Tomcat을 재시작하거나, Tomcat Manager를 통한 수동 배포를 사용합니다. 반면 개발 환경에서는 autoDeploy를 켜 두는 것(true)이 편리합니다. 파일 변경을 자동 감지하여 바로 반영할 수 있기 때문에 코드 수정 → 브라우저 확인 사이클이 빨라집니다. 다만, autoDeploy가 켜져 있으면 Tomcat이 변경 감지를 위해 리소스를 사용하므로, 개발용이 아닌 운영 서버에서는 성능과 로그상의 잦은 재배포 이슈를 고려해야 합니다.

     

    Q2. Tomcat unpackWARs 옵션의 의미는 무엇인가요?
    A: unpackWARs는 WAR 파일을 풀어서(explode) 디렉터리 형태로 전개할지 여부를 결정하는 설정입니다. 기본값 true로 두면 Tomcat이 WAR을 자동으로 풀어서 $CATALINA_BASE/webapps/앱이름/ 폴더로 만들고 그 안에서 애플리케이션을 실행합니다. 이 경우 WAR 압축 해제 시간은 들지만, 앱 구동 후에는 파일을 직접 접근하기 때문에 클래스 로딩이나 JSP 컴파일 등이 더 원활합니다. 반대로 false로 설정하면 WAR을 풀지 않고 압축 상태로 둔 채 실행합니다. Tomcat이 압축을 실시간 해제하면서 읽기 때문에 약간의 오버헤드가 있을 수 있지만, 디스크에 폴더를 생성하지 않아 배포 속도가 빠르고 깨끗하게 WAR 단일 파일로 관리할 수 있습니다. 요약하면: true = WAR 자동 풀기 (일반적으로 권장), false = WAR 풀지 않고 바로 사용. 대부분의 경우 기본값인 true를 유지하면 됩니다.

     

    Q3. Tomcat에서 appBase와 docBase는 뭐가 다르고 어떻게 설정해야 하나요?
    A: appBaseHost(가상호스트)의 기본 애플리케이션 디렉토리입니다. 예를 들어 <Host name="localhost" appBase="webapps">라고 하면 $CATALINA_BASE/webapps 폴더가 해당 Host의 appBase가 됩니다. Tomcat은 이 폴더를 스캔하여 WAR 파일이나 디렉토리를 자동 배포합니다. docBase각각의 Context(웹앱)이 어디에 존재하는지 가리키는 경로입니다. 보통 명시적으로 Context를 정의할 때 사용하며, WAR 파일명이나 폴더명을 appBase 기준 상대경로로 주거나, 절대경로를 지정해서 appBase 바깥의 위치를 가리킬 수도 있습니다. 쉽게 말해, appBase = "웹앱들을 담는 기본 폴더", docBase = "특정 웹앱의 실제 위치"입니다. 특별한 이유가 없다면 기본 appBase (webapps)를 그대로 쓰면서, 표준적으로 WAR 파일을 그 안에 두는 방식을 따르면 됩니다. 만약 소스 디렉터리로 직접 배포하거나 외부 경로로 운영해야 하면 docBase를 활용하면 됩니다.

     

    Q4. Tomcat에서 context.xml 설정은 언제, 어떻게 활용하나요?
    A: Tomcat의 context.xml은 두 가지로 나뉩니다. 하나는 글로벌 context.xml (예: $CATALINA_BASE/conf/context.xml)로 모든 웹앱에 공통 적용되는 설정이고, 다른 하나는 개별 Context Descriptor로서 각 애플리케이션별 설정을 정의하는 파일입니다. 우리가 여기서 논의한 것은 후자인 Context Descriptor XML 파일입니다. 이 파일들은 $CATALINA_BASE/conf/<Engine>/<Host>/<앱이름>.xml 형태로 위치하며, 파일명으로 context path를 결정하고 그 안에 <Context> 태그로 개별 설정을 넣습니다. 언제 활용하냐면, WAR 자동배포 방식 대신 명시적으로 애플리케이션을 배치하고 싶을 때입니다. 예를 들어 WAR를 특정 폴더에 풀어놓고 운영한다거나, 또는 WAR 파일 이름과 다른 경로로 매핑하고 싶을 때 context.xml에 <Context docBase="..." path="...">를 써서 지정합니다. 이 방법은 autoDeploy를 끈 환경에서 주로 쓰이며, 한 번 설정해두면 Tomcat 재시작 시마다 그 설정대로 앱을 올려주므로 일관된 배포를 보장합니다. 다만, server.xml에 직접 Context를 넣는 방식은 권장되지 않으므로 (업그레이드나 관리 이슈), 가급적 이러한 개별 context.xml 파일을 활용하는 것이 좋습니다. 또한 context.xml을 쓸 때는 중복 배포되지 않도록 appBase 내 동일한 앱을 제거하는 것 잊지 마세요.

     

    Q5. Tomcat 운영 환경에서 추천하는 실무 배포 전략은 무엇인가요?
    A: 규모와 요구사항에 따라 다르지만, 일반적인 Tomcat 실무 배포 전략은 다음과 같습니다. 먼저, 운영 인스턴스에서는 autoDeploy를 끄고 검증된 절차에 따라 배포하여 안정성을 확보합니다. 예컨대, 새 버전 배포 시 1) 새로운 WAR을 올리고, 2) Tomcat을 재기동하거나 (혹은 다중 인스턴스 중 하나씩 교체), 3) 정상 기동 확인 후 서비스 트래픽을 새 버전으로 전환하는 절차입니다. 가능하다면 무중단 배포를 위해 두 개 이상의 Tomcat 노드를 사용해 Blue-Green 또는 Rolling 배포를 구성하는 것이 이상적입니다. 만약 단일 인스턴스라 무중단이 어렵다면 Tomcat의 병렬 배포 기능(WAR 파일명에 ##버전 추가)을 활용해 일시적으로 두 버전을 동시에 올린 뒤 안정되면 이전 버전을 내리는 방법도 있습니다. 또한, 배포 아티팩트 관리 측면에서, WAR 파일을 곧바로 webapps에 복사하기보다는 외부 디렉터리에서 전개 후 심볼릭 링크를 거는 방법이나, Context 외부 경로 지정을 사용하면 배포 시간을 줄이고 롤백을 쉽게 할 수 있습니다. 마지막으로, 어떤 전략이든 사전 테스트모니터링이 중요합니다. 세션 유지, 메모리 누수 여부, 의존 서비스 연결 등을 점검하면서 배포 전략을 세우세요. 결론적으로: *"안정적이고 예측 가능하며, 필요에 따라 무중단을 구현할 수 있는 방식"*이 최고의 전략이며, 이를 위해 Tomcat의 다양한 설정과 기법 (autoDeploy off, context.xml 활용, 병렬 배포 등)을 상황에 맞게 조합하여 활용하면 됩니다.