Skip to content

Wiki_BE_Nginx

openLeeWorld edited this page May 13, 2026 · 1 revision

Nginx 기초: 백엔드 개발자 실무 가이드

본 문서는 백엔드 개발에 투입되는 신입 개발자를 위해 작성되었습니다.
Nginx의 핵심 개념, 설정 방법, 자주 쓰는 명령어를 실무 중심으로 정리합니다.


목차

  1. Nginx란?
  2. 설치 및 기본 명령어
  3. 디렉토리 및 파일 구조
  4. 설정 파일 문법 기초
  5. 정적 파일 서빙
  6. 리버스 프록시 설정
  7. 로드 밸런싱
  8. HTTPS 설정 (SSL/TLS)
  9. 로그 확인 및 디버깅
  10. 실무 설정 예시 모음

1. Nginx란?

Nginx(엔진엑스) 는 고성능 웹 서버이자 리버스 프록시 서버입니다. 백엔드 서버 앞단에 위치하여 다음 역할을 수행합니다.

인터넷 (클라이언트)
        │
        ▼
  ┌──────────┐
  │  Nginx   │  ← 웹 서버 / 리버스 프록시 / 로드 밸런서
  └──────────┘
        │
  ┌─────┴──────┐
  ▼            ▼
[서버 1]    [서버 2]   ← 실제 백엔드 애플리케이션
(FastAPI)   (Flask)

Nginx가 하는 일:

역할 설명
웹 서버 HTML, CSS, JS, 이미지 등 정적 파일 직접 서빙
리버스 프록시 클라이언트 요청을 백엔드 서버로 전달
로드 밸런서 여러 백엔드 서버에 트래픽 분산
SSL 터미네이션 HTTPS 처리를 Nginx가 담당, Web Application Server는 HTTP만 처리
캐시 서버 응답을 캐싱하여 백엔드 부하 감소

2. 설치 및 기본 명령어

2.1 설치 (Ubuntu/Debian 기준)

# 패키지 목록 업데이트
sudo apt update

# Nginx 설치
sudo apt install -y nginx

# 설치 확인
nginx -v
# 출력 예시: nginx version: nginx/1.24.0

2.2 서비스 제어 명령어 (systemctl)

실제 서버에서는 systemctl 로 Nginx를 관리합니다.

# Nginx 시작
sudo systemctl start nginx

# Nginx 중지
sudo systemctl stop nginx

# Nginx 재시작 (설정 변경 후 완전 재시작 - 짧은 다운타임 발생)
sudo systemctl restart nginx

# Nginx 리로드 (설정 변경 후 무중단 적용 - 실무에서 주로 사용)
sudo systemctl reload nginx

# 서버 부팅 시 Nginx 자동 시작 등록
sudo systemctl enable nginx

# 자동 시작 해제
sudo systemctl disable nginx

# 현재 상태 확인
sudo systemctl status nginx

restart vs reload 차이:

명령어 동작 다운타임
restart 프로세스 완전 종료 후 재시작 있음 (짧은 순간)
reload 설정만 다시 읽음, 프로세스 유지 없음 ✅

실무 팁: 설정 변경 후에는 반드시 reload를 사용하십시오. restart는 서비스가 잠깐 중단됩니다.

2.3 Nginx 직접 제어 명령어

# 설정 파일 문법 검사 (적용 전 반드시 실행)
sudo nginx -t

# 설정 파일 문법 검사 + 상세 출력
sudo nginx -T

# 설정 리로드 (systemctl reload와 동일)
sudo nginx -s reload

# Nginx 정상 종료 (현재 처리 중인 요청 완료 후 종료)
sudo nginx -s quit

# Nginx 즉시 강제 종료
sudo nginx -s stop

# 특정 설정 파일 지정하여 실행
sudo nginx -c /etc/nginx/nginx.conf

⚠️ 주의: 설정 파일 수정 후 nginx -t 로 반드시 문법을 검사한 뒤 적용하십시오.
문법 오류가 있는 상태로 reload하면 Nginx가 중단될 수 있습니다.

# 올바른 설정 변경 절차
sudo vi /etc/nginx/sites-available/myapp.conf   # 1. 설정 수정
sudo nginx -t                                    # 2. 문법 검사
sudo systemctl reload nginx                      # 3. 문제 없으면 적용

3. 디렉토리 및 파일 구조

/etc/nginx/
├── nginx.conf                  ← 메인 설정 파일
├── sites-available/            ← 사용 가능한 사이트 설정 보관
│   ├── default
│   └── myapp.conf
├── sites-enabled/              ← 실제 활성화된 사이트 설정 (심볼릭 링크)
│   └── myapp.conf -> ../sites-available/myapp.conf
├── conf.d/                     ← 추가 설정 파일 (자동 로드)
│   └── gzip.conf
├── snippets/                   ← 재사용 가능한 설정 조각
│   └── ssl-params.conf
└── mime.types                  ← 파일 확장자 ↔ MIME 타입 매핑

주요 로그 파일:

/var/log/nginx/
├── access.log   ← 모든 요청 기록
└── error.log    ← 오류 기록

기본 정적 파일 경로:

/var/www/html/        ← Nginx 기본 웹 루트 디렉토리
└── index.nginx-debian.html

3.1 사이트 활성화/비활성화

Nginx는 sites-available에 설정을 작성하고, sites-enabled에 심볼릭 링크를 걸어 활성화합니다.

# 사이트 활성화 (심볼릭 링크 생성)
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/

# 사이트 비활성화 (심볼릭 링크 제거)
sudo rm /etc/nginx/sites-enabled/myapp.conf

# 변경 사항 적용
sudo nginx -t && sudo systemctl reload nginx

4. 설정 파일 문법 기초

4.1 기본 구조

Nginx 설정은 블록(Block) 과 지시어(Directive) 로 구성됩니다.

# 전역 블록 (nginx.conf 최상단)
worker_processes auto;

# events 블록
events {
    worker_connections 1024;
}

# http 블록
http {

    # server 블록 (가상 호스트)
    server {
        listen 80;
        server_name example.com;

        # location 블록 (URL 경로별 처리)
        location / {
            root /var/www/html;
            index index.html;
        }
    }
}

4.2 블록 계층 구조

http
└── server        ← 도메인/포트 단위 설정
    └── location  ← URL 경로 단위 설정

4.3 핵심 지시어 설명

지시어 설명 예시
listen 수신 포트 listen 80;
server_name 처리할 도메인 server_name example.com;
root 정적 파일 루트 경로 root /var/www/html;
index 기본 인덱스 파일 index index.html;
proxy_pass 프록시 대상 서버 proxy_pass http://localhost:8080;
return 리다이렉트 또는 응답 반환 return 301 https://$host$request_uri;
include 다른 설정 파일 포함 include /etc/nginx/conf.d/*.conf;

4.4 location 블록 매칭 규칙

URL 경로를 매칭하는 방법에는 우선순위가 있습니다.

# 1순위: = (완전 일치)
location = /favicon.ico { ... }

# 2순위: ^~ (접두어 일치, 정규식 탐색 중단)
location ^~ /images/ { ... }

# 3순위: ~ (정규식, 대소문자 구분)
location ~ \.php$ { ... }

# 4순위: ~* (정규식, 대소문자 무시)
location ~* \.(jpg|jpeg|png|gif)$ { ... }

# 5순위: / (접두어 일치, 기본값)
location / { ... }

실무에서 자주 쓰는 패턴:

server {
    listen 80;
    server_name example.com;

    # 정적 파일은 Nginx가 직접 처리
    location ~* \.(html|css|js|png|jpg|gif|ico|svg|woff2)$ {
        root /var/www/html;
        expires 30d;    # 브라우저 캐시 30일
    }

    # API 요청은 백엔드로 전달
    location /api/ {
        proxy_pass http://localhost:8080;
    }

    # 그 외 모든 요청
    location / {
        root /var/www/html;
        try_files $uri $uri/ /index.html;  # SPA 대응
    }
}

4.5 변수

Nginx 설정에서 자주 사용하는 내장 변수입니다.

변수 의미
$host 요청의 Host 헤더 값
$request_uri 요청 URI (쿼리스트링 포함)
$uri 요청 URI (쿼리스트링 제외)
$remote_addr 클라이언트 IP 주소
$args 쿼리스트링
$scheme 프로토콜 (http 또는 https)
$server_port 서버 포트 번호
$upstream_addr 프록시 대상 서버 주소

5. 정적 파일 서빙

가장 기본적인 Nginx 사용 사례입니다.

server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/myapp;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
        # $uri        : 해당 파일 시도
        # $uri/       : 디렉토리 시도
        # =404        : 없으면 404 반환
    }

    # 정적 파일 캐시 설정
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf)$ {
        expires 1y;                          # 1년 캐시
        add_header Cache-Control "public";
    }
}

파일 권한 설정:

# Nginx가 파일을 읽을 수 있도록 권한 설정
sudo chown -R www-data:www-data /var/www/myapp
sudo chmod -R 755 /var/www/myapp

6. 리버스 프록시 설정

백엔드 서버(Spring Boot, Node.js, Django 등)로 요청을 전달하는 설정입니다.

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://localhost:8080;    # 백엔드 서버 주소

        # 프록시 필수 헤더 설정
        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;

        # 타임아웃 설정
        proxy_connect_timeout 60s;   # 백엔드 연결 대기 시간
        proxy_read_timeout    60s;   # 백엔드 응답 대기 시간
        proxy_send_timeout    60s;   # 백엔드로 전송 대기 시간
    }
}

헤더 설명:

헤더 역할
X-Real-IP 실제 클라이언트 IP를 백엔드에 전달
X-Forwarded-For 프록시 체인 전체 IP 목록 전달
X-Forwarded-Proto 원본 프로토콜(http/https) 전달
Host 원본 도메인 전달

실무 팁: 백엔드 애플리케이션에서 클라이언트 IP를 가져올 때 request.getRemoteAddr() 대신 X-Real-IP 또는 X-Forwarded-For 헤더를 사용해야 합니다. Nginx를 거치면 RemoteAddr은 Nginx의 IP가 됩니다.


7. 로드 밸런싱

여러 백엔드 서버로 트래픽을 분산합니다.

http {

    # upstream 블록: 백엔드 서버 그룹 정의
    upstream backend_servers {
        server 192.168.1.101:8080;
        server 192.168.1.102:8080;
        server 192.168.1.103:8080;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend_servers;    # upstream 그룹으로 전달

            proxy_set_header Host            $host;
            proxy_set_header X-Real-IP       $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

7.1 로드 밸런싱 알고리즘

upstream backend_servers {
    # 1. Round Robin (기본값): 순서대로 분산
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;

    # 2. Least Connections: 연결 수가 가장 적은 서버에 분산
    # least_conn;
    # server 192.168.1.101:8080;
    # server 192.168.1.102:8080;

    # 3. IP Hash: 같은 클라이언트 IP는 항상 같은 서버로 (세션 유지)
    # ip_hash;
    # server 192.168.1.101:8080;
    # server 192.168.1.102:8080;

    # 4. Weight: 가중치로 분산 비율 조정 (3:1 비율)
    # server 192.168.1.101:8080 weight=3;
    # server 192.168.1.102:8080 weight=1;
}

7.2 서버 상태 옵션

upstream backend_servers {
    server 192.168.1.101:8080;
    server 192.168.1.102:8080 backup;     # 다른 서버 모두 다운 시에만 사용
    server 192.168.1.103:8080 down;       # 임시 비활성화
    server 192.168.1.104:8080 max_fails=3 fail_timeout=30s;
    # max_fails  : 실패 횟수 초과 시 비정상 처리
    # fail_timeout : 비정상 처리 유지 시간
}

8. HTTPS 설정 (SSL/TLS)

8.1 Certbot으로 무료 SSL 인증서 발급 (Let's Encrypt)

# Certbot 설치
sudo apt install -y certbot python3-certbot-nginx

# 인증서 발급 및 Nginx 자동 설정
sudo certbot --nginx -d example.com -d www.example.com

# 인증서 갱신 테스트 (90일마다 자동 갱신됨)
sudo certbot renew --dry-run

# 인증서 목록 확인
sudo certbot certificates

8.2 HTTPS 설정 (Certbot 적용 후 기준)

# HTTP → HTTPS 리다이렉트
server {
    listen 80;
    server_name example.com www.example.com;

    # 모든 HTTP 요청을 HTTPS로 리다이렉트
    return 301 https://$host$request_uri;
}

# HTTPS 서버
server {
    listen 443 ssl;
    server_name example.com www.example.com;

    # SSL 인증서 경로 (Certbot이 자동 생성)
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # 권장 SSL 설정
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://localhost:8080;

        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;
    }
}

9. 로그 확인 및 디버깅

9.1 로그 실시간 확인

# 접근 로그 실시간 출력
sudo tail -f /var/log/nginx/access.log

# 에러 로그 실시간 출력
sudo tail -f /var/log/nginx/error.log

# 마지막 100줄 출력
sudo tail -n 100 /var/log/nginx/error.log

# 특정 단어 포함 로그 필터링
sudo grep "500" /var/log/nginx/access.log
sudo grep "error" /var/log/nginx/error.log

9.2 로그 포맷

기본 access.log 포맷:

192.168.1.1 - - [01/Jan/2024:12:00:00 +0900] "GET /api/users HTTP/1.1" 200 512 "-" "Mozilla/5.0"
      │               │                          │         │      │
  클라이언트 IP      시간                        메서드+경로 상태코드 응답크기

9.3 커스텀 로그 포맷

http {
    # 커스텀 로그 포맷 정의
    log_format custom '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      '"$http_referer" "$http_user_agent" '
                      'rt=$request_time uct=$upstream_connect_time '
                      'urt=$upstream_response_time';

    # 특정 서버에 적용
    server {
        access_log /var/log/nginx/myapp_access.log custom;
        error_log  /var/log/nginx/myapp_error.log warn;
        # 로그 레벨: debug | info | notice | warn | error | crit
    }
}

9.4 디버깅 체크리스트

# 1. 설정 파일 문법 검사
sudo nginx -t

# 2. Nginx 상태 확인
sudo systemctl status nginx

# 3. 포트 사용 현황 확인 (80, 443 포트 리스닝 여부)
sudo ss -tlnp | grep nginx
# 또는
sudo netstat -tlnp | grep nginx

# 4. 에러 로그 확인
sudo tail -n 50 /var/log/nginx/error.log

# 5. 프로세스 확인
ps aux | grep nginx

# 6. 방화벽 확인 (포트가 열려있는지)
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

10. 실무 설정 예시 모음

10.1 Spring Boot 앱 프록시 (가장 흔한 패턴)

server {
    listen 80;
    server_name api.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name api.example.com;

    ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;

    # 최대 업로드 파일 크기
    client_max_body_size 10M;

    location / {
        proxy_pass http://localhost:8080;

        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;

        proxy_connect_timeout 60s;
        proxy_read_timeout    60s;
    }
}

10.2 React/Vue SPA 서빙

server {
    listen 80;
    server_name example.com;

    root /var/www/frontend/dist;
    index index.html;

    # SPA: 모든 경로를 index.html로 fallback
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 정적 파일 캐시
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # API 요청은 백엔드로 전달
    location /api/ {
        proxy_pass http://localhost:8080;
        proxy_set_header Host            $host;
        proxy_set_header X-Real-IP       $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

10.3 Gzip 압축 설정

전송 데이터를 압축하여 응답 속도를 향상시킵니다.

http {
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;       # 압축 레벨 (1~9, 높을수록 압축률↑ CPU↑)
    gzip_min_length 1000;    # 1KB 이상인 경우만 압축
    gzip_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/json
        application/xml
        image/svg+xml;
}

10.4 요청 속도 제한 (Rate Limiting)

API 남용, DDoS 방어에 사용합니다.

http {
    # IP당 초당 10개 요청으로 제한
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

    server {
        location /api/ {
            limit_req zone=api_limit burst=20 nodelay;
            # burst   : 순간 허용 초과 요청 수
            # nodelay : 버스트 요청을 지연 없이 즉시 처리
            proxy_pass http://localhost:8080;
        }
    }
}

10.5 CORS 헤더 추가

server {
    location /api/ {
        # CORS 헤더
        add_header 'Access-Control-Allow-Origin'  'https://example.com' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always;

        # Preflight 요청 처리
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Max-Age' 86400;
            add_header 'Content-Length' 0;
            return 204;
        }

        proxy_pass http://localhost:8080;
    }
}

10.6 WebSocket 프록시

server {
    location /ws/ {
        proxy_pass http://localhost:8080;

        # WebSocket 업그레이드 설정
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host       $host;

        proxy_read_timeout 3600s;  # WebSocket은 오래 유지되므로 타임아웃 증가
    }
}

빠른 참조 (Quick Reference)

자주 쓰는 명령어 요약

# 상태 확인
sudo systemctl status nginx

# 설정 문법 검사
sudo nginx -t

# 무중단 설정 적용 (실무 표준)
sudo nginx -t && sudo systemctl reload nginx

# 재시작
sudo systemctl restart nginx

# 로그 실시간 확인
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log

# 사이트 활성화
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

# 사이트 비활성화
sudo rm /etc/nginx/sites-enabled/myapp.conf
sudo nginx -t && sudo systemctl reload nginx

설정 변경 표준 절차

# 1. 설정 파일 수정
sudo vi /etc/nginx/sites-available/myapp.conf

# 2. 문법 검사
sudo nginx -t

# 3. 정상이면 적용
sudo systemctl reload nginx

# 4. 로그 확인
sudo tail -f /var/log/nginx/error.log

주요 파일 경로

경로 설명
/etc/nginx/nginx.conf 메인 설정 파일
/etc/nginx/sites-available/ 사이트 설정 보관
/etc/nginx/sites-enabled/ 활성화된 사이트 (심볼릭 링크)
/var/log/nginx/access.log 접근 로그
/var/log/nginx/error.log 에러 로그
/var/www/html/ 기본 웹 루트

본 문서의 내용은 Nginx를 처음 다루는 개발자를 위한 최소한의 실무 기초입니다.
심화 학습은 [Nginx 공식 문서](https://nginx.org/en/docs/)를 참고하십시오.

Clone this wiki locally