nginx의 설정은 크게 두 계층으로 나뉜다.
- 전역(Global) 설정 / conf파일
- 개별 사이트 설정 - site-available/ 폴더
1.nginx.conf 파일
nginx 설치 후 etc/nginx 경로에 들어가면 nginx.conf 란 이름으로 위치해있는 파일이다.
이 파일에는 nginx의 전역 설정이 정의되어있는 곳으로
프로세스, worker, 리소스, 로깅, 모듈, 공통 설정이 정의되어있다.
즉, nginx 전체적인 설정을 담당하는 곳이다.
user www-data; # nginx 워커 프로세스가 어떤 리눅스 실행 계정으로 권한될 지 지정(마스터 프로세스는 root로 실행됨)
worker_processes auto; # CPU 코어 개수만큼 워커 프로세스 자동 설정
pid /run/nginx.pid; # PID 파일 경로
events {
worker_connections 1024; # 각 worker가 처리할 수 있는 최대 동시 연결 수
multi_accept on; # 여러 연결을 동시에 수락
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 전역 로그 설정
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# 사이트별 설정 포함
include /etc/nginx/sites-enabled/*;
}
프로세스.(참고로 프로세스란? 운영체제(OS)입장에서 실행 중인 하나의 프로그램 단위)
nginx는 2단계 프로세스 구조로 되어있다.
마스터 프로세스와 워커프로세스
마스터 프로세스는 nginx의 시작, 중지, 설정 리로드 등 전체적인 nginx를 관리하고
워커프로세스는 실제로 HTTP 요청을 받아서 응답을 돌려준다. 클라이언트 연결(브라우저 요청)을 처리하고, 파일 읽기, 리버스 프록시, 로드밸런싱을 수행하는 nginx의 핵심 단위이기도 하다.
ps -ef | grep nginx를 입력하면 nginx의 프로세스들을 확인할 수 있다.

설정 파일에서 worker_processes auto; 라고 명시했기에 워커프로세스의 개수는 CPU의 코어 수 만큼 생성된다.
그래서 4코어에 맞게 4개의 워커 프로세스가 생성된 것이다.
그리고 events 블록에서 woker_connections 1024로 설정했기에 워커 4개 * 1024 = 4096개의 동시 요청에 대해 처리가 가능하다.
(event 블록은 nginx의 이벤트 처리 방식을 제어한다- 즉 worker가 네트워크 연결을 어떻게 수락할 지를 정의)
user www-data; # nginx 프로세스 실행 계정
worker_processes auto; # CPU 코어 개수만큼 워커 프로세스 자동 설정
pid /run/nginx.pid; # PID 파일 경로
events {
worker_connections 1024; # 각 worker가 처리할 수 있는 최대 동시 연결 수
multi_accept on; # 여러 연결을 동시에 수락
}
리소스 설정
리소스 설정은 아래의 sendfile 부분과 keepalive_timeout부분이다.
로깅설정은 nginx.conf파일의 http{}블록에서 설정하는 곳으로 로그를 쌓을 위치와 파일을 말한다.
http블록 안에는 MIME타입, 로그, 압축, 캐시, 프록시, 보안 설정 등 모든 웹 관련설정이 들어간다.
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 전역 로그 설정
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# 사이트별 설정 포함
include /etc/nginx/sites-enabled/*;
}
2.Sites- available
nginx.config가 전역설정을 담당했다면, 하나의 nginx의 여러 웹사이트를 물려 운영할 때 각 사이트마다 설정을 독립적으로 담당하는 곳이 sites-available 폴더에 있는 파일이다(처음엔 default란 이름으로 파일이 있을 것이다.).
이곳에는 각 도메인에 대한 포트,도메인 이름,정적 파일 경로,백엔드 프록시, SSL인증서, 보안/캐시 정책등을 저장할 수 있다.
예시)
server {
listen 80;
server_name myapp.com www.myapp.com;
# 1️⃣ 모든 HTTP 요청을 HTTPS로 리다이렉트
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name myapp.com www.myapp.com;
# 2️⃣ SSL 인증서 경로
ssl_certificate /etc/nginx/ssl/myapp.crt;
ssl_certificate_key /etc/nginx/ssl/myapp.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# 3️⃣ 보안 헤더
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
server_tokens off;
autoindex off;
# 4️⃣ 정적 파일 루트 (React 빌드 경로)
root /var/www/myapp/dist;
index index.html;
# 5️⃣ 정적 파일 요청 처리
location / {
try_files $uri /index.html;
}
# 6️⃣ API 요청은 내부 백엔드로 프록시 전달
location /api/ {
proxy_pass http://192.168.10.21:8080/api/;
# 요청 헤더 전달
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;
# 대용량 업로드 허용
client_max_body_size 100M;
# CORS (개발용, 실제 배포 시 제한 필요)
add_header 'Access-Control-Allow-Origin' 'https://myapp.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always;
if ($request_method = OPTIONS) {
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
}
# 7️⃣ 이미지, CSS, JS 캐싱 (브라우저 캐시 30일 유지)
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# 8️⃣ 보안: 민감 파일 접근 차단
location ~ /\.env { deny all; return 404; }
location ~* \.(yml|properties|log|sql)$ { deny all; return 404; }
# 9️⃣ 로그 (이 사이트 전용)
access_log /var/log/nginx/myapp_access.log;
error_log /var/log/nginx/myapp_error.log;
}
보통은 하나의 도메인에 하나의 sever{}블록 안에 정적 자원 제공+ 리버스 프록시 + 보안/캐시 정책을 관리한다.
즉 server{}은 이 도메인으로 들어오는 요청을 이렇게 처리하라고 정의하는 과정이다.
server {
listen 80;
server_name myapp.com www.myapp.com;
# 1️⃣ 모든 HTTP 요청을 HTTPS로 리다이렉트
return 301 https://$host$request_uri;
}
listen은 이 서버 블록이 수신할 포트를 지정하는 것이다.
즉 HTTP 기본 포트 80을 열어서 요청을 받고, sever_name에 지정한 두 도메인에 대해 HTTPS 로 리다이렉트 하겠다는 의미다.
301은 영구 리다이렉트를 나타내는 상태코드고 $host는 현재 요청한 도메인 $request_uri는 요청한 경로(ex./login)을 그대로 붙여준다는 의미다.
server {
listen 443 ssl http2;
server_name myapp.com www.myapp.com;
HTTPS용 443 포트를 연다는 의미며 ssl은 인증서 사용, http2는 최신 프로토콜을 지원한다는 의미다.
# 2️⃣ SSL 인증서 경로
ssl_certificate /etc/nginx/ssl/myapp.crt;
ssl_certificate_key /etc/nginx/ssl/myapp.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_certificate는 HTTPS에 사용할 공개인증서(crt) 파일 경로.
ssl_certificate_key는 인증서의 개인키 파일 경로
ssl_protocols는 허용할 TLS 버전
ssl_prefer_server_ciphers on 은 클라이언트보다는 서버에서 지정한 암호화 방식을 우선 사용하겠다는 의미다.
즉, https:// 접속 시 어떤 인증서로 암호화할지를 정의하는 부분이다.
# 3️⃣ 보안 헤더
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
server_tokens off;
autoindex off;

추가로 server_tokens off 는 nginX 버전 정보 노출을 막는 설정이다.
기본적으로 nginx는 에러 페이지나 응답헤더에 자기 버전을 표시하기 때문이다.
autoindex off는 nginx는 기본적으로 요청한 경로 안에 index.html이 없으면 그 디렉토리의 파일 목록을 자동으로 보여주는 기능이 있는데 이는 보안에 위협이므로 off를 해두는 것이 맞다.
# 4️⃣ 정적 파일 루트 (React 빌드 경로)
root /var/www/myapp/dist;
index index.html;
# 5️⃣ 정적 파일 요청 처리
location / {
try_files $uri /index.html;
}


# 6️⃣ API 요청은 내부 백엔드로 프록시 전달
location /api/ {
proxy_pass http://192.168.10.21:8080/api/;
# 요청 헤더 전달
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;
# 대용량 업로드 허용
client_max_body_size 100M;
# CORS (개발용, 실제 배포 시 제한 필요)
add_header 'Access-Control-Allow-Origin' 'https://myapp.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always;
if ($request_method = OPTIONS) {
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
}

즉, /api/... 요청은 nginx가 직접 처리하지 않고, 내부망의 Spring 서버로 대신 전달(리버스 프록시) 한다는 말이다.

# 7️⃣ 이미지, CSS, JS 캐싱 (브라우저 캐시 30일 유지)
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# 8️⃣ 보안: 민감 파일 접근 차단
location ~ /\.env { deny all; return 404; }
location ~* \.(yml|properties|log|sql)$ { deny all; return 404; }
# 9️⃣ 로그 (이 사이트 전용)
access_log /var/log/nginx/myapp_access.log;
error_log /var/log/nginx/myapp_error.log;


nginx에서 다루는 2가지 설정파일에 대해서 다시 정리해서 비교해보자면 아래와 같다.

여기서 sitesenabled 폴더에 링크돼야 활성화된다는 말이 잘 와닿지 않을 것이다.
nginx는 사이트 설정 파일이 들어있는 두 폴더를 사용한다.
- /etc/nginx/sites-available/ ← 모든 사이트 설정 저장소 (비활성)
- /etc/nginx/sites-enabled/ ← 실제 동작 중인 설정 목록 (활성)
sites-available 폴더 안에 있는 설정파일을 nginx가 실제로 읽혀서 적용되려면 sites-enabled 폴더 안에 심볼릭 링크로 연결되어있어야한다.
(심볼릭 링크란? 원본 파일을 카리키는 바로가기 같은 것이다. 윈도우에서 파일 아이콘을 바탕화면에 바로가기 아이콘으로 만드는 것처럼 리눅스에서는 그 역할을 하는 것이 심볼릭 링크다.)
예를 들어, /etc/nginx/sites-available/ 안에 myapp.conf 파일이 있다고 하자.
이를 활성화시키려면 아래와 같은 명령어를 입력한다.
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/
그러면 sites-enabled폴더에 바로가기 파일이 생긴다.
그러면, nginx가 시작 될 때 sites-enabled폴더를 자동으로 읽고 이와 연결되는 sites_available의 myapp.conf파일을 읽어 설정을 불러오게 되는 구조다.
(아! 항상 설정을 하고나서는 sudo systemctl restart nginx로 바뀐 설정이 적용된 nginx를 다시 시작해야할 것을 잊지 말아야한다.)
'네트워크' 카테고리의 다른 글
| [AWS]도커 이미지로 백엔드 배포하기 (4) | 2026.01.05 |
|---|---|
| HTTP프로토콜을 스프링 서버가 받는 과정(+HTTP 구조,Content-type) (1) | 2025.12.18 |
| [네트워크]VPN이란? (+공개망,사설망,터널링) (3) | 2025.08.24 |
| 암호화 총 정리(+단방향 암호화,양방향 암호화) (1) | 2025.08.22 |
| [VM웨어] 내 컴퓨터에서 VM웨어 내 리눅스로 파일 전송하기(SSH,SCP프로토콜) (6) | 2025.08.21 |