본문으로 건너뛰기
Advertisement

mod_proxy_http 설정 — 현대적 Apache+Tomcat 연동

mod_proxy_http는 표준 HTTP/1.1로 Tomcat과 통신하는 방식으로, 신규 Apache+Tomcat 연동의 권장 방법입니다. AJP 취약점이 없고 설정이 단순하며, SSL Termination, 헤더 제어, 로드밸런싱까지 Apache 표준 기능을 그대로 활용할 수 있습니다.


모듈 활성화

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers
sudo a2enmod rewrite
sudo systemctl reload apache2

apache2ctl -M | grep "proxy_http"
# proxy_http_module (shared)

기본 설정

# /etc/apache2/sites-available/myapp.conf

<VirtualHost *:80>
ServerName example.com

ProxyRequests Off # 포워드 프록시 비활성화
ProxyPreserveHost On # 원래 Host 헤더 유지

ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

완전한 프로덕션 설정

# /etc/apache2/sites-available/myapp-ssl.conf

<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com

# HTTPS 리다이렉트
RewriteEngine On
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>

<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com

# SSL 설정
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256

# 실제 클라이언트 IP 전달
RequestHeader set X-Real-IP "%{REMOTE_ADDR}s"
RequestHeader set X-Forwarded-For "%{X-Forwarded-For}e env=HTTP_X_FORWARDED_FOR"
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s" env=!HTTP_X_FORWARDED_FOR
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}s"

# 보안 헤더
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

# 프록시 설정
ProxyRequests Off
ProxyPreserveHost On

# 정적 파일 제외
ProxyPass /static !
ProxyPass /favicon.ico !
ProxyPass /robots.txt !

# 동적 요청 → Tomcat
ProxyPass / http://127.0.0.1:8080/ connectiontimeout=10 timeout=60
ProxyPassReverse / http://127.0.0.1:8080/

# 정적 파일 직접 서빙
Alias /static /var/www/myapp/static
<Directory "/var/www/myapp/static">
Options -Indexes
AllowOverride None
Require all granted
</Directory>

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
</IfModule>

# 로그
CustomLog ${APACHE_LOG_DIR}/myapp_access.log combined
ErrorLog ${APACHE_LOG_DIR}/myapp_error.log
</VirtualHost>

ProxyPass 경로 처리

ProxyPass의 경로 변환 규칙을 이해하는 것이 중요합니다.

# 경로 그대로 전달
ProxyPass /app/ http://127.0.0.1:8080/app/
# /app/users → http://127.0.0.1:8080/app/users

# 경로 변환 (슬래시 주의)
ProxyPass /app/ http://127.0.0.1:8080/
# /app/users → http://127.0.0.1:8080/users

# API 경로 분기
ProxyPass /api/v1/ http://127.0.0.1:8080/api/
# /api/v1/users → http://127.0.0.1:8080/api/users

ProxyPass 순서: 더 구체적인 경로를 먼저 작성합니다.

# 올바른 순서 (구체적인 경로 먼저)
ProxyPass /api/admin http://127.0.0.1:8081/admin
ProxyPass /api/ http://127.0.0.1:8080/api/
ProxyPass / http://127.0.0.1:8080/

# 잘못된 순서 (/ 가 모든 요청을 잡아버림)
ProxyPass / http://127.0.0.1:8080/ # 먼저 작성하면 안 됨
ProxyPass /api/ http://127.0.0.1:8080/api/ # 도달 불가

쿠키 경로 재작성 (ProxyPassReverseCookiePath)

Tomcat이 /myapp/으로 설정된 쿠키 경로를 /로 변환해야 할 때 사용합니다.

# Tomcat이 Set-Cookie: Path=/myapp/ 설정 시
# 클라이언트는 Apache를 통해 /로 접근하므로 불일치 발생

ProxyPassReverseCookiePath /myapp/ /
ProxyPassReverseCookieDomain 127.0.0.1 example.com

타임아웃과 재시도 설정

# 글로벌 프록시 타임아웃
ProxyTimeout 60

# ProxyPass 개별 속성
ProxyPass / http://127.0.0.1:8080/ \
connectiontimeout=10 \
timeout=60 \
retry=5 \
acquire=3000 \
max=100 \
ttl=300

# keepalive 연결 재사용
SetEnv proxy-nokeepalive 0 # keepalive 활성화
SetEnv proxy-initial-not-pooled 0 # 연결 풀 사용
속성설명
connectiontimeout연결 수립 대기 시간(초)
timeout응답 대기 시간(초)
retry오류 후 재시도 간격(초), 0이면 즉시
acquire연결 풀 대기 시간(ms)
max최대 연결 수
ttl연결 재사용 최대 시간(초)

로드밸런싱

sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests
sudo a2enmod lbmethod_bybusyness
<Proxy "balancer://tomcatcluster">
# 멤버 추가
BalancerMember "http://127.0.0.1:8080" route=tomcat1 loadfactor=1
BalancerMember "http://192.168.1.11:8080" route=tomcat2 loadfactor=1

# 백업 서버 (모든 메인이 다운됐을 때)
BalancerMember "http://192.168.1.12:8080" status=+H

# 로드밸런싱 설정
ProxySet lbmethod=bybusyness # bybusyness: 바쁘지 않은 서버 우선
ProxySet stickysession=JSESSIONID # 세션 고정
ProxySet nofailover=Off # 장애 시 다른 서버로 전환 허용
</Proxy>

ProxyPass / balancer://tomcatcluster/
ProxyPassReverse / balancer://tomcatcluster/

# 밸런서 관리 페이지
<Location /balancer-manager>
SetHandler balancer-manager
Require ip 127.0.0.1 10.0.0.0/8
</Location>

헬스체크 설정

# Apache 2.4.55+ 내장 헬스체크
<Proxy "balancer://tomcatcluster">
BalancerMember "http://127.0.0.1:8080" hcmethod=GET hcuri=/actuator/health hcinterval=10
BalancerMember "http://192.168.1.11:8080" hcmethod=GET hcuri=/actuator/health hcinterval=10
ProxySet lbmethod=byrequests
</Proxy>

Summary

항목설정
필수 모듈proxy + proxy_http
기본 지시어ProxyPass + ProxyPassReverse
실제 IP 전달RequestHeader set X-Forwarded-For/Proto
정적 파일 제외ProxyPass /static !
로드밸런싱proxy_balancer + stickysession=JSESSIONID
쿠키 경로ProxyPassReverseCookiePath
타임아웃ProxyTimeout + connectiontimeout=10 timeout=60
Advertisement