Nginx와 Apache는 세계에서 가장 널리 배포된 웹 서버입니다.
아키텍처: 근본적인 차이
Nginx와 Apache의 핵심 아키텍처 차이가 성능을 결정합니다.
Apache: 프로세스/스레드 기반
Apache는 멀티 프로세싱 모듈(MPM) 아키텍처를 사용합니다.
Apache Architecture (Process/Thread Model):
Master Process
├── Worker Process 1
│ ├── Thread 1 → handles connection A
│ ├── Thread 2 → handles connection B
│ └── Thread N → handles connection C
├── Worker Process 2
│ ├── Thread 1 → handles connection D
│ └── Thread N → handles connection E
└── Worker Process N...
MPM Modes:
- prefork: 1 process per connection (safe for non-thread-safe modules like mod_php)
- worker: threads within process pool (more efficient)
- event: listener thread for keep-alive (best for Apache 2.4+)Nginx: 이벤트 기반, 논블로킹
Nginx는 비동기 이벤트 기반 아키텍처를 사용합니다.
Nginx Architecture (Event-Driven):
Master Process (reads config, manages workers)
├── Worker Process 1 (single thread, event loop)
│ └── Event Loop: handles 1000s of connections via epoll/kqueue
│ ├── Connection A (non-blocking I/O)
│ ├── Connection B (non-blocking I/O)
│ ├── Connection C (non-blocking I/O)
│ └── ... (thousands more)
├── Worker Process 2 (single thread, event loop)
│ └── Event Loop: handles 1000s more connections
└── Worker Process N (typically = CPU cores)
Key: No thread-per-connection overhead
Result: 10K+ connections with ~30-50MB RAM성능 벤치마크
워크로드 유형에 따라 다릅니다.
| 지표 | Apache 2.4 | Nginx 1.27 |
|---|---|---|
| 정적 파일 (요청/초) | ~15,000-25,000 | ~50,000-100,000 |
| 동시 연결 (10K) | 성능 저하 | 안정적 |
| 10K 연결 메모리 | ~300-600MB | ~30-50MB |
| PHP | mod_php/PHP-FPM | PHP-FPM |
| 리버스 프록시 | 양호 | 우수 |
| SSL/TLS | 양호 | 우수 |
설정 비교
Apache와 Nginx는 설정 방식이 다릅니다.
Apache: .htaccess + httpd.conf
Apache는 .htaccess를 통한 분산 설정을 지원합니다.
# Apache Virtual Host Configuration (/etc/apache2/sites-available/example.conf)
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example/public
<Directory /var/www/example/public>
AllowOverride All
Require all granted
Options -Indexes +FollowSymLinks
</Directory>
# Enable mod_rewrite
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# PHP via mod_php (prefork MPM required)
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
# Or PHP via PHP-FPM (recommended with event MPM)
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>
# Logging
ErrorLog ${APACHE_LOG_DIR}/example-error.log
CustomLog ${APACHE_LOG_DIR}/example-access.log combined
</VirtualHost>
# .htaccess file (per-directory, no restart needed)
# /var/www/example/public/.htaccess
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]Nginx: 중앙 집중식 설정
Nginx는 중앙 집중식 설정 파일을 사용합니다.
# Nginx Server Block (/etc/nginx/sites-available/example.conf)
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/example/public;
index index.html index.php;
# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Static files with caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# PHP via PHP-FPM
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# SPA fallback (equivalent to .htaccess rewrite)
location / {
try_files $uri $uri/ /index.html;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;
access_log /var/log/nginx/example-access.log;
error_log /var/log/nginx/example-error.log;
}기능 비교
Feature Apache 2.4 Nginx 1.27
-------------------------------------------------------------------
Module System Dynamic (load at runtime) Static + dynamic (since 1.9.11)
.htaccess Full support Not supported
URL Rewriting mod_rewrite (regex) rewrite directive (simpler)
Reverse Proxy mod_proxy + mod_proxy_http Native proxy_pass
Load Balancing mod_proxy_balancer Native upstream module
Caching mod_cache Native proxy_cache + FastCGI
WebSocket mod_proxy_wstunnel Native support
HTTP/2 mod_http2 Native
HTTP/3 (QUIC) Experimental Native since 1.25.0
Scripting mod_lua OpenResty (Lua), njs (JS)
Config Reload Restart required Graceful reload (zero downtime)
Per-dir Config .htaccess (runtime) Not available
License Apache 2.0 BSD 2-Clause사용 시나리오
Nginx를 선택할 때:
- 높은 트래픽
- 리버스 프록시
- 로드 밸런싱
- 정적 콘텐츠
Apache를 선택할 때:
- 공유 호스팅
- WordPress/PHP
- 동적 모듈
함께 사용
Nginx를 Apache 앞의 리버스 프록시로 사용하는 것이 인기 있는 아키텍처입니다.
# Nginx as reverse proxy in front of Apache
# /etc/nginx/sites-available/example.conf
upstream apache_backend {
server 127.0.0.1:8080; # Apache listens on port 8080
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Nginx serves static files directly (fast)
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2)$ {
root /var/www/example/public;
expires 30d;
access_log off;
}
# Dynamic requests go to Apache (PHP, .htaccess)
location / {
proxy_pass http://apache_backend;
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;
}
}리버스 프록시 설정
# Nginx reverse proxy to Node.js / Python / Go backend
upstream app_servers {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
keepalive 64;
}
server {
listen 443 ssl http2;
server_name api.example.com;
location / {
proxy_pass http://app_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}로드 밸런싱
# Nginx Load Balancing Strategies
# Round Robin (default)
upstream backend_rr {
server 10.0.0.1:8080;
server 10.0.0.2:8080;
server 10.0.0.3:8080;
}
# Weighted Round Robin
upstream backend_weighted {
server 10.0.0.1:8080 weight=5; # gets 5x traffic
server 10.0.0.2:8080 weight=3;
server 10.0.0.3:8080 weight=1;
}
# Least Connections
upstream backend_least {
least_conn;
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
# IP Hash (sticky sessions)
upstream backend_ip {
ip_hash;
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
# Health checks and failover
upstream backend_health {
server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.3:8080 backup; # only used when others fail
}SSL/TLS 설정
# Nginx SSL/TLS Best Practices (2026)
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
# Modern TLS configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
# Session resumption
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# HSTS (15768000 seconds = 6 months)
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
}보안 비교
두 서버 모두 우수한 보안 기록을 가지고 있습니다.
Security Aspect Apache Nginx
-----------------------------------------------------------------
CVE History More CVEs (larger surface) Fewer CVEs (smaller codebase)
.htaccess Risk Can expose config errors N/A (no .htaccess)
Default Config Permissive Restrictive
Module Surface Large (many loaded) Minimal (compile what you need)
Rate Limiting mod_ratelimit limit_req / limit_conn (native)
WAF Integration mod_security (mature) ModSecurity + NAXSI
Access Control .htaccess / <Directory> allow/deny directives
Request Size Limits LimitRequestBody client_max_body_size자주 묻는 질문
Nginx가 Apache보다 빠른가요?
정적 콘텐츠와 높은 동시성에서 Nginx가 빠릅니다. 동적 콘텐츠에서는 비슷합니다.
Nginx가 Apache를 완전히 대체할 수 있나요?
대부분의 경우 가능합니다. .htaccess가 필요한 경우 제외.
WordPress에는 어느 것이 좋은가요?
Apache가 전통적이지만, Nginx가 적절히 설정되면 더 빠릅니다.
Nginx를 Apache의 리버스 프록시로 사용해야 하나요?
두 가지의 장점을 모두 얻을 수 있는 인기 있는 패턴입니다.
Caddy와 Traefik은?
Caddy는 간단한 배포에, Traefik은 컨테이너 오케스트레이션에 적합합니다.
관련 도구 및 가이드
- JSON Formatter - Format Nginx/Apache JSON configs
- JSON to YAML Converter - Convert config formats
- Regex Tester - Test URL rewrite patterns
- Nginx Config Examples
- Nginx Location Block Regex Guide
- .htaccess Redirect Cheat Sheet
- DNS Record Types Guide