Nginx 성능 튜닝: HTTP 처리 및 구성
12분 소요 - 2026년 5월 26일

단일 서버에서 초당 50,000개 이상의 요청을 처리하도록 Nginx 워커 프로세스, 버퍼, 킵얼라이브 및 로드 밸런싱을 조정합니다.
Nginx HTTP 처리 흐름: 구성 튜닝
Nginx의 기본 구성은 성능이 아닌 호환성을 위해 설계되었습니다. 적절한 튜닝을 통해 단일 서버가 초당 50,000~80,000건의 요청을 처리할 수 있습니다. 이 가이드에서는 워커 프로세스, 연결, 키프얼라이브, 버퍼링, 부하 분산 등 가장 중요한 설정 사항과 벤치마크를 통해 변경 사항을 검증하는 방법을 다룹니다.
Nginx가 HTTP 요청을 처리하는 방식
Nginx는 요청을 서로 다른 단계로 처리하며, 각 단계마다 시스템 리소스를 소비합니다. 이 흐름을 이해하면 적절한 설정을 적용하는 데 도움이 됩니다.
이 과정은 커널 수준에서 시작됩니다. 들어오는 연결은 SYN 및 ACCEPT 큐에 도착하며, Nginx 워커 프로세스가 이를 처리합니다. 수락되면 워커는 커널 버퍼에서 HTTP 요청을 파싱합니다. TLS 트래픽의 경우 이 단계에서 CPU 사용량이 더 많이 발생합니다.
다음으로, Nginx는 Host 헤더와 IP/포트 조합을 사용하여 요청을 가상 서버에 매칭한 후, 접두사 또는 정규식(regex) 매칭을 통해 URI를 location 블록으로 변환합니다.
동적 콘텐츠의 경우, Nginx는 요청을 백엔드(FastCGI, 프록시)로 전달합니다. 이 업스트림 통신 단계는 지속적 연결(persistent connections)을 통해 큰 이점을 얻습니다. 업스트림 keepalive가 없으면 Nginx는 요청마다 새로운 TCP 연결을 열게 되어 지연 시간과 CPU 오버헤드가 증가합니다.
if proxy_buffering 이 활성화되어 있으면, Nginx는 전체 업스트림 응답을 메모리에 읽어온 후 클라이언트에 전달합니다. 이를 통해 워커는 즉시 새로운 요청을 처리할 수 있게 됩니다. 마지막으로, 출력 전달 단계에서 sendfile 를 활성화하면 제로 카피 전송이 가능해져 처리량을 약 6 Gbps에서 30 Gbps로 끌어올릴 수 있습니다.
모든 단계에서는 메모리 버퍼, 파일 디스크립터 및 CPU 사이클이 소모됩니다. 아래 섹션에서는 각 병목 현상을 해결하는 방법을 다룹니다.
작업자 프로세스 및 연결
메인 컨텍스트에서 worker_processes auto; 로 시작하십시오. 이는 워커 수를 CPU 코어 수와 일치시킵니다. 코어가 제한된 VPS의 경우 수치를 수동으로 설정하십시오(예: worker_processes 2;). 메모리 집약적인 워크로드인 경우, RAM 과부하를 방지하기 위해 워커 수를 줄이는 것을 고려하십시오.
를 활성화하여 worker_cpu_affinity auto; 를 활성화하여 각 워커를 특정 코어에 고정하세요. 이렇게 하면 캐시 미스 및 컨텍스트 전환이 줄어듭니다. Nginx 1.9.10부터 사용 가능합니다.
연결 제한
` worker_connections 지시어는 각 워커가 처리할 수 있는 동시 연결 수를 설정합니다. 총 용량은 worker_processes × worker_connections입니다. 기본값인 512 또는 1,024는 실제 운영 환경에서는 너무 적습니다. 트래픽이 많은 사이트의 경우 워커당 2,048 또는 4,096으로 설정하십시오.
각 연결에는 최소한 하나의 파일 디스크립터가 필요합니다. 리버스 프록시 환경에서는 각 연결이 두 개(클라이언트용 하나, 업스트림용 하나)를 사용합니다. worker_rlimit_nofile 값보다 최소 두 배 이상으로 설정하십시오 worker_connections 값의 두 배 이상으로 설정하고 여유분을 확보하십시오. worker_connections 4096;의 경우 worker_rlimit_nofile 10000; 이상을 사용하십시오.
시스템 수준에서 fs.file-max 값을 /etc/sysctl.conf 값을 최소 500,000으로 늘리고 systemd의 LimitNOFILE=65535.
마지막으로, multi_accept on; events 블록에 추가하여, 워커가 대기 중인 연결을 한 번에 하나씩이 아니라 모두 한꺼번에 수락하도록 하십시오.
타임아웃 및 키프얼라이브
클라이언트 키프얼라이브
keepalive_timeout 지시어는 유휴 클라이언트 연결이 유지되는 시간을 제어합니다. 트래픽이 많은 서버의 경우 30~65초가 적절합니다. 두 개의 매개변수를 사용하는 형식을 사용하십시오:
keepalive_timeout 65s 60s;첫 번째 값은 서버 측 타임아웃입니다. 두 번째 값은 클라이언트에 Keep-Alive: timeout=60 헤더를 클라이언트에 전송합니다. 클라이언트 값을 약간 낮게 설정하면, 브라우저가 Nginx가 이미 닫은 연결을 재사용하려는 경합 상황을 방지할 수 있습니다.
이 keepalive_requests 지시어는 단일 연결이 종료되기 전까지 처리할 수 있는 요청 수를 제한합니다. 기본값은 1,000입니다(버전 1.19.10에서 100에서 상향 조정됨). 안정적인 백엔드의 경우, 연결 전환을 줄이기 위해 이 값을 10,000으로 늘리십시오.
프록시 타임아웃
proxy_connect_timeout 는 Nginx가 백엔드와의 연결을 설정하기 위해 대기하는 시간을 설정합니다. 기본값은 60초입니다. 빠른 장애 조치(failover)를 위해 이 값을 5~10초로 줄이십시오.
proxy_read_timeout Nginx가 업스트림에서 연속적인 읽기 작업 사이에 대기하는 시간을 정의합니다. 백엔드의 실행 타임아웃과 일치하도록 설정하십시오. PHP-FPM의 request_terminate_timeout 120초인 경우, proxy_read_timeout 값을 최소 120초로 설정하여 조기 504 오류를 방지하십시오.
proxy_send_timeout 업스트림에 대한 연속적인 쓰기 작업 간의 간격을 제어합니다. 대용량 요청 본문을 전송하는 경우가 아니라면 기본값인 60초로 설정해도 일반적으로 문제없습니다.
일반적으로 proxy_connect_timeout 세 가지 중 가장 짧은 값으로 설정해야 합니다.
버퍼 크기
client_body_buffer_size 는 Nginx가 메모리에 저장하는 수신 요청 본문의 양을 제어합니다. 기본값인 8k 또는 16k는 간단한 양식 제출을 처리할 수 있지만, 파일 업로드 시 데이터가 디스크로 넘쳐나게 됩니다. 중소 규모의 업로드를 처리하려면 이 값을 128k로 늘리십시오. 사용자가 대용량 파일을 업로드할 경우 client_max_body_size 사용자가 더 큰 파일을 업로드하는 경우 기본값인 1MB에서 늘리십시오.
proxy_buffer_size 는 본문과 별도로 응답 헤더를 처리합니다. 기본값인 4k 또는 8k는 대개 충분하지만, 헤더 크기가 큰 애플리케이션의 경우 Set-Cookie (전자상거래에서 흔히 발생) 이 값을 초과하여 502 오류를 유발할 수 있습니다. 실제 헤더 크기를 측정하십시오:
curl -s -w '%{size_header}' -o /dev/null http://your-upstream-url가장 가까운 4k 단위로 올림하십시오.
proxy_buffers 응답 본문을 위한 버퍼의 수와 크기를 설정합니다. 기본값(4k 또는 8k 버퍼 8개, 총 32k~64k)으로는 대용량 JSON 응답을 수용할 수 없습니다. curl 충분한 버퍼를 구성하여 전체를 RAM에 보관하십시오.
프록시 버퍼링 동작
가 proxy_buffering on (기본값)을 사용하면 Nginx는 전체 업스트림 응답을 메모리에 읽어들인 후 클라이언트로 전송합니다. 이를 통해 백엔드 서버는 즉시 새로운 요청을 처리할 수 있습니다.
를 proxy_busy_buffers_size 을 최소 proxy_buffer_size 버퍼 수량에 1을 더한 값 이상으로 설정하되, 전체 버퍼 풀 용량보다 작게 설정하십시오. proxy_buffers 8 16k (총 128k)인 경우 proxy_busy_buffers_size 112k 미만으로 유지하십시오.
Server-Sent Events나 롱 폴링과 같은 실시간 엔드포인트의 경우, 위치 지정 블록을 사용하여 버퍼링을 비활성화하십시오. proxy_buffering off 위치별 블록에서 비활성화하십시오. 이 설정을 /stream 또는 /events 경로에 선택적으로 적용하고, 전역적으로는 적용하지 마십시오.
로드 밸런싱 및 업스트림 키프얼라이브
기본적으로 Nginx는 프록시되는 각 요청마다 새로운 TCP 연결을 열게 됩니다. 각 핸드셰이크마다 10~100ms의 지연 시간이 발생하며, TLS를 사용할 경우 여기에 10~50ms가 추가됩니다. 업스트림 키프얼라이브는 이러한 오버헤드를 제거하기 위해 지속적 연결 풀을 유지합니다.
다음 세 가지 설정이 필요합니다:
upstream backend {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
keepalive 128;
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}` keepalive 값은 워커당 최대 유휴 연결 수를 설정합니다. 최적의 풀 크기는 다음과 같이 계산합니다: (workers × target concurrency) / upstream nodes.
upstream keepalive_timeout 값을 60~120초로 설정하여 백엔드 설정에 맞추고 트래픽 급증을 처리하십시오.
부하 분산 전략
Nginx는 여러 부하 분산 방법을 지원합니다. 라운드 로빈(기본값)은 요청을 순차적으로 분배합니다. least_conn 는 활성 연결 수가 가장 적은 서버로 라우팅하며, 이는 요청 지속 시간이 가변적인 워크로드에 적합합니다. ip_hash 동일한 클라이언트 IP를 동일한 백엔드로 라우팅하여 세션 지속성을 제공합니다.
서버의 용량이 서로 다른 경우 weight 매개변수를 사용하십시오:
upstream backend {
least_conn;
server 10.0.1.10:8080 weight=3;
server 10.0.1.11:8080;
server 10.0.1.12:8080 backup;
keepalive 128;
}가중치가 부여된 서버는 3배의 트래픽을 수신합니다. backup 서버는 모든 주 서버가 다운된 경우에만 활성화됩니다. max_fails 와 fail_timeout 를 수동 상태 확인용으로 설정하고, max_conns 를 사용하여 백엔드당 동시 연결 수를 제한하십시오.
테스트 및 모니터링
무언가를 변경하기 전에는 항상 기준 성능을 측정하십시오. 변경 후에는 매번 벤치마크를 다시 수행하십시오. 한 번에 한 가지 변경 사항만 적용하십시오.
재로드하기 전에 nginx -t 를 사용하여 구성 구문을 검증하십시오. 리소스 경합을 피하기 위해 별도의 머신에서 벤치마크를 실행하십시오.
wrk는 HTTP 부하 테스트를 위한 표준 도구입니다:
wrk -t4 -c200 -d30s http://your-server.com/초당 요청 수, 평균 지연 시간, 최대 지연 시간 및 전송 속도를 추적하십시오. Apache Bench는 간단한 테스트에 적합합니다:
ab -n 50000 -c 40 http://your-server.com/지속적인 모니터링
모듈을 활성화하여 stub_status 모듈을 활성화하여 curl http://localhost/nginx_status.
로그 형식에 타이밍 변수를 추가하여 지연이 발생하는 지점을 파악하세요:
$request_time전체 요청 소요 시간$upstream_connect_time백엔드 연결 시간$upstream_response_time전체 백엔드 처리 시간
버퍼 문제를 확인하려면 오류 로그를 확인하십시오 journalctl -u nginx --no-pager | grep "temporary file". 응답이 디스크에 닿는다면, proxy_buffers 크기가 너무 작습니다. "열린 파일 수가 너무 많음(too many open files)" 오류를 확인하십시오. 이는 worker_rlimit_nofile 크기를 늘려야 함을 나타냅니다.
버퍼링 로깅을 사용하여 로그 I/O를 줄이십시오:
access_log /var/log/nginx/access.log combined buffer=64k flush=5s;부하 테스트 중에 ss -tn state established dst [backend_ip] 부하 테스트 중에 연결이 재사용되고 TIME_WAIT 상태에 쌓이지 않는지 확인하십시오.
고성능 워크로드에 최적화된 전용 서버 및 VPS 호스팅에 대해서는 FDC 서버를 참조하십시오.

Linux 서버 워크로드 최적화를 위한 튜닝된 프로필
GPU, 데이터베이스 및 고대역폭 Linux 서버를 위한 튜닝된 프로필을 선택, 적용 및 사용자 지정하는 방법과 예제 및 Ansible 배포 팁을 제공합니다.
16분 소요 - 2026년 6월 9일
VPS를 위한 Linux OOM 킬러 튜닝: 실용적인 가이드
12분 소요 - 2026년 6월 8일

질문이 있거나 맞춤형 솔루션이 필요하신가요?
유연한 옵션
글로벌 도달 범위
즉시 배포
유연한 옵션
글로벌 도달 범위
즉시 배포