본문으로 건너뛰기
Advertisement

실전 고수 팁 — Apache vs Nginx 선택 기준과 공존 운영 패턴

Apache와 Nginx의 실무 선택 기준을 재정리하고, 한 서버에서 두 웹서버를 동시에 운영하는 포트 분리 패턴과 Apache 운영 시 자주 만나는 문제를 다룹니다.


Apache vs Nginx 최종 선택 기준

기준Apache 선택Nginx 선택
트래픽 규모중소 규모대규모 (초당 수천 이상)
PHP 실행mod_php (Prefork) 또는 php-fpmphp-fpm (항상)
설정 유연성.htaccess, 복잡한 mod_rewrite설정 문법 단순
모듈 다양성mod_* 매우 다양제한적 (컴파일 시 포함)
WebSocketmod_proxy_wstunnel기본 지원
정적 파일빠름 (충분)매우 빠름
메모리높음 (프로세스/스레드 기반)낮음 (이벤트 기반)
레거시 호환매우 높음 (.htaccess 등)낮음
학습 자료매우 풍부풍부
대표 용도PHP 앱, CMS(WordPress·Drupal), 레거시리버스 프록시, 고트래픽, 컨테이너

실무 결론

  • 신규 Java 백엔드 서비스: Nginx (리버스 프록시 역할 탁월)
  • WordPress·Drupal·Joomla: Apache (mod_php, .htaccess 의존 CMS)
  • 레거시 PHP 앱 유지보수: Apache (기존 .htaccess 설정 그대로 사용)
  • 마이크로서비스 API Gateway: Nginx
  • 클라우드·Kubernetes: Nginx Ingress

Apache + Nginx 공존 운영 (포트 분리 패턴)

같은 서버에서 Apache와 Nginx를 동시에 운영해야 할 때 포트를 분리하여 충돌을 방지합니다.

구성 1: Nginx 앞단 + Apache 뒷단

[인터넷] → [Nginx :80/:443] → [Apache :8080] → [PHP/CMS]

Nginx가 SSL 처리·정적 파일 서빙을 담당하고, Apache는 PHP 처리에 집중합니다.

# Apache를 8080 포트로 변경
# /etc/apache2/ports.conf
Listen 8080

# VirtualHost
<VirtualHost *:8080>
ServerName example.com
DocumentRoot /var/www/wordpress

<Directory /var/www/wordpress>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
# Nginx가 80/443 처리 후 Apache로 프록시
server {
listen 443 ssl;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# 정적 파일은 Nginx가 직접 처리
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
root /var/www/wordpress;
expires 30d;
add_header Cache-Control "public";
}

# PHP 처리는 Apache로 프록시
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

구성 2: 도메인별 역할 분리

[example.com:80]    → Nginx (React SPA + API 프록시)
[legacy.example.com:80] → Apache (레거시 PHP 앱)

HAProxy나 AWS ALB를 앞에 두고 도메인별로 다른 웹서버로 라우팅합니다.


Apache 자주 발생하는 문제와 해결책

문제 1: mod_rewrite 작동 안 함

증상: .htaccessRewriteEngine On이 무시됨

원인 1: AllowOverride None으로 설정됨

# 해결: AllowOverride All로 변경
<Directory "/var/www/html">
AllowOverride All
</Directory>

원인 2: mod_rewrite 모듈이 활성화되지 않음

# 확인
apache2ctl -M | grep rewrite

# 활성화
sudo a2enmod rewrite
sudo systemctl reload apache2

문제 2: 403 Forbidden 에러

증상: 파일은 있는데 403 에러 발생

원인 1: 파일/디렉터리 권한 문제

# 웹 루트 권한 확인
ls -la /var/www/html/

# 권한 수정 (일반적으로 755/644)
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
sudo chown -R www-data:www-data /var/www/html/

원인 2: Directory 지시어에서 Require all denied 설정

# 확인 후 수정
<Directory "/var/www/html">
Require all granted # denied → granted
</Directory>

원인 3: SELinux (CentOS/RHEL)

# SELinux 컨텍스트 확인
ls -Z /var/www/html/

# httpd가 읽을 수 있도록 컨텍스트 설정
sudo restorecon -Rv /var/www/html/

# 또는 임시로 SELinux 허용 (테스트용)
sudo setenforce 0

문제 3: 느린 응답 - HostnameLookups On

# 잘못된 설정 — DNS 조회로 인한 지연
HostnameLookups On

# 올바른 설정 — 항상 Off (기본값)
HostnameLookups Off

문제 4: MaxRequestWorkers 초과

증상: 트래픽 급증 시 "server reached MaxRequestWorkers" 경고, 새 요청 대기

# 에러 로그 확인
grep "MaxRequestWorkers" /var/log/apache2/error.log
# Event MPM 기준 조정
<IfModule mpm_event_module>
StartServers 4
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 400 # 증가
MaxConnectionsPerChild 0
</IfModule>

Apache 보안 강화 체크리스트

# 1. 서버 정보 숨기기
ServerTokens Prod
ServerSignature Off

# 2. 디렉터리 목록 비활성화
<Directory /var/www/html>
Options -Indexes
</Directory>

# 3. ETag에서 inode 제거
FileETag MTime Size

# 4. 불필요한 HTTP 메서드 차단
<LimitExcept GET POST HEAD>
Require all denied
</LimitExcept>

# 5. 심볼릭 링크 보호
<Directory /var/www/html>
Options -FollowSymLinks +SymLinksIfOwnerMatch
</Directory>

# 6. .htaccess 파일 직접 접근 차단
<Files ".ht*">
Require all denied
</Files>

# 7. 보안 헤더
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
</IfModule>

설정 변경 자동화 스크립트

#!/bin/bash
# /usr/local/bin/apache-deploy.sh

set -e

echo "=== Apache 설정 검증 ==="
if apache2ctl configtest; then
echo "✅ 문법 검증 통과"
else
echo "❌ 문법 오류 발견 - 배포 중단"
exit 1
fi

echo "=== Apache 무중단 리로드 ==="
systemctl reload apache2
echo "✅ 배포 완료"

# 상태 확인
systemctl status apache2 --no-pager | head -5

정리

상황권장
신규 프로젝트 (Java/API)Nginx 선택
WordPress·PHP CMSApache 선택
공존 운영Nginx(80/443) → Apache(8080) 프록시
403 에러권한·AllowOverride·SELinux 순서로 확인
보안 강화ServerTokens Prod + Options -Indexes + 보안 헤더
성능Event MPM + HostnameLookups Off + AllowOverride None
Advertisement