Apache + Tomcat 연동 방식 3종 비교
Apache HTTPD와 Tomcat을 연동하는 방법은 크게 세 가지입니다: mod_jk, mod_proxy_ajp, mod_proxy_http. 각 방식의 동작 원리와 장단점을 이해하고 상황에 맞는 방식을 선택하는 것이 중요합니다.
연동 방식 개요
[클라이언트]
↓ HTTP/HTTPS
[Apache HTTPD :80/:443]
↓ (연동 방식에 따라 다름)
├── mod_jk → AJP :8009 → [Tomcat]
├── mod_proxy_ajp → AJP :8009 → [Tomcat]
└── mod_proxy_http → HTTP :8080 → [Tomcat]
3가지 연동 방식 비교
| 항목 | mod_jk | mod_proxy_ajp | mod_proxy_http |
|---|---|---|---|
| 프로토콜 | AJP (바이너리) | AJP (바이너리) | HTTP/1.1 (텍스트) |
| 모듈 기원 | 별도 프로젝트 (tomcat-connectors) | Apache 내장 | Apache 내장 |
| 설치 복잡도 | 높음 (컴파일 필요) | 낮음 (기본 포함) | 낮음 (기본 포함) |
| 설정 파일 | workers.properties 별도 | httpd.conf/VirtualHost | httpd.conf/VirtualHost |
| 로드밸런싱 | 내장 (lbmethod) | Apache 내장 balancer | Apache 내장 balancer |
| 세션 고정 | jvmRoute 기반 | 가능 | 가능 |
| 보안 이슈 | Ghostcat CVE-2020-1938 | Ghostcat CVE-2020-1938 | 없음 |
| 현재 상태 | 레거시 (개발 중단) | 유지 중 | ** 현대 권장** |
| 권장 신규 사용 | ❌ | ⚠️ 레거시 전용 | ✅ |
mod_jk — 레거시 방식
mod_jk는 Apache Tomcat Connectors 프로젝트에서 관리하는 별도 모듈로, AJP 프로토콜로 Tomcat과 통신합니다. 2000년대 초반부터 널리 쓰였으나, 현재는 mod_proxy_http로 전환이 권장됩니다.
구조:
Apache (mod_jk.so 로드)
↓ AJP 바이너리 프로토콜
Tomcat :8009 (AJP 커넥터)
사용하는 경우:
- 기존 mod_jk 기반 시스템 유지보수
- workers.properties 기반의 복잡한 로드밸런싱 구성
mod_proxy_ajp — 절충안
mod_proxy_ajp는 Apache 내장 프록시 모듈을 AJP 프로토콜에 적용한 방식입니다. mod_jk보다 설정이 단순하지만 AJP를 사용한다는 점에서 Ghostcat 취약점 주의가 필요합니다.
구조:
Apache (mod_proxy + mod_proxy_ajp)
↓ AJP 바이너리
Tomcat :8009 (secretRequired=true 필수)
사용하는 경우:
- mod_jk에서 mod_proxy로 단계적 전환 중인 레거시 환경
- AJP가 이미 활성화된 시스템
mod_proxy_http — 현대 권장
mod_proxy_http는 표준 HTTP/1.1로 Tomcat과 통신합니다. 설정이 간단하고 Ghostcat 취약점이 없으며, SSL 종료와 헤더 관리가 쉽습니다.
구조:
Apache (mod_proxy + mod_proxy_http)
↓ HTTP/1.1 텍스트
Tomcat :8080 (HTTP 커넥터, address=127.0.0.1)
사용하는 경우:
- 신규 프로젝트 (항상 이 방식)
- 레거시 시스템의 mod_jk → HTTP 프록시 마이그레이션
포트 구성
외부 방화벽:
허용: 80 (HTTP), 443 (HTTPS)
차단: 8080 (Tomcat HTTP), 8009 (Tomcat AJP)
서버 내부:
Apache :80/:443 → Tomcat :8080 (mod_proxy_http)
Apache :80/:443 → Tomcat :8009 (mod_jk / mod_proxy_ajp)
Tomcat 수신 주소 제한 (server.xml)
<!-- HTTP 커넥터: 로컬에서만 수신 -->
<Connector port="8080" protocol="HTTP/1.1"
address="127.0.0.1"
connectionTimeout="20000"/>
<!-- AJP 커넥터 (사용 시): 로컬에서만, 시크릿 필수 -->
<Connector protocol="AJP/1.3"
address="127.0.0.1"
port="8009"
secretRequired="true"
secret="ChangeThisSecret!"/>
필요 모듈 활성화
# mod_proxy_http (권장)
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests
sudo a2enmod headers
sudo a2enmod rewrite
# mod_proxy_ajp (AJP 사용 시)
sudo a2enmod proxy_ajp
# 재시작
sudo systemctl reload apache2
sudo apache2ctl configtest
선택 가이드
신규 프로젝트?
→ mod_proxy_http ✅
기존 mod_jk 사용 중?
→ 단기 유지 가능, 장기적으로 mod_proxy_http 전환 계획 수립
기존 mod_proxy_ajp 사용 중?
→ Tomcat secretRequired 설정 확인 후 유지 또는 mod_proxy_http 전환
보안 감사/컴플라이언스 요구?
→ AJP 완전 비활성화 + mod_proxy_http
Summary
| 방식 | 상태 | 권장 |
|---|---|---|
| mod_jk | 레거시 (개발 중단) | 기존 시스템 유지보수만 |
| mod_proxy_ajp | 유지 중 | 레거시 전환 중간 단계 |
| mod_proxy_http | 활성 개발 중 | 신규/마이그레이션 모두 |