user www-data; worker_processes auto; # worker_rlimit_nofile directive # CPU: 쿼드코어, RAM: 4GB, 요청수: ~50/s 기반 설정시 worker_rlimit_nofile 8192; # worker_rlimit_nofile 8192; # worker_priority 0; # worker_cpu_affinity 0001 0010 0100 1000; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; # Load ModSecurity dynamic module # load_module /etc/nginx/modules/ngx_http_modsecurity_module.so events { use epoll; # 리눅스에서 권장 accept_mutex on; # 기본값이지만 명시해두면 좋음 # 단일 워커당 동시 연결 수 # worker_processes * worker_connections = 최대 동시 연결 수 # 여기에 워커가 상시 쓰는 FD(에러/액세스 로그, 리스닝 소켓, epoll 등) 오버헤드를 조금 빼고 잡아야 안전하다 (약 50~150 정도 버퍼). # CPU: 쿼드코어, RAM: 4GB, 요청수: ~50/s 기반 설정시 # off 설정에 대한 효과 # 부하 분산: 워커 간 균등한 연결 분배 # 안정성: 한 워커가 과부하되는 것 방지 # 예측 가능한 성능: 일관된 응답 시간 multi_accept off; worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; # WebSocket 및 HTTP keepalive 동시 지원을 위한 Connection 헤더 동적 설정 # - WebSocket 요청 ($http_upgrade가 있는 경우): "upgrade" 반환 # - 일반 HTTP 요청 ($http_upgrade가 없는 경우): "" 반환 (keepalive 연결 유지) map $http_upgrade $connection_upgrade { default upgrade; '' ''; } log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/main_access.log main; error_log /var/log/nginx/main_error.log; server_tokens off; charset utf-8; # Docker 내부 DNS 사용 (컨테이너 이름 해석) resolver 127.0.0.11 valid=30s ipv6=off; resolver_timeout 5s; # 기본 헤더 버퍼 (대부분의 요청 처리) client_header_buffer_size 4k; # 큰 헤더 버퍼 (JWT, 큰 쿠키 등) large_client_header_buffers 4 16k; # POST나 PUT 요청으로 전송하는 본문(body) 데이터를 받을 때, Nginx가 메모리(RAM)에 임시 저장할 버퍼의 크기 client_body_buffer_size 128k; # 일반적으로 64KB~256KB 권장 client_body_timeout 15s; # 클라이언트 본문 수신 타임아웃 client_header_timeout 15s; # 클라이언트 헤더 수신 타임아웃 # 효율적인 파일 전송 설정 sendfile on; # 커널 공간에서 직접 파일 전송 (제로카피) tcp_nopush on; # sendfile 사용 시 패킷 효율 향상 tcp_nodelay on; # Keep-alive 연결에서 지연 없이 전송 (실시간 통신에 유리) # Keep-alive 연결 설정 keepalive_timeout 30s; # 연결 유지 시간 keepalive_requests 1000; # 연결당 최대 요청 수 send_timeout 15s; # 클라이언트로 응답 전송 타임아웃 # ===== 파일 업로드 설정 ===== client_max_body_size 50M; # 최대 업로드 크기 (필요에 따라 조정) # ===== 프록시 타임아웃 설정 ===== proxy_connect_timeout 300s; # 백엔드 연결 타임아웃 proxy_send_timeout 300s; # 백엔드로 요청 전송 타임아웃 proxy_read_timeout 300s; # 백엔드 응답 수신 타임아웃 proxy_request_buffering off; # 대용량 파일 스트리밍 업로드 (버퍼링 비활성화) # ===== 해시 테이블 ===== # MIME 타입 해시 테이블 설정 # mime.types 파일에 정의된 파일 확장자와 MIME 타입 매핑을 저장 # 예: .html -> text/html, .jpg -> image/jpeg 등의 매핑을 빠르게 찾기 위해 사용됨 types_hash_max_size 2048; # 기본 mime.types의 수백 개 타입을 충분히 수용하는 크기 types_hash_bucket_size 64; # 각 해시 버킷 크기, CPU 캐시 라인과 정렬하여 성능 최적화 # 서버 이름 해시 테이블 설정 (server_name 지시자에 정의된 도메인명만 해당) # server 블록의 server_name 지시자에 설정된 도메인명들을 빠르게 매칭하기 위한 해시 테이블 server_names_hash_max_size 1024; # 여러 도메인/서브도메인 운영 시 충분한 공간 확보 server_names_hash_bucket_size 64; # 도메인명 길이를 고려한 버킷 크기 (일반적으로 32~64면 충분) # Nginx 변수 해시 테이블 설정 # $host, $remote_addr 같은 내장 변수와 map/set으로 정의한 커스텀 변수들을 저장하는 해시 테이블 # HTTP 헤더를 변수로 변환한 $http_* 변수들도 여기에 포함됨 (예: $http_user_agent, $http_referer) variables_hash_max_size 2048; # 내장 변수 + 커스텀 변수를 위한 충분한 공간 variables_hash_bucket_size 64; # 변수명 길이와 충돌 방지를 위한 적절한 버킷 크기 # ===== 압축 설정 ===== # 실시간 압축 비활성화 (CPU 부하 감소) gzip off; # 미리 압축된 .gz 파일 제공 # 예: style.css 요청 시 → style.css.gz 파일을 찾아서 전송 gzip_static on; # Vary: Accept-Encoding 헤더 추가 (프록시 캐시 호환성) gzip_vary on; include /etc/nginx/proxy_params/*; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*.conf; }