본문 바로가기
Tech Stack/Backend

🐱순수 Jakarta EE 서블릿 환경에서 톰캣 연동 및 구동 테스트

by 박수무당벌레 2026. 6. 24.

1. 개발 환경 구축 및 WAR 빌드/배포 절차

1) STS4 자바 엔터프라이즈 플러그인 설치

순수 서블릿 및 웹 기능(Dynamic Web Project) 개발을 위해 플러그인이 필요함.

  1. Help ▶️ Eclipse Marketplace... 선택
  2. Find 검색창에 Eclipse Enterprise Java 검색
  3. 마켓플레이스에서 검색 결과로 나오는 Eclipse Enterprise Java and Web Developer Tools 설치 후 STS4 재시작
💡 Spring Boot 기반으로 나온 STS4는 기본적으로 순수 Dynamic Web Project(레거시 서블릿) 메뉴가 포함되어 있지 않음

2) 프로젝트 환경(빌드)별 WAR 파일 추출 방법

  • 빌드 도구가 없는 순수 서블릿 (일반 Dynamic Web Project):
    1. Project Explorer에서 원하는 프로젝트 우클릭 ▶️ Export ▶️ WAR file (※ 플러그인을 깔아야 이 메뉴가 보임)
    2. 생성 경로 및 배포: 지정한 목적지 경로에 생성
  • Maven을 사용하는 경우 (pom.xml이 존재):
    1. pom.xml 상단에 war 확인
    2. 프로젝트 main 코드 환경 우클릭 ▶️ Run As ▶️ Maven clean 실행 (이전 빌드 지움)
    3. 위와 마찬가지로 우클릭 ▶️ Run As ▶️ Maven install (또는 package)
    4. 생성 경로 및 배포: 프로젝트 내 target/ 폴더 내 자동 생성
  • Gradle을 사용하는 경우 (build.gradle이 존재):
    1. build.gradle 파일 상단 plugins { ... } 블록에 id 'war' 추가
    2. 우측 Gradle Tasks 탭 실행
      (※ 안 보인다면 Window > Show View > Other > Gradle Tasks 선택)
    3. 프로젝트 이름 ▶️ build 그룹 안의 war 혹은 build 더블 클릭하여 실행
    4. 생성 경로 및 배포: 프로젝트 내 build/libs/ 폴더 내 자동 생성

3) 아파치 톰캣 서버 실행 테스트

  1. Tomcat 다운로드: Apache Tomcat 공식 홈페이지에서 압축 파일(.zip) 형태로 다운로드 (인스톨러 미사용)
  2. 압축 해제: 반디집 등을 이용해 원하는 경로에 압축 해제
  3. 서버 구동: bin 디렉토리 안의 startup.bat (배치 파일) 실행
  4. 브라우저 접속 및 네트워크 메커니즘: 프롬프트 창(앱)을 끄지 않은 상태에서 브라우저에 localhost:8080 입력 후 접속
    • 루프백(Loopback) 통신: 외부 네트워크 나갈 필요 없이 내 컴퓨터(로컬) 내부에서 돌고 도는 통신. 
      • OSI 7계층 기준: 물리적인 데이터 전송(1, 2계층) 단계가 필요 없고, 네트워크 계층(3계층, IP: 127.0.0.1) 단계에서 곧바로 자기 자신에게 패킷을 보냄.
      • TCP/IP 4계층 기준: 애플리케이션(4) ➔ 전송(3) ➔ 인터넷(2) 계층까지만 내려간 뒤, 다시 역으로 올라와 내부 서블릿 컨테이너로 연결됨.
    • 서버 종료: 구동 배치 파일과 한 쌍으로 존재하는 shutdown.bat 실행
⚠️포트 충돌(Port Conflict)
하나의 네트워크 포트(8080)에는 한 번에 하나의 프로세스만 바인딩(점유)할 수 있으므로, 다른 애플리케이션이 이미 해당 포트를 쓰고 있다면 톰캣 서버는 구동되지 못하고 에러가 발생

2. 자카르타 EE 서블릿 구동 메커니즘

1) 서블릿 실행 5단계 흐름 (레거시 기반)

  1. 클래스 정의: 자바 엔터프라이즈(Jakarta EE)의 HttpServlet 클래스를 상속받아 doGet() 또는 doPost()를 오버라이딩.
  2. 패키징 (아래 첨부파일 확인): 화면을 담당할 JSP나 자바 컴파일 파일(.class)들을 묶어 helloservlet.war 배포 파일을 생성.
  3. 톰캣 배치: 톰캣 디렉토리 내 webapps/ 폴더에 WAR 파일을 넣고 bin/startup.bat을 실행. (종료 시에는 shutdown.bat 사용)
  4. *언팩 (Unpack): 톰캣이 구동되면서 WAR 파일 압축을 자동으로 해제하고 고유 구조(WEB-INF/classes/ 내부의 컴파일된 파일들)를 호스팅 영역으로 인지.
  5. 요청 처리: localhost:8080/helloservlet/sayhello로 요청 시, 톰캣이 web.xml(서블릿 규격 명세서)을 파싱하여 배포 서블릿의 FQCN(완전 정규화된 클래스 경로, 예: mypkg.HelloServlet)과 sayhello URL 패턴을 매핑한 후, doGet() 내부의 코드(out.println()) 결과물을 HTTP 응답 바디에 실어 브라우저로 반환.
💡 요즘은 web.xml 대신 @WebServlet("/sayhello") 어노테이션을 사용하는 방식이 더 주류

helloservlet.war
0.00MB

더보기

💡 톰캣 구동 이후

  • 톰캣의 자동 배포(Auto Deploy) 기능: 톰캣이 구동되거나 실행 중일 때 webapps/ 폴더를 주기적으로 감시한다. 이 폴더에 새로운 .war 파일이 들어오면, 톰캣 내부의 Host 배포기(Deployment 구동체)가 이를 감지하고 자동으로 압축을 풀어 버림.
  • 압축을 푸는 이유: 자바 웹 애플리케이션이 실행되려면 WEB-INF/classes/ 안에 있는 컴파일된 클래스 파일들과 WEB-INF/lib/ 안의 라이브러리(.jar) 파일들을 자바 가상머신(JVM)이 읽을 수 있어야 함. 톰캣이 이 구조를 인식할 수 있도록 호스팅 영역에 압축을 풀어놓는 것.

2) 핵심 객체 및 컴포넌트 개념 비교

  • HttpServletRequest / HttpServletResponse: 톰캣 웹서버가 클라이언트의 텍스트 요청(헤더+바디)을 받아 자바 객체로 변환해 서블릿의 파라미터(아규먼트)로 채워줌. 개발자가 response 객체의 out 스트림에 바디를 작성하면, 톰캣이 이를 기반으로 HTTP 응답 패킷을 완성한다.
  • 서블릿 컨테이너(Servlet Container) vs 서블릿 컨텍스트(ServletContext):
    1. 서블릿 컨테이너: 서블릿이 실행되고 관리되는 실질적인 시스템 환경으로, 요청을 알맞은 서블릿에 매핑하고 서블릿의 생명주기(생성, 초기화, 요청 처리, 소멸)를 전반적으로 관리하는 주체/핵심컴포넌트
      • 엄밀히 말하면, 톰캣의 핵심 서블릿 컨테이너 엔진(통칭 *카탈리나, Catalina)이 이 역할을 총괄하며, 내부적으로 내부 아키텍처(Engine, Host, Context, Wrapper)를 통해 요청을 분배하고 서블릿을 구동한다.
      • 자바 엔터프라이즈(Jakarta EE) 명세에서 서블릿이 실행되는 환경을 서블릿 컨테이너 또는 서블릿 런타임 환경이라고 부름
    2. 서블릿 컨텍스트: 하나의 웹 애플리케이션(하나의 WAR 파일 단위) 영역 전체를 관리하고 공유 자원을 담는 컨테이너 내부의 환경(컨텍스트) 정보입니다.
  • 정적 서버(Apache, Nginx) vs 동적 서버(Tomcat): 정적 서버는 고정된 HTML/JS 리소스를 프록시 환경에서 빠르게 서비스하며, AJP 프로토콜 등을 통해 톰캣 전단에 서기도 함. 반면 톰캣은 요청에 따라 실시간으로 변화하는 동적 페이지를 생성.
    • Forward Proxy/Reverse Proxy 환경에서 Apache/Nginx가 앞단에 서고 톰캣이 뒷단에서 동적 처리를 하는 구조
더보기

ℹ️ 카탈리나 자세히

 

1) 톰캣과 카탈리나의 관계

  • 톰캣(Tomcat)이란? 웹 서버 기능(HTTP 요청 받기) + 서블릿 컨테이너 기능을 합친 전체 WAS(Web Application Server)의 이름.
  • 카탈리나(Catalina)란? 이 톰캣 프로그램 내부에서 서블릿 사양을 실제로 구현하고 관리하는 본체(서블릿 컨테이너 엔진)의 이름.

2) 카탈리나 서블릿 컨테이너 내부 (계층적 구조)

카탈리나 서블릿 컨테이너 내부는 계층적 구조로 이루어져 있다. Engine ➔ Host ➔ Context ➔ Wrapper 순으로 상위에서 하위로 연결

Engine (최상위 엔진)
  └── Host A (도메인: example.com)
  │     ├── Context 1 (웹앱: /shop)
  │     │     ├── Wrapper X (서블릿: OrderServlet)
  │     │     └── Wrapper Y (서블릿: ProductServlet)
  │     └── Context 2 (웹앱: /board)
  │           └── Wrapper Z (서블릿: BoardServlet)
  └── Host B (도메인: admin.example.com)
        └── Context 3 (웹앱: /ROOT)
              └── Wrapper W (서블릿: AdminServlet)
  1. Engine: 카탈리나 컨테이너의 최상위 컴포넌트. 알맞은 가상 호스트(Host)로 요청을 전달하는 대형 라우터(중앙 제어 장치) 역할을 한다.
    • 특징: 톰캣 내부에서 알맞은 커넥터(Connector)로부터 요청을 넘겨받아 중심에서 처리한다.
      • 하나 이상의 Host(가상 호스트)를 자식으로 포함.
      • 엔진 레벨에서 정의된 설정(예: 로깅, 밸브 등)은 하위의 모든 호스트와 컨텍스트에 상속.
  2. Host: www.naver.com 같은 네트워크상 가상 호스트(도메인)를 뜻함.
    • 특징:
      • 하나의 톰캣 서버에서 여러 개의 도메인(예: www.example.com, api.example.com)을 독립적으로 서비스할 수 있게 해줌.
      • 각 호스트는 내부에 여러 개의 Context(웹 애플리케이션)를 자식으로 포함.
      • 톰캣 설정 파일(server.xml)의 <Host> 태그와 매핑.
  3. Context: 하나의 웹 애플리케이션(WAR 파일 하나) 단위.
    • 특징:
      • 가장 친숙한 단위인 WAR 파일 또는 특정 웹 루트 디렉터리와 1:1로 매핑.
      • 각 Context는 자신만의 고유한 서블릿 컨텍스트(ServletContext) 경로(예: /shop, /blog)를 가짐.
      • 내부적으로 웹 애플리케이션에 포함된 여러 개의 Wrapper(서블릿)를 자식으로 관리.
  4. Wrapper: 가장 하위 단계의 컨테이너로, 개별 서블릿 하나하나를 감싸서 관리하는 컴포넌트.
    • 특징:
      • 서블릿 인스턴스의 생명주기(init, service, destroy)를 직접 감싸서 실행하고 관리.
      • 서블릿은 카탈리나 컨테이너 구조에 직접 참여할 수 없기 때문에, Wrapper가 서블릿을 감싸서 컨테이너의 구성원으로 만들어 주는 역할.
ℹ️ 덧붙임: Valve (밸브)와 Pipeline (파이프라인)
카탈리나가 이 계층 구조를 따라 요청을 전달할 때, 각 컨테이너(Engine, Host, Context, Wrapper)는 내부에 Pipeline을 가지고 있음. 이 파이프라인 안에는 Valve라는 부품들이 직렬로 연결되어 있어, 요청이 하위 컨테이너로 넘어가기 전에 인증, 로깅, IP 제한 같은 전처리 작업을 수행. (서블릿의 Filter와 유사하지만, 톰캣 자체에 종속된 기능.)