Apache HTTP Server ์นํธ์ํธ ํต์ฌ ๋ช
๋ น์ด ๋ฐ ์ค์ ๊ฐ์ด๋
apachectl/httpd ์ ์ด, ๊ฐ์ ํธ์คํธ(VirtualHost), ๋ฆฌ๋ฒ์ค ํ๋ก์(mod_proxy), URL ์ฌ์์ฑ(mod_rewrite/.htaccess), SSL/TLS(HTTPS), ๋ณด์ ๋ฐ MPM ์ฑ๋ฅ ํ๋
## 1. CLI ์๋น์ค ์ ์ด & ๋ฌธ๋ฒ ๊ฒ์ฌ (Service Control & CLI)
```bash
# ๐ชถ [1] ์ค์ ํ์ผ ๋ฌธ๋ฒ ๊ฒ์ฌ (Syntax Check - ์ค์ ๋ณ๊ฒฝ ํ ํ์!)
apachectl configtest # ๋๋ httpd -t
# ๊ตฌ์ฒด์ ์ธ ๊ฐ์ ํธ์คํธ(VirtualHost) ๋ฐ์ธ๋ฉ ๋ชฉ๋ก ํ์ธ
apachectl -S # ๋๋ httpd -S
# ๐ [2] ๋ฌด์ค๋จ ์์ ๋ฆฌ๋ก๋ (Graceful Reload) vs ์ฌ์์
apachectl graceful # ์ฒ๋ฆฌ ์ค์ธ ์์ฒญ ์๋ฃ ํ ์์ ํ๊ฒ ์ค์ ๋ฆฌ๋ก๋ (๊ถ์ฅ)
apachectl restart # ์ฆ์ ์ค์ง ํ ์ฌ์์
apachectl stop # Apache ์ค์ง
# ๐ง [3] systemd ์๋น์ค ๊ด๋ฆฌ (Linux)
# Ubuntu / Debian
sudo systemctl status apache2
sudo systemctl reload apache2
sudo systemctl restart apache2
# RHEL / CentOS / Rocky
sudo systemctl status httpd
sudo systemctl reload httpd
sudo systemctl restart httpd
# ๐ฆ [4] ํ์ฑํ๋ ๋ชจ๋ ๋ฐ ๋ฒ์ ํ์ธ
apachectl -M # ๋๋ httpd -M (๋ก๋๋ ์ ์ฒด ๋ชจ๋ ๋ชฉ๋ก)
apachectl -V # ์์ธ ๋น๋ ์ ๋ณด ๋ฐ MPM ๋ชจ๋ ํ์ธ
```
## 2. ๋ฐฐํฌํ๋ณ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ & ๋ชจ๋ ํ์ฑํ
| ๊ตฌ๋ถ | Ubuntu / Debian (`apache2`) | RHEL / CentOS (`httpd`) |
|---|---|---|
| **๋ฉ์ธ ์ค์ ํ์ผ** | `/etc/apache2/apache2.conf` | `/etc/httpd/conf/httpd.conf` |
| **ํฌํธ ์ค์ ** | `/etc/apache2/ports.conf` | ๋ฉ์ธ ์ค์ ๋ด `Listen 80` |
| **๊ฐ์ ํธ์คํธ** | `/etc/apache2/sites-available/` | `/etc/httpd/conf.d/*.conf` |
| **๋ชจ๋ ๋๋ ํ ๋ฆฌ** | `/etc/apache2/mods-available/` | `/etc/httpd/conf.modules.d/` |
| **๊ธฐ๋ณธ DocumentRoot** | `/var/www/html` | `/var/www/html` |
| **๊ธฐ๋ณธ ๋ก๊ทธ ๊ฒฝ๋ก** | `/var/log/apache2/` | `/var/log/httpd/` |
```bash
# Ubuntu/Debian ์ ์ฉ ๋ชจ๋ ๋ฐ ์ฌ์ดํธ ํ์ฑํ CLI
sudo a2enmod rewrite ssl proxy proxy_http headers deflate # ๋ชจ๋ ํ์ฑํ
sudo a2dismod autoindex # ๋ชจ๋ ๋นํ์ฑํ
sudo a2ensite my-site.conf # ๊ฐ์ ํธ์คํธ ํ์ฑํ
sudo a2dissite 000-default.conf # ๊ธฐ๋ณธ ์ฌ์ดํธ ๋นํ์ฑํ
```
## 3. ๊ธฐ๋ณธ ๊ฐ์ ํธ์คํธ (VirtualHost: ํฌํธ 80)
```apache
# /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ServerAdmin admin@example.com
DocumentRoot /var/www/example.com/public_html
# ๋๋ ํ ๋ฆฌ๋ณ ์ ๊ทผ ๊ถํ ์ค์
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks # -Indexes: ํ์ผ ๋ชฉ๋ก ๋
ธ์ถ ์ฐจ๋จ
AllowOverride All # .htaccess ํ์ผ ์ฌ์ฉ ํ์ฉ (None: ๋ฌด์)
Require all granted # ๋ชจ๋ ํด๋ผ์ด์ธํธ ์ ๊ทผ ํ๊ฐ
</Directory>
# ์๋ฌ ๋ฐ ์ก์ธ์ค ๋ก๊ทธ ๊ฒฝ๋ก
ErrorLog ${APACHE_LOG_DIR}/example_error.log
CustomLog ${APACHE_LOG_DIR}/example_access.log combined
</VirtualHost>
```
## 4. ๋ฆฌ๋ฒ์ค ํ๋ก์ (Reverse Proxy & Load Balancer)
Spring Boot, Node.js, Tomcat ๋ฑ์ผ๋ก ํธ๋ํฝ์ ํ๋ก์ ์ ๋ฌํ ๋ ์ฌ์ฉ (`mod_proxy`, `mod_proxy_http` ํ์).
```apache
<VirtualHost *:80>
ServerName api.example.com
# ํ๋ก์ ์ค์
ProxyRequests Off # Forward Proxy ๋นํ์ฑํ (๋ณด์ ํ์)
ProxyPreserveHost On # ์๋ณธ ์์ฒญ์ Host ํค๋๋ฅผ ๋ฐฑ์๋๋ก ๋ณด์กด ์ ๋ฌ
ProxyAddHeaders On # X-Forwarded-For, X-Forwarded-Host ์๋ ์ถ๊ฐ
# [1] ๋จ์ผ ๋ฐฑ์๋ ํ๋ก์ (ํฌํธ 8080)
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
# [2] ๋ก๋ ๋ฐธ๋ฐ์ฑ (Round Robin)
<Proxy "balancer://mycluster">
BalancerMember http://192.168.1.11:8080 route=node1
BalancerMember http://192.168.1.12:8080 route=node2
ProxySet lbmethod=byrequests
</Proxy>
# ProxyPass / balancer://mycluster/
# ProxyPassReverse / balancer://mycluster/
</VirtualHost>
```
## 5. URL ์ฌ์์ฑ (mod_rewrite) & .htaccess
SPA(Vue/React) ๋ผ์ฐํ
๋ฐ 301 ์๊ตฌ ๋ฆฌ๋ค์ด๋ ํธ ํจํด (`RewriteEngine On` ํ์).
```apache
# [1] HTTP -> HTTPS ๋ฌด์กฐ๊ฑด ์๊ตฌ ๋ฆฌ๋ค์ด๋ ํธ (301)
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# [2] WWW ์๋ ๋๋ฉ์ธ์ผ๋ก ํตํฉ (example.com)
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
# [3] Vue / React / Angular SPA ๋ผ์ฐํ
(HTML5 History Mode Fallback)
<Directory /var/www/spa/dist>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f # ์ค์ ํ์ผ์ด ์๋๋ฉด
RewriteCond %{REQUEST_FILENAME} !-d # ์ค์ ๋๋ ํ ๋ฆฌ๊ฐ ์๋๋ฉด
RewriteRule . /index.html [L] # index.html๋ก ๋ด๋ถ ํฌ์๋ฉ
</Directory>
```
- `[NC]`: No Case (๋์๋ฌธ์ ๋ฌด์)
- `[L]`: Last (์ด ๊ท์น์ด ๋งค์นญ๋๋ฉด ๋ค์ Rewrite ๊ท์น ๊ฑด๋๋)
- `[R=301]`: HTTP 301 ์๊ตฌ ๋ฆฌ๋ค์ด๋ ํธ (๊ฒ์์์ง SEO ์ต์ ํ)
## 6. SSL/TLS (HTTPS: ํฌํธ 443) ๋ณด์ ์ค์
```apache
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# SSL ํ์ฑํ ๋ฐ ์ธ์ฆ์ ๊ฒฝ๋ก (Let's Encrypt ํ์ค ์์)
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# ๋ชจ๋ ๋ณด์ ํ๋กํ ์ฝ ๋ฐ ์ํธํ ์ค์ํธ (TLS 1.2, 1.3๋ง ํ์ฉ)
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES
SSLHonorCipherOrder on
# HSTS ํ์ฑํ (๋ธ๋ผ์ฐ์ ์ HTTPS ์ ์ ๊ฐ์ , 6๊ฐ์)
Header always set Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
</VirtualHost>
```
## 7. ๋ณด์ ๊ฐํ, Gzip ์์ถ & ๋ธ๋ผ์ฐ์ ์บ์ฑ
```apache
# ๐ [1] ์๋ฒ ๋ฒ์ ์ ๋ณด ์๋ (๋ณด์ ํ์)
ServerTokens Prod # Server ํค๋์ 'Apache'๋ง ๋
ธ์ถ (OS ๋ฐ ์ธ๋ถ๋ฒ์ ์จ๊น)
ServerSignature Off # ์๋ฌ ํ์ด์ง ํ๋จ ์๋ฒ ์ ๋ณด ์ถ๋ ฅ ๋นํ์ฑํ
# ๐ก๏ธ [2] ํ์ ๋ณด์ ์๋ต ํค๋ ์ถ๊ฐ (mod_headers)
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# ๐๏ธ [3] Gzip ํ
์คํธ ์์ถ ์ ์ก (mod_deflate)
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
AddOutputFilterByType DEFLATE application/javascript application/json application/xml
</IfModule>
# โก [4] ๋ธ๋ผ์ฐ์ ์บ์ฑ ๋ง๋ฃ ์๊ฐ ์ค์ (mod_expires)
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/css "access plus 1 week"
ExpiresByType application/javascript "access plus 1 week"
</IfModule>
```
## 8. MPM ๋ชจ๋ & ์ฑ๋ฅ ์ต์ ํ (Event MPM ๊ถ์ฅ)
Apache 2.4+ ํ๊ฒฝ์์๋ ๊ณ ์ฑ๋ฅ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ `mpm_event`๊ฐ ๊ธฐ๋ณธ ๊ถ์ฅ๋ฉ๋๋ค.
```apache
# /etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
StartServers 3 # ์ด๊ธฐ ๊ธฐ๋ํ ํ๋ก์ธ์ค ์
MinSpareThreads 75 # ์ต์ ์ ํด ์ค๋ ๋ ์
MaxSpareThreads 250 # ์ต๋ ์ ํด ์ค๋ ๋ ์
ThreadsPerChild 25 # ์์ ํ๋ก์ธ์ค๋น ์์ฑํ ์ค๋ ๋ ์
MaxRequestWorkers 400 # ๋์ ์ฒ๋ฆฌ ๊ฐ๋ฅํ ์ต๋ ํด๋ผ์ด์ธํธ ์์ฒญ ์
MaxConnectionsPerChild 0 # ํ๋ก์ธ์ค ์ฌ์ฌ์ฉ ํ์ (0: ๋ฌด์ ํ)
</IfModule>
# KeepAlive ์ปค๋ฅ์
์ฌ์ฌ์ฉ ์ค์
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5 # ์ ํด ์ฐ๊ฒฐ ์ ์ง ์๊ฐ (์ด ๋จ์)
```
์๊ฒฌ ๋ฐ ์ง๋ฌธ
0์์ง ๋ฑ๋ก๋ ์๊ฒฌ์ด ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋๊ธ์ ๋จ๊ฒจ๋ณด์ธ์!
๋๊ธ ์์
๋๊ธ ์ญ์