nginx는 오픈소스로, 웹서버 또는 웹 프록시 서버로 많이 쓰인다.
설정을 잘하면 정적 콘텐츠를 효율적으로 제공할 수 있다.
이 중에서 몇 가지 주요한 설정들을 기록하고자 한다.
성능과 관련된 몇 가지 주요 설정들
1. gzip 압축
웹 사이트를 로드할 때 웹서버로부터 자바스크립트, 이미지, html, css 등 수많은 파일들을 받는다.
이때 이 콘텐츠들을 원본 그대로 내려주는 것이 아니라, gzip 압축을 활용하면 전송되는 데이터 양을 유의미하게 줄일 수 있다.
- 사용자 입장에서, 실제 로딩 속도가 빨라진다.
반면, 서버가 콘텐츠를 응답하기 전에 gzip 압축을 실행해야 하므로, 서버의 cpu가 높아질 수 있다.
어떤 유형의 파일을 압축할지, 압축 정도는 어느정도인지, 얼마나 큰 파일을 압축할지 등 운영 레벨에 적용하기 전에 테스트가 꼭 필요하다.
gzip on; # gzip 압축을 설정한다.
gzip_vary on; # 헤더에 Vary: Accept-Encoding을 추가한다.
gzip_proxied any; # 만약 nginx를 프록시서버로 쓴다면, 백엔드에서 받은 응답을 압축한다. (프록시된 요청에 대한 압축)
gzip_min_length 256; # 256 크기 이상의 파일만 압축
gzip_comp_level 5; # 1~9 압축 수준을 설정한다. 높아질수록 cpu사용률이 증가한다. 5는 약 50% 정도 압축한다.
gzip_types text/plain text/css text/xml application/json application/javascript;
// 압축할 콘텐츠 유형을 설정한다.
* gzip_vary는 클라이언트가 gzip을 지원할 때와 지원하지 않을 때 콘텐츠를 압축된 버전과 압축되지 않은 버전으로 각각 보낼 수 있도록 지시한다. (클라이언트의 요청 헤더(Accept-Encoding)에 따라 다른 버전의 콘텐츠가 제공될 수 있음을 알린다.)
2. proxy_buffer 설정
nginx가 클라이언트에 응답을 보내기 전에 응답을 버퍼에 저장한다.
웹 서버가 클라이언트로 응답을 보낼 때, 클라이언트의 속도가 느리다면 서버는 데이터를 전송하기 위해 계속 기다려야 한다. (네트워크 병목 현상)
이때 서버 자원을 계속 사용하고 있으므로, 이를 해결하기 위해 버퍼를 사용하여 클라이언트 처리 속도와 상관없이 응답을 임시로 처리한다. 이로 인해 아래의 이점이 있다.
location / {
proxy_pass 서버url;
# 프록시 버퍼 설정
proxy_buffering on; # 버퍼를 활성화한다.
proxy_buffer_size 4k; #버퍼의 크기를 설정한다. (주로 헤더가 들어간다.)
proxy_buffers 8 4k; # 각 연결에 대한 버퍼의 개수와 크기 (4kb짜리 8개)
proxy_busy_buffers_size 8k; # 클라이언트로 응답을 보내는 동안 사용할 수 있는 최대 버퍼 크기
}
※ 버퍼의 크기를 너무 크게 했을 때, text streaming같은 실시간 데이터 전송이 지연될 수 있으므로, 반드시 테스트가 필요하다. 특히 최근 AI 관련 서비스가 많이 나오고 있는데 만약 텍스트 stream이 안된다면 이 설정을 꼭 확인해보자.
3. worker와 http 설정
worker는 클라이언트의 요청을 처리하는 프로세스이며, 서버의 cpu 코어마다 몇 개를 가질지 설정할 수 있다.
http는 일반적으로 요청 - 연결 - 응답 -연결종료인데, 여러 번의 요청에 대해 연결하는 리소스를 줄이기 위해 클라이언트 연결을 유지할 수 있다. 이것이 keep alive 설정이다.
worker_processes auto; # 사용 가능한 CPU 코어 수에 따라 자동 설정
worker_connections 1024; # 각 worker가 동시에 처리할 수 있는 연결 수
# keep-alive 설정
keepalive_timeout 65;
keepalive_requests 100;
server {
listen 80;
location / {
proxy_pass 서버 url;
}
}
만약 사용하고 있는 서버의 코어 수가 4개이면 이론 상 가능한 연결 수는 1,024 * 4 = 4,096이다.
(리소스나 트래픽 환경에 따라 정확하지 않을 수 있음)
4,096개의 클라이언트가 동시접속하여 65초 간 모든 keepalive를 점유하고 있을 때,
4,097번째 사용자가 접속하려고 하면, 연결을 할 수 없으므로, 응답이 지연될 수 있다.
따라서 auto scaling 등으로 서버 자원이 안정적이라고 가정할 때, 이벤트 시 응답 지연이 발생한다면 위 설정이 간접적인 영향을 끼칠 수 있다.
4. 기타 - location block
proxy buffer 등의 일부 설정은 요청 url 별로 적용할 수 있다.
* keep-alive 등의 일부 설정은 HTTP/Server 레벨에서 적용되어 블록 별로 설정 불가
server {
listen 80;
server_name example.com;
# 기본 경로 처리 (/)
location / {
proxy_pass 서버 url;
# 버퍼링 설정
proxy_buffering on;
proxy_buffers 8 16k;
proxy_buffer_size 32k;
proxy_busy_buffers_size 64k;
}
# /test 경로 처리
location /test {
proxy_pass 서버 url2;
# 버퍼링 비활성화
proxy_buffering off; # 버퍼링 비활성화 (응답 바로 전송)
}
}
위 설정을 통해 웹성능을 최적화할 수 있다. 여러가지 테스트 케이스를 고려하여 충분히 테스트 후, 서버 성능을 최적화하자!
* 서버 다운타임없이 변경된 설정의 nginx를 적용할 수 있으므로, 대부분 안정적이다.