Nginx 성능 튜닝: gzip, 캐시, 커넥션 풀 설정

지난주 이커머스 사이트의 홈 로딩 시간이 4초까지 치솟았다는 알림을 받았습니다. Chrome DevTools를 열어 보니 HTML 파일은 120KB, CSS와 JS를 합치면 350KB였는데 모두 압축되지 않은 원본 파일이었습니다. 더 심각한 문제는 모든 요청이 백엔드로 전달되고 캐시 적중률은 고작 12%에 불과했다는 점입니다. 그날 밤 야근하며 2시간 동안 Nginx 설정을 조정했습니다. gzip 압축을 켜고, 캐시 전략을 보완하고, 커넥션 풀 매개변수를 손봤습니다. 다음 날 아침 다시 확인하니 홈 로딩 시간은 1.6초로 줄었고 백엔드 QPS도 거의 절반으로 감소했습니다.
이런 문제는 너무 흔합니다. 많은 사람이 Nginx를 설치한 뒤 기본 상태로 실행합니다. gzip은 기본적으로 꺼져 있고, 캐시 설정은 대충 두 줄만 추가하며, 최대 연결 수는 기본값을 그대로 씁니다. 그러다 트래픽이 몰리면 서버가 버티지 못합니다.
이 글에서는 제가 프로덕션 환경에서 검증한 Nginx 성능 튜닝 설정을 정리합니다. gzip 압축은 전송 용량을 6080% 줄이고, 캐시 적중률이 95%라면 백엔드 부하는 90% 줄일 수 있습니다. 커넥션 풀을 적절히 설정하면 동시 처리 능력도 34배 높일 수 있습니다. 각 모듈의 설정 세부 사항과 직접 겪은 문제, 실측 데이터를 하나씩 자세히 살펴보겠습니다.
1장: gzip 압축 설정 — 전송 용량 줄이기
먼저 gzip이 왜 그렇게 중요한지 알아보겠습니다. 원본 크기가 100KB인 HTML 파일을 gzip으로 압축하면 2025KB까지 줄어들 수 있습니다. 절약한 7580KB의 대역폭은 사용자에게는 더 빠른 로딩 속도를, 운영자에게는 더 낮은 트래픽 비용을 의미합니다.
제가 이 문제를 처음 실감한 것은 한 고객의 프로젝트에서였습니다. 모바일 사용자가 60%를 넘었고 상당수가 4G 네트워크로 접속했습니다. 홈 로딩에 3~4초가 걸리면서 이탈률이 70%까지 치솟았습니다. gzip을 적용하자 전송 용량이 곧바로 70% 줄었고 첫 화면 로딩 시간도 약 1.5초로 단축됐습니다.
1.1 기본 설정: 우선 작동하게 만들기
Nginx의 gzip 설정은 사실 복잡하지 않습니다. 핵심은 몇 줄뿐입니다.
http {
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
}
gzip on은 활성화 스위치이므로 별도 설명이 필요 없습니다. gzip_vary on은 매우 중요합니다. 응답 헤더에 Vary: Accept-Encoding을 추가해 CDN과 브라우저에 클라이언트의 압축 지원 여부에 따라 응답 내용이 달라진다는 사실을 알리고, 잘못된 캐시가 사용되는 것을 방지합니다.
gzip_min_length를 1000바이트로 설정하면 1KB보다 작은 파일은 압축하지 않습니다. 너무 작은 파일은 압축 효과가 크지 않고 오히려 CPU만 낭비합니다. gzip_types는 압축할 MIME 유형을 지정합니다. 기본값은 text/html만 압축하므로 CSS, JS, JSON, XML도 추가해야 합니다.
1.2 고급 설정: 압축 레벨과 MIME 유형 목록
압축 레벨은 균형이 필요한 선택입니다. Nginx의 gzip_comp_level은 1~9로 설정할 수 있습니다. 숫자가 클수록 압축률은 높아지지만 CPU 사용량도 증가합니다.
제가 진행한 테스트 결과는 다음과 같습니다.
| 압축 레벨 | HTML 압축률 | CPU 시간(ms) | 권장 환경 |
|---|---|---|---|
| 1 | 65% | 2 | CPU 자원이 빠듯한 환경 |
| 4 | 72% | 3 | 균형형(권장) |
| 6 | 75% | 5 | 대역폭이 부족한 환경(권장) |
| 9 | 78% | 12 | 극단적인 환경 |
대부분의 경우 레벨 4와 6이 가장 좋은 선택입니다. 레벨 9는 CPU 사용량이 두 배로 늘지만 압축률은 몇 퍼센트포인트만 개선되므로 효율적이지 않습니다.
아래는 제가 프로덕션 환경에서 사용하는 전체 gzip 설정입니다.
# gzip 압축 설정
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/xhtml+xml
application/x-javascript;
gzip_disable "msie6";
gzip_proxied any는 놓치기 쉬운 매개변수입니다. Nginx를 리버스 프록시로 사용할 때 백엔드 응답 헤더에 Content-Length가 없으면 기본적으로 압축하지 않습니다. any로 설정하면 조건에 맞는 모든 응답을 강제로 압축할 수 있습니다.
gzip_disable "msie6"은 구형 IE6와의 호환성을 위한 설정입니다. IE6는 gzip 지원에 문제가 있습니다. 이제 IE6는 거의 사라졌으므로 사실 이 줄은 지워도 되지만, 저는 혹시 모를 상황에 대비해 습관적으로 남겨 둡니다.
1.3 어떤 파일 유형의 효과가 가장 큰가요?
제가 측정한 데이터에 따르면 파일 유형에 따라 압축 효과에 큰 차이가 있습니다.
| 파일 유형 | 원본 크기 | 압축 후 | 압축률 |
|---|---|---|---|
| HTML | 100KB | 20~25KB | 75~80% |
| CSS | 80KB | 24~28KB | 65~70% |
| JavaScript | 120KB | 36~42KB | 65~70% |
| JSON API | 50KB | 20~25KB | 50~60% |
| 이미지/동영상 | 이미 압축됨 | 의미 없음 | 0~5% |
이미지와 동영상은 JPEG, PNG, MP4 같은 형식으로 이미 압축되어 있어 gzip을 다시 적용하면 오히려 용량이 커질 수 있습니다. 따라서 gzip_types에 image/*와 video/*를 절대 추가하지 마세요. 추가하면 역효과가 납니다.
한번은 다른 사람의 문제를 진단하다가 gzip_types에 image/jpeg를 추가해 둔 것을 발견했습니다. 그 결과 이미지 용량이 오히려 3~5% 커졌습니다. 저도 예전에 잘 몰랐을 때는 이런 초보적인 실수를 했을 겁니다. 당시에는 모든 MIME 유형을 전부 넣고 싶었으니까요.
2장: 캐시 전략 설정 — 정적 콘텐츠 가속
캐시는 성능 튜닝에서 가장 직접적인 효과를 내는 요소입니다. 제대로 설정하면 요청의 95%를 백엔드로 전달하지 않고 Nginx에서 바로 응답할 수 있습니다. 백엔드 서버는 과부하로 힘들어하는데 Nginx 캐시는 거의 활용되지 않는 시스템을 너무 많이 봤습니다. 캐시를 켜지 않은 것이 아니라 잘못 설정한 경우가 많았습니다.
2.1 proxy_cache와 fastcgi_cache 중 무엇을 선택할까요?
Nginx는 두 가지 캐시 메커니즘을 제공합니다.
- proxy_cache: 업스트림 서버의 응답을 캐시하며, 리버스 프록시 환경에 적합합니다(예: Node.js, Python, Go 서비스).
- fastcgi_cache: FastCGI 프로세스의 응답을 캐시하며, PHP-FPM 환경에 적합합니다.
무엇을 선택할지는 백엔드 기술 스택에 따라 달라집니다. PHP라면 fastcgi_cache를, Node.js, Python, Go 등을 사용한다면 proxy_cache를 선택하세요. 두 방식의 설정 논리는 거의 같으므로 여기서는 proxy_cache를 예로 들어 설명하겠습니다.
2.2 전체 proxy_cache 설정
먼저 http 블록에서 캐시 경로를 정의합니다.
http {
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=my_cache:10m
max_size=10g
inactive=60m
use_temp_path=off;
}
각 줄의 의미는 다음과 같습니다.
levels=1:2: 캐시 디렉터리 계층입니다. 1:2는 2단계 디렉터리 구조를 뜻하며 한 디렉터리에 파일이 지나치게 많아지는 것을 방지합니다.keys_zone=my_cache:10m: 캐시 영역 이름과 메타데이터 메모리 크기입니다. 10m에는 약 8만 개의 캐시 키를 저장할 수 있습니다.max_size=10g: 전체 캐시 용량의 상한입니다. 이를 초과하면 LRU 알고리즘으로 항목을 제거합니다.inactive=60m: 60분 동안 접근하지 않은 캐시는 정리됩니다.use_temp_path=off: 임시 파일 이동 비용을 피하기 위해 캐시 디렉터리에 직접 기록합니다.
그런 다음 server 또는 location에서 캐시를 활성화합니다.
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_cache my_cache;
# 캐시 유효 기간 설정
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid any 1m;
# 캐시 키 설계
proxy_cache_key $scheme$request_method$host$request_uri;
# 폴백 전략(뒤에서 자세히 설명)
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
# 응답 헤더에 캐시 상태 추가(디버깅용)
add_header X-Cache-Status $upstream_cache_status;
}
}
proxy_cache_valid는 상태 코드별 캐시 기간을 정의하는 핵심 설정입니다.
200 302 10m: 정상 응답을 10분간 캐시합니다.404 1m: 악의적인 요청이 백엔드를 계속 두드리지 않도록 404 오류를 1분간 캐시합니다.any 1m: 그 밖의 상태 코드는 1분간 캐시합니다.
2.3 캐시 키 설계와 무효화 전략
캐시 키 proxy_cache_key는 어떤 요청을 ‘동일한’ 요청으로 볼지 결정합니다. 기본값은 $scheme$proxy_host$request_uri이지만 명시적으로 다음과 같이 선언하는 것을 권장합니다.
proxy_cache_key $scheme$request_method$host$request_uri;
이렇게 하면 캐시 키에 프로토콜, 요청 메서드, 호스트 이름, 전체 URI가 포함됩니다. 사이트가 GET과 POST를 모두 지원하거나 도메인이 여러 개라면 이 설정이 더 정확합니다.
캐시 무효화는 까다로운 문제입니다. 일반적인 전략은 다음과 같습니다.
- 시간 만료:
proxy_cache_valid로 시간을 설정하고 만료 시 자동으로 무효화합니다. - 능동적 우회:
proxy_cache_bypass로 캐시를 우회합니다. - 캐시 제거: 상용판 Nginx Plus의
proxy_cache_purge를 사용합니다.
저는 보통 두 번째 방식으로 요청 헤더를 통해 제어합니다.
# 특정 요청 헤더로 캐시 우회
proxy_cache_bypass $http_x_nocache;
# 또는 특정 매개변수로 우회
proxy_cache_bypass $arg_nocache;
캐시를 새로 고쳐야 할 때 ?nocache=1을 붙이거나 X-Nocache: 1 요청 헤더를 추가하면 됩니다.
2.4 폴백 전략: 백엔드가 중단되어도 서비스 유지하기
proxy_cache_use_stale은 매우 유용한 설정입니다. 백엔드 서비스에서 오류가 발생하거나 시간이 초과됐을 때 Nginx는 즉시 오류를 반환하는 대신 만료된 캐시 콘텐츠를 제공할 수 있습니다.
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
작년 광군제 기간에 백엔드 서비스를 확장하다가 문제가 생겨 API 서비스에서 간헐적으로 502 오류가 발생했습니다. 다행히 캐시에 이 폴백 전략을 설정해 두어 사용자 접속에는 거의 영향이 없었습니다. 캐시가 몇 분 지난 상태였지만 콘텐츠는 정상적으로 반환됐습니다. 백엔드가 복구된 뒤에는 캐시도 자동으로 갱신됐습니다.
실측 데이터를 비교하면 다음과 같습니다.
| 지표 | 캐시 없음 | 캐시 적중 | 폴백 모드 |
|---|---|---|---|
| 응답 시간 | 150~200ms | 5~10ms | 5~10ms |
| 백엔드 QPS | 1000 | 50 | 0 |
| 사용자 경험 | 정상 | 정상 | 약간 느림 |
캐시가 적중하면 응답 시간이 200ms에서 5~10ms로 줄어 거의 20배 빨라집니다. 효과가 매우 분명합니다.
3장: 커넥션 풀 설정 — 고동시성 환경의 필수 요소
gzip과 캐시가 ‘어떻게 더 빠르게 전송할지’를 해결한다면 커넥션 풀은 ‘어떻게 더 많은 요청을 처리할지’를 해결합니다. 기본 설정에서 Nginx worker 하나의 최대 동시 연결 수는 1024개에 불과합니다. 트래픽이 늘면 곧바로 부족해집니다.
3.1 worker_connections: 상한을 정확히 계산하기
최대 동시 연결 수의 계산식은 다음과 같습니다.
최대 동시 연결 수 = worker_processes × worker_connections
서버에 8코어 CPU가 있고 worker_processes를 8로 설정하거나 auto로 자동 일치시키며, worker_connections를 4096으로 설정했다고 가정해 보겠습니다.
최대 동시 연결 수 = 8 × 4096 = 32768
수치만 보면 매우 커 보이지만, 요청 하나는 보통 두 개의 연결을 사용한다는 점을 기억해야 합니다. 하나는 클라이언트와 Nginx 사이, 다른 하나는 Nginx와 백엔드 사이의 연결입니다. 따라서 실제로 처리할 수 있는 동시 요청 수는 대략 이 수치의 절반입니다.
events 블록에 다음과 같이 설정합니다.
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
use epoll은 Linux의 기본값이라 명시할 필요는 없지만, 적어 두면 더 분명합니다. multi_accept on은 worker가 여러 새 연결을 동시에 받아들이게 해 고동시성 환경에서 연결 대기를 줄입니다.
3.2 클라이언트 keepalive: 연결을 재사용해 비용 줄이기
TCP 연결을 수립하려면 3-way handshake가 필요하며 적지 않은 비용이 듭니다. keepalive를 사용하면 클라이언트와 Nginx 사이의 연결을 재사용할 수 있어 요청마다 새 연결을 맺지 않아도 됩니다.
http {
keepalive_timeout 65;
keepalive_requests 1000;
}
keepalive_timeout 65는 연결을 65초 동안 유지한 뒤 종료한다는 뜻입니다. 값이 너무 크면 서버 자원을 지나치게 많이 차지하고, 너무 작으면 재사용 효과가 크지 않습니다. 60~75초가 합리적인 범위입니다.
keepalive_requests 1000은 연결 하나에서 최대 1000개의 요청을 처리한다는 뜻입니다. 값이 너무 작으면 연결이 자주 끊기고, 너무 크면 자원 누수가 생길 수 있습니다. 제가 테스트한 결과 1000은 비교적 안정적인 값입니다.
3.3 upstream keepalive: 백엔드 커넥션 풀
많은 사람이 잘 모르지만 효과가 분명한 설정입니다. Nginx와 백엔드 서비스 사이에서도 연결을 재사용해 TCP 연결을 반복해서 수립하는 비용을 줄일 수 있습니다.
upstream backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
keepalive 64;
keepalive_timeout 60s;
keepalive_requests 1000;
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
keepalive 64는 유휴 연결 64개를 풀에 유지한다는 뜻입니다. 백엔드 서비스 수에 맞춰 조정하며 일반적으로 백엔드 서버 수의 4~8배로 설정합니다.
proxy_http_version 1.1과 proxy_set_header Connection "" 두 줄은 반드시 추가해야 합니다. HTTP/1.1은 기본적으로 keepalive를 지원하며, Connection 헤더를 비워야 연결을 재사용할 수 있습니다. 이 두 줄을 쓰지 않으면 upstream keepalive가 작동하지 않습니다.
실측 결과를 비교하면 다음과 같습니다.
| 설정 | 분당 연결 수립 횟수 | CPU 비용 | 권장 환경 |
|---|---|---|---|
| upstream keepalive 없음 | 6000 | 높음 | 저트래픽 |
| keepalive 32 | 3000 | 중간 | 중간 트래픽 |
| keepalive 64 | 1500 | 낮음 | 고트래픽 |
upstream keepalive를 적용하자 연결 수립 비용이 곧바로 50% 줄었습니다. 이 설정은 고동시성 환경에서 특히 중요합니다.
3.4 권장 매개변수 요약표
환경별 권장 설정을 표로 정리했습니다.
| 매개변수 | 저트래픽(<1000 QPS) | 중간 트래픽(1000~5000 QPS) | 고트래픽(>5000 QPS) |
|---|---|---|---|
| worker_processes | auto | auto | auto |
| worker_connections | 1024 | 2048 | 4096 |
| keepalive_timeout | 60 | 65 | 75 |
| keepalive_requests | 100 | 500 | 1000 |
| upstream keepalive | 16 | 32 | 64 |
이는 출발점일 뿐이며 실제 조정은 부하 테스트 데이터를 바탕으로 해야 합니다. 저는 보통 wrk나 ab로 부하 테스트를 실행해 연결 수와 응답 시간의 변화 곡선을 확인하고 최적값을 찾습니다.
4장: 통합 설정 템플릿 — 프로덕션 환경에 바로 적용하기
앞의 세 장에서는 원리를 설명했습니다. 여기서는 통합 설정 템플릿을 바로 제공합니다. 실제 환경에 맞춰 매개변수를 조정할 수 있지만 전체 구조는 공통으로 사용할 수 있습니다.
# nginx.conf 프로덕션 환경 템플릿
user nginx;
worker_processes auto;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# gzip 압축 설정
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml
application/xml+rss application/xhtml+xml;
gzip_disable "msie6";
# 캐시 경로 설정
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=my_cache:10m
max_size=10g
inactive=60m
use_temp_path=off;
# 클라이언트 연결 설정
keepalive_timeout 65;
keepalive_requests 1000;
# 백엔드 서버 그룹
upstream backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
keepalive 64;
keepalive_timeout 60s;
keepalive_requests 1000;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
# 캐시 설정
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_key $scheme$request_method$host$request_uri;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
# 디버깅용 응답 헤더
add_header X-Cache-Status $upstream_cache_status;
}
}
}
세 가지 환경별 설정 차이
이커머스 사이트: 홈과 상품 상세 페이지가 자주 바뀌므로 캐시 시간은 짧게 설정하며 10~15분이면 충분합니다. 데이터베이스 쿼리가 많고 백엔드 부하가 크므로 upstream keepalive는 크게 설정해야 합니다.
API 서비스: 데이터 실시간성이 중요하므로 proxy_cache_valid가 1~5분에 불과할 수 있습니다. gzip은 JSON에 효과적이므로 반드시 추가하세요.
정적 사이트: HTML, CSS, JS가 거의 바뀌지 않으므로 캐시를 1시간 또는 그 이상으로 설정할 수 있습니다. 텍스트 기반 정적 파일이 많아 gzip 압축 효과가 가장 큽니다.
5장: 자주 발생하는 문제와 해결 방법
제가 자주 겪은 문제와 해결 방법을 바로 정리해 보겠습니다.
Q: gzip 압축이 적용되지 않고 응답 헤더에 Content-Encoding: gzip이 없습니다.
다음 세 가지를 확인하세요.
gzip on이 올바른 설정 계층인 http 블록에 있는지 확인합니다.gzip_types에 해당 응답의 MIME 유형이 포함되어 있는지 확인합니다.- 응답 본문 크기가
gzip_min_length보다 큰지 확인합니다.
curl로 테스트합니다. curl -H "Accept-Encoding: gzip" -I http://your-site.com
Q: 캐시 적중률이 매우 낮고 X-Cache-Status는 대부분 MISS입니다.
일반적인 원인은 다음과 같습니다.
- 캐시 키 설계가 잘못되어 각 요청이 모두 ‘서로 다른’ 요청으로 처리됩니다.
proxy_cache_valid가 너무 짧아 캐시를 사용하기도 전에 만료됩니다.- 백엔드 응답 헤더에
Cache-Control: no-cache또는Set-Cookie가 있습니다.
응답 헤더를 확인해 캐시를 금지하는 지시문이 없는지 확인하세요.
Q: worker_connections가 부족해 502 오류가 발생합니다.
Nginx 오류 로그를 확인하세요. worker_connections are not enough가 있다면 동시 연결 수가 상한을 넘었다는 뜻입니다.
해결 방법은 다음과 같습니다.
worker_connections값을 늘립니다.- 연결 누수가 있는지 확인합니다(keepalive 설정이 적절하지 않을 수 있습니다).
- 서버를 추가해 부하 분산하는 방안을 검토합니다.
Q: 메모리 사용량이 너무 높고 서버에서 OOM이 자주 발생합니다.
가능한 원인은 다음과 같습니다.
proxy_cache_path의keys_zone이 너무 큽니다.- 캐시 파일이 너무 많아 메모리 매핑 사용량이 높습니다.
keepalive커넥션 풀이 너무 커서 유휴 연결이 자원을 차지합니다.
이 매개변수들을 적절히 줄이거나 서버 메모리를 늘리세요.
마치며
Nginx 성능 튜닝의 핵심 세 가지는 gzip 압축, 캐시 전략, 커넥션 풀 설정입니다. 세 모듈을 적절히 조합하면 웹사이트 로딩 속도를 두 배 높이고 동시 처리 능력을 3~4배 향상할 수 있습니다.
튜닝은 한 번으로 끝나는 작업이 아닙니다. 다음 순서로 진행하는 것을 권장합니다.
- 먼저 gzip 활성화: 변경 범위가 가장 작고 효과가 가장 직접적이며 10분이면 완료할 수 있습니다.
- 그다음 캐시 설정: 비즈니스 환경에 맞는 캐시 전략을 설계하며 하루 안에 완료할 수 있습니다.
- 마지막으로 커넥션 풀 조정: 부하 테스트로 검증해야 하므로 트래픽이 안정된 뒤 진행하는 것이 좋습니다.
변경할 때마다 부하 테스트로 효과를 검증하세요. wrk나 ab를 사용해 응답 시간, QPS, 오류율의 변화를 확인할 수 있습니다. 감으로 조정하지 말고 데이터에 근거해 판단해야 합니다.
마지막 점검 목록입니다.
- gzip이 활성화되어 있고 MIME 유형 설정이 완전합니다.
- CPU와 압축률의 균형을 위해 gzip_comp_level을 4~6으로 설정했습니다.
- proxy_cache_path를 설정했고 캐시 용량이 적절합니다.
- 비즈니스 환경에 맞게 proxy_cache_valid를 설정했습니다.
- proxy_cache_use_stale 폴백 전략을 설정했습니다.
- worker_connections를 4096 이상으로 설정했습니다.
- keepalive_timeout을 60~75초로 설정했습니다.
- upstream keepalive를 설정했습니다(HTTP/1.1과 Connection 헤더 포함).
- 디버깅을 위해 응답 헤더에 X-Cache-Status가 포함되어 있습니다.
이 정도면 핵심 내용은 모두 다뤘습니다. 궁금한 점이 있으면 댓글로 남겨 주세요. 가능한 한 답변하겠습니다.
Nginx 성능 튜닝 설정 절차
gzip 압축, 캐시 전략, 커넥션 풀 최적화를 3단계로 완료하는 프로덕션 환경 설정 절차입니다.
⏱️ Estimated time: 30 min
- 1
Step 1: gzip 압축 활성화
http 블록에 설정을 추가합니다.
• gzip on; 압축 활성화
• gzip_vary on; Vary 응답 헤더 추가
• gzip_comp_level 6; 압축 레벨 설정(권장 4~6)
• gzip_min_length 1000; 1KB 미만은 압축하지 않음
• gzip_types로 MIME 유형 지정: text/plain text/css application/json application/javascript - 2
Step 2: proxy_cache 캐시 설정
두 단계로 설정합니다.
1단계: 캐시 경로 정의
• proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m
2단계: location에서 캐시 활성화
• proxy_cache my_cache;
• proxy_cache_valid 200 10m; 정상 응답을 10분간 캐시
• proxy_cache_use_stale error timeout http_502; 폴백 전략 설정 - 3
Step 3: 커넥션 풀 매개변수 최적화
핵심 설정은 세 가지입니다.
• worker_connections 4096; events 블록에서 설정
• keepalive_timeout 65; keepalive_requests 1000; http 블록에서 설정
• upstream keepalive 64; proxy_http_version 1.1; proxy_set_header Connection ""; 백엔드 커넥션 풀 설정
FAQ
gzip 압축 레벨은 어느 정도가 적절한가요?
proxy_cache와 fastcgi_cache 중 무엇을 선택해야 하나요?
worker_connections는 얼마로 설정하는 것이 적절한가요?
캐시 적중률이 낮을 때는 어떻게 진단하나요?
upstream keepalive에 HTTP/1.1 설정이 꼭 필요한 이유는 무엇인가요?
비즈니스 유형별 캐시 시간은 어떻게 설정하나요?
3분 읽기 · 게시일: 2026년 4월 11일 · 수정일: 2026년 9월 4일
Nginx 실전 가이드
검색으로 들어왔다면 같은 시리즈의 이전 글이나 다음 글로 이동하는 것이 가장 빠릅니다.
이전
Nginx 리버스 프록시 완벽 가이드: upstream, 버퍼링, 타임아웃
Nginx 리버스 프록시의 3대 핵심 설정인 upstream 로드 밸런싱, proxy buffer 튜닝, timeout 설정을 깊이 있게 살펴보고 502/504 오류 진단, keepalive 연결 풀, 헬스 체크 등 실전 기법을 소개합니다.
3편 중 1편
다음
Nginx SSL/TLS 설정 실전: HTTPS 인증서부터 A+ 보안 강화까지
Nginx HTTPS를 처음부터 설정하는 방법을 알아봅니다. Let's Encrypt 인증서 발급, TLS 1.3 보안 강화, SSL Labs A+ 등급 설정 템플릿, OCSP Stapling 성능 최적화를 다루는 2026년 최신 완전 가이드입니다.
3편 중 3편



댓글
GitHub로 로그인하여 댓글을 남기세요