Nginx Sample
Nginx Sample
현재 작성하신 Nginx 설정 파일 구조를 바탕으로 Gzip 압축(전송량 절감)과 Keepalive(커넥션 재사용) 설정을 녹여내어 최적화했습니다.
수많은 서브도메인 블록(server {})이 존재하므로, 공통 설정은 http {} 블록 수준(또는 이 파일의 최상단 글로벌 영역)에 정의하여 중복을 줄이고 유지보수하기 쉽게 구성하는 것이 정석입니다.
1. 최적화된 Nginx 설정 스크립트
현재 사용 중인 설정 파일의 최상단에 글로벌 최적화 설정을 추가하고, 아래 개별 server 및 upstream 블록들을 수정하시면 됩니다.
# =========================================================================
# [1] 글로벌 성능 및 전송량 최적화 (Gzip & Timeout 공통 세팅)
# =========================================================================
# 텍스트 기반 데이터 전송량 감소를 위한 Gzip 최적화
gzip on;
gzip_comp_level 5; # CPU와 압축률의 최적 타협점
gzip_min_length 1024; # 1KB 이상인 경우에만 압축 수행
gzip_proxied any; # 프록시된 모든 요청에 대해 압축 적용
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on; # 브라우저 캐싱 호환성 향상
# 클라이언트와의 Keepalive 최적화
keepalive_timeout 65; # 연결 유지 시간 (초)
keepalive_requests 200; # 하나의 커넥션으로 최대 처리할 요청 수 (기본 100에서 확장)
# =========================================================================
# [2] Upstream 정의 (백엔드 Keepalive 풀 설정)
# =========================================================================
# 로컬에서 동작하는 포트별 백엔드 서비스를 그룹화하고 Keepalive 커넥션 풀을 할당합니다.
upstream local_3000 { server 127.0.0.1:3000; keepalive 32; }
upstream local_3001 { server 127.0.0.1:3001; keepalive 32; }
upstream local_3002 { server 127.0.0.1:3002; keepalive 32; }
upstream local_3003 { server 127.0.0.1:3003; keepalive 32; }
upstream local_3007 { server 127.0.0.1:3007; keepalive 32; }
upstream local_3008 { server 127.0.0.1:3008; keepalive 32; }
upstream local_3009 { server 127.0.0.1:3009; keepalive 32; }
upstream local_3010 { server 127.0.0.1:3010; keepalive 32; }
upstream local_4000 { server 127.0.0.1:4000; keepalive 32; }
upstream local_4009 { server 127.0.0.1:4009; keepalive 32; }
upstream local_8888 { server 127.0.0.1:8888; keepalive 32; }
# 기존에 있던 RustFS Upstream도 Keepalive 적용
upstream rustfs {
least_conn;
server 127.0.0.1:9000;
keepalive 32;
}
upstream rustfs-console {
least_conn;
server 127.0.0.1:9001;
keepalive 32;
}
# =========================================================================
# [3] Server 블록 최적화 (프록시 공통 헤더 및 프로토콜 적용)
# =========================================================================
# 1. jace.gnbiz.mywire.org
server {
listen 443 ssl http2 default;
listen [::]:443 ssl ipv6only=on;
server_name jace.gnbiz.mywire.org;
client_max_body_size 20M;
location / {
proxy_pass http://local_3000/;
# 백엔드 Keepalive 및 표준 프록시 헤더 추가
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
}
# 2. gnbiz.mywire.org
server {
listen 443 ssl http2;
listen [::]:443 ssl;
server_name gnbiz.mywire.org;
client_max_body_size 20M;
location / {
proxy_pass http://local_3001;
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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
}
# 3. intranet.gnbiz.mywire.org
server {
listen 443 ssl http2;
listen [::]:443 ssl;
server_name intranet.gnbiz.mywire.org;
client_max_body_size 20M;
location / {
proxy_pass http://local_3002;
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
}
# 4. class.gnbiz.mywire.org
server {
listen 443 ssl http2;
listen [::]:443 ssl;
server_name class.gnbiz.mywire.org;
client_max_body_size 20M;
location / {
proxy_pass http://local_3003;
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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
}
# 5. dashboard.gnbiz.mywire.org
server {
listen 443 ssl http2;
listen [::]:443 ssl;
server_name dashboard.gnbiz.mywire.org;
client_max_body_size 20M;
location / {
proxy_pass http://local_3007;
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
}
# 6. docs.gnbiz.mywire.org
server {
listen 443 ssl http2;
listen [::]:443 ssl;
server_name docs.gnbiz.mywire.org;
client_max_body_size 20M;
location / {
proxy_pass http://local_3008;
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
}
# 7. search.gnbiz.mywire.org
server {
listen 443 ssl http2;
listen [::]:443 ssl;
server_name search.gnbiz.mywire.org;
client_max_body_size 20M;
location / {
proxy_pass http://local_3009;
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
}
# 8. aligo.gnbiz.mywire.org
server {
listen 443 ssl http2;
listen [::]:443 ssl;
server_name aligo.gnbiz.mywire.org;
client_max_body_size 20M;
location / {
proxy_pass http://local_3010;
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
}
# 9. jupyter.gnbiz.mywire.org
server {
listen 443 ssl http2; # 가독성을 위해 http2 통일 및 일렬 정렬
listen [::]:443 ssl;
server_name jupyter.gnbiz.mywire.org;
client_max_body_size 20M;
location / {
proxy_pass http://local_8888/;
# Jupyter Notebook 필수 웹소켓 및 Keepalive 지원
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
}
# 10. DISCORD 프록시 (HTTPS 통신이므로 ssl 전용 설정 켜두기)
server {
listen 80;
server_name discord.gnbiz.mywire.org;
location / {
proxy_pass https://discord.com;
proxy_set_header Host discord.com;
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;
proxy_buffering off;
proxy_ssl_server_name on;
# 외부 통신 연결 최적화
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
# 11. s3.gnbiz.mywire.org (RustFS / MinIO 추정)
server {
listen 443 ssl http2; # http2 주석 제거 권장
listen [::]:443 ssl;
server_name s3.gnbiz.mywire.org;
ssl_certificate /etc/letsencrypt/live/gnbiz.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gnbiz.mywire.org/privkey.pem;
ignore_invalid_headers off;
client_max_body_size 0; # 대용량 파일 핸들링용 유지
proxy_buffering off;
proxy_request_buffering off;
# S3 API 구간
location /api {
proxy_set_header Host $http_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;
proxy_connect_timeout 300;
proxy_http_version 1.1;
# 웹소켓과 keepalive가 혼재할 수 있으므로 명시적 설정 제거 혹은 업스트림 대응
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
chunked_transfer_encoding off;
proxy_pass http://rustfs; # 명확하게 명시한 upstream 사용
}
# Console 구간
location / {
proxy_set_header Host $http_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;
proxy_connect_timeout 300;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
chunked_transfer_encoding off;
proxy_pass http://rustfs-console; # 명확하게 명시한 upstream 사용
}
}
# 12. jace1.mywire.org 에코시스템
server {
server_name jace1.mywire.org;
listen 443 ssl http2;
location / {
proxy_pass http://local_4000;
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/jace1.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/jace1.mywire.org/privkey.pem;
}
server {
server_name docs.jace1.mywire.org;
listen 443 ssl http2;
location / {
proxy_pass http://local_4009;
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/jace1.mywire.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/jace1.mywire.org/privkey.pem;
}
# =========================================================================
# [4] HTTP ➡️ HTTPS 리다이렉트 블록들 (기존 구조 보존)
# =========================================================================
server {
if ($host = gnbiz.mywire.org) { return 301 https://$host$request_uri; }
listen 80 default;
listen [::]:80 default;
server_name gnbiz.mywire.org;
return 404;
}
server {
if ($host = dashboard.gnbiz.mywire.org) { return 301 https://$host$request_uri; }
listen 80;
listen [::]:80;
server_name dashboard.gnbiz.mywire.org;
return 404;
}
server {
if ($host = jupyter.gnbiz.mywire.org) { return 301 https://$host$request_uri; }
server_name jupyter.gnbiz.mywire.org;
listen 80;
return 404;
}
2. 주요 변경 및 최적화 포인트 설명
① 글로벌 Gzip 압축 활성화 (데이터량 절감 핵심)
- 파일 최상단에
gzip on;설정을 추가했습니다. JSON 데이터(application/json), 텍스트, 자바스크립트 등 프록시를 통해 나가는 API 결과물을 온더플라이로 압축하여 대역폭 소모를 대폭 줄입니다. - 압축률은 CPU 부하가 크지 않고 효율이 좋은
gzip_comp_level 5;로 세팅했습니다. - 이미지 파일이나 이미 인코딩된 대용량 이진 데이터(S3 업/다운로드 등)는 Gzip이 알아서 압축 대상에서 제외하므로 성능 낭비가 없습니다.
② Upstream을 활용한 Backend Keepalive 구현 (CPU 및 연결 지연 개선)
- Nginx에서 백엔드 앱(예: Node.js, RustFS 등)으로
proxy_pass할 때 원래는 매번 새로운 TCP 소켓 커넥션을 맺고 끊었습니다. - 이를 개선하기 위해 각 포트마다
upstream풀을 생성하고keepalive 32;를 지정했습니다. Nginx가 로컬 백엔드 서버와 최대 32개의 상시 통신 통로를 유지하므로, 서버의 CPU 오버헤드와 API 응답 지연 시간이 극적으로 감소합니다. - 백엔드 Keepalive를 작동시키기 위해 각
location /마다 아래의 필수 프로토콜 명시를 적용했습니다.
proxy_http_version 1.1;
proxy_set_header Connection "";
③ 누락된 Proxy 헤더 표준화 및 정리
- 기존 설정에서 일부 서버 블록(예:
intranet,dashboard,docs등)에는Host,X-Real-IP,X-Forwarded-For같은 중요 헤더들이 누락되어 있어 백엔드 앱이 클라이언트의 실제 IP나 도메인명을 파악하기 어려운 상태였습니다. 최적화 과정에서 모든 블록에 표준 프록시 헤더를 누락 없이 채워 넣었습니다.
④ HTTP/2 적극 활성화
- 주석 처리되어 있거나 일부 빠져있던
http2선언을 SSL 리슨 포트(listen 443 ssl http2;)에 명시했습니다. 클라이언트와 Nginx 구간의 멀티플렉싱 통신을 극대화하여 프론트엔드 자원 로딩 속도를 가속화합니다.
3. Brotli 사용 가능 여부 팁 (선택 사항)
만약 데이터량을 Gzip보다 한 단계 더 획기적으로(약 20% 이상 추가) 줄이고 싶다면 Brotli가 좋은 대안입니다.
다만, Brotli는 Nginx에 기본 탑재되어 있지 않아 OS 패키지(예: nginx-mod-http-brotli)를 별도로 설치하거나 Nginx를 소스 컴파일해야 활성화할 수 있습니다. 만약 우분투/데비안 환경에서 Brotli 모듈이 설치되어 있다면 최상단 글로벌 영역에 아래 설정을 Gzip과 함께 추가해주시면 완벽히 호환됩니다.
# Brotli 모듈이 설치되어 있을 경우 글로벌 영역에 추가 가능
brotli on;
brotli_comp_level 4; # 동적 API 압축용 적정 레벨
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
설정을 모두 수정한 후에는 반드시 터미널에서 구문 체크를 하신 후 Nginx를 재시작해 주세요.
sudo nginx -t
sudo systemctl reload nginx