Nginx Reverse Proxy 설정 가이드: Modern Infrastructure를 위한 핵심 전략
Nginx Reverse Proxy는 현대 웹 애플리케이션의 성능, 보안, 확장성을 위한 필수 구성 요소입니다. 이 가이드에서는 Nginx 리버스 프록시의 기본 설정부터 로드 밸런싱, SSL/TLS, 캐싱 등 고급 기능과 Docker, Kubernetes 환경에서의 활용법을 DevOps 관점에서 심층적으로 다룹니다.
Nginx Reverse Proxy 설정 가이드: Modern Infrastructure를 위한 핵심 전략
현대 웹 서비스는 마이크로서비스 아키텍처, 컨테이너 기반 배포, 클라우드 인프라 등 복잡한 환경에서 운영됩니다. 이러한 환경에서 안정적이고 효율적인 서비스 제공을 위해 Nginx는 단순한 웹 서버를 넘어 리버스 프록시, 로드 밸런서, 캐싱 서버 등 다재다능한 역할을 수행하며 핵심적인 위치를 차지하고 있습니다. 이 글에서는 DevOps 엔지니어링 관점에서 Nginx 리버스 프록시의 기본 개념부터 고급 설정, 그리고 Docker 및 Kubernetes 환경에서의 활용법까지 상세히 다루어 보겠습니다.
Nginx Reverse Proxy 이해
Nginx 리버스 프록시는 클라이언트의 요청을 직접 처리하는 대신, 이 요청을 백엔드 서버(예: 웹 애플리케이션 서버, API 서버)로 전달하고, 백엔드 서버로부터 받은 응답을 다시 클라이언트에게 전달하는 역할을 합니다. 이는 웹 서비스의 보안, 성능, 확장성, 유연성을 크게 향상시키는 중요한 아키텍처 패턴입니다.
Nginx 리버스 프록시의 주요 이점:
- 보안 강화: 클라이언트에게 백엔드 서버의 실제 IP 주소나 내부 구조를 노출하지 않아 보안 위협으로부터 보호합니다. 또한, Nginx에서 SSL/TLS Termination을 수행하여 백엔드 서버의 부담을 줄이고 보안을 중앙 집중화할 수 있습니다.
- 성능 향상: 정적 파일 캐싱, 압축, SSL/TLS 오프로딩 등을 통해 백엔드 서버의 부하를 줄이고 응답 시간을 단축하여 전반적인 서비스 성능을 개선합니다.
- 확장성 및 로드 밸런싱: 여러 대의 백엔드 서버로 트래픽을 효율적으로 분산하여 서비스의 가용성과 확장성을 확보합니다. 특정 서버에 장애가 발생하더라도 다른 서버로 트래픽을 우회하여 서비스 중단을 방지할 수 있습니다.
- 유연한 라우팅: URL 경로, 호스트 헤더 등에 따라 다른 백엔드 서버로 요청을 라우팅할 수 있어 A/B 테스트, 마이크로서비스 연동 등에 유용합니다.
- 중앙 집중식 관리: 모든 트래픽이 Nginx를 통과하므로, 접근 제어, 로깅, 모니터링 등을 한 곳에서 관리하기 용이합니다.
Nginx 설치 및 기본 설정
Nginx를 리버스 프록시로 활용하기 위한 첫 단계는 시스템에 Nginx를 설치하고 기본 설정 파일을 이해하는 것입니다.
Linux 환경에 Nginx 설치
대부분의 Linux 배포판에서 Nginx는 패키지 관리자를 통해 쉽게 설치할 수 있습니다.
Ubuntu/Debian 계열:
sudo apt update
sudo apt install nginx
CentOS/RHEL 계열:
sudo yum install epel-release # Nginx 저장소 추가
sudo yum install nginx
설치 후 Nginx 서비스를 시작하고 시스템 부팅 시 자동 실행되도록 설정합니다.
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx
방화벽이 활성화되어 있다면 HTTP(80) 및 HTTPS(443) 포트를 허용해야 합니다.
# Ubuntu (UFW)
sudo ufw allow 'Nginx HTTP'
sudo ufw allow 'Nginx HTTPS' # HTTPS 사용 시
sudo ufw enable
sudo ufw status
# CentOS (firewalld)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https # HTTPS 사용 시
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
Nginx 설정 파일 구조 이해
Nginx의 설정 파일은 주로 /etc/nginx 디렉토리에 위치합니다.
-
/etc/nginx/nginx.conf: Nginx의 전역 설정 파일입니다. worker 프로세스 수, 이벤트 모델, 기본 HTTP 설정 등이 포함됩니다. -
/etc/nginx/conf.d/*.conf: 개별 서비스나 모듈에 대한 설정을 위한 디렉토리입니다.nginx.conf에서 이 디렉토리의.conf파일을include하는 것이 일반적이며, 깔끔한 설정을 위해 권장됩니다. -
/etc/nginx/sites-available/및/etc/nginx/sites-enabled/: Debian/Ubuntu 계열에서 가상 호스트 설정을 관리하는 데 사용됩니다.sites-available에 설정 파일을 작성하고,sites-enabled에 심볼릭 링크를 생성하여 활성화합니다.
리버스 프록시 기본 설정
이제 Nginx를 사용하여 간단한 웹 애플리케이션을 리버스 프록시하는 방법을 살펴보겠습니다. 예를 들어, http://localhost:8080에서 실행 중인 백엔드 애플리케이션에 대해 example.com 도메인으로 들어오는 요청을 프록시하는 시나리오입니다.
conf.d 디렉토리 내에 myapp.conf 파일을 생성합니다.
# /etc/nginx/conf.d/myapp.conf
server {
listen 80; # 80번 포트로 들어오는 HTTP 요청을 수신합니다.
server_name example.com www.example.com; # 이 서버 블록이 처리할 도메인 이름입니다.
location / {
# 모든 요청 (/)을 http://localhost:8080으로 프록시합니다.
proxy_pass http://localhost:8080;
# 원본 요청의 헤더 정보를 백엔드 서버로 전달합니다.
# Host: 클라이언트가 요청한 Host 헤더를 백엔드로 전달합니다.
proxy_set_header Host $host;
# X-Real-IP: 클라이언트의 실제 IP 주소를 백엔드로 전달합니다.
proxy_set_header X-Real-IP $remote_addr;
# X-Forwarded-For: 프록시를 거쳐온 클라이언트 IP 체인을 전달합니다.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# X-Forwarded-Proto: 클라이언트가 사용한 프로토콜(http 또는 https)을 전달합니다.
proxy_set_header X-Forwarded-Proto $scheme;
}
}
설정 파일을 변경한 후에는 Nginx 설정의 유효성을 검사하고 서비스를 재시작해야 합니다.
sudo nginx -t # 설정 파일 문법 검사
sudo systemctl reload nginx # Nginx 서비스 재시작 (설정만 다시 로드)
# 또는 sudo systemctl restart nginx # Nginx 서비스 완전히 재시작
이제 example.com으로 접근하면 Nginx를 통해 http://localhost:8080에서 실행 중인 애플리케이션의 응답을 받을 수 있습니다.
고급 리버스 프록시 기능 활용
Nginx는 단순한 프록시를 넘어 로드 밸런싱, SSL/TLS Termination, 캐싱, WebSocket 프록시 등 다양한 고급 기능을 제공합니다.
로드 밸런싱
여러 대의 백엔드 서버에 트래픽을 분산하여 시스템의 가용성과 확장성을 높이는 기능입니다. upstream 블록을 사용하여 백엔드 서버 그룹을 정의하고, proxy_pass에서 이 그룹 이름을 참조합니다.
# /etc/nginx/conf.d/loadbalancer.conf
upstream backend_servers {
# 기본은 Round Robin 방식 (순차적으로 요청 분배)
server 192.168.1.100:8080;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
# 로드 밸런싱 알고리즘 지정 예시:
# least_conn; # 가장 적은 활성 연결을 가진 서버로 요청
# ip_hash; # 클라이언트 IP 주소의 해시값을 기반으로 서버 지정 (세션 유지에 유리)
# 서버 가중치 설정 (더 많은 트래픽을 받을 서버)
# server 192.168.1.100:8080 weight=3;
# server 192.168.1.101:8080 weight=1;
# 백업 서버 설정 (모든 주 서버가 다운되었을 때만 사용)
# server 192.168.1.103:8080 backup;
# 서버 비활성화 (유지보수 등)
# server 192.168.1.104:8080 down;
}
server {
listen 80;
server_name myapp.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;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
SSL/TLS Termination
Nginx에서 SSL/TLS 암호화/복호화를 처리하고, 백엔드 서버로는 암호화되지 않은 HTTP 요청을 전달하여 백엔드 서버의 부하를 줄이는 기법입니다. Let's Encrypt와 같은 무료 인증서를 활용하여 쉽게 HTTPS를 적용할 수 있습니다.
# /etc/nginx/conf.d/secure_myapp.conf
server {
listen 443 ssl; # 443번 포트로 들어오는 HTTPS 요청을 수신합니다.
server_name secure.example.com;
# SSL/TLS 인증서 및 키 파일 경로를 지정합니다.
ssl_certificate /etc/letsencrypt/live/secure.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/secure.example.com/privkey.pem;
# 보안을 위해 권장되는 SSL/TLS 프로토콜 및 암호화 스위트 설정
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:8080; # 백엔드로는 HTTP로 전달
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 https; # 백엔드에 원본 프로토콜이 HTTPS였음을 알림
}
}
# HTTP 요청을 HTTPS로 리다이렉트하는 설정 (선택 사항)
server {
listen 80;
server_name secure.example.com;
return 301 https://$host$request_uri;
}
캐싱 (Proxy Caching)
자주 요청되는 콘텐츠를 Nginx 서버에 저장하여 백엔드 서버의 부하를 줄이고 응답 속도를 향상시킬 수 있습니다.
# /etc/nginx/nginx.conf 또는 별도의 파일에 정의
# 캐시 저장 경로, 크기, 만료 시간 등을 설정합니다.
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
# /etc/nginx/conf.d/cache.conf
server {
listen 80;
server_name cache.example.com;
location / {
proxy_cache my_cache; # 위에서 정의한 캐시 존 사용
proxy_cache_valid 200 302 10m; # 200, 302 응답은 10분 동안 캐싱
proxy_cache_valid 404 1m; # 404 응답은 1분 동안 캐싱
proxy_cache_min_uses 1; # 1번 이상 요청된 경우 캐싱
proxy_cache_background_update on; # 백그라운드에서 만료된 캐시 업데이트
# 오류 발생 시 오래된 캐시를 제공하도록 설정
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
# 캐시 상태를 응답 헤더에 추가하여 디버깅에 활용
add_header X-Proxy-Cache $upstream_cache_status;
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;
}
}
WebSocket 프록시 설정
WebSocket은 HTTP와 달리 지속적인 양방향 통신을 제공하므로, Nginx를 통해 프록시하려면 특별한 설정이 필요합니다. Upgrade 및 Connection 헤더를 적절히 설정하여 Nginx가 WebSocket 연결을 올바르게 처리하도록 해야 합니다.
# /etc/nginx/conf.d/websocket.conf
server {
listen 80;
server_name ws.example.com;
location /ws/ {
proxy_pass http://localhost:8081; # WebSocket 백엔드 서버
proxy_http_version 1.1; # HTTP/1.1 프로토콜 사용
proxy_set_header Upgrade $http_upgrade; # Upgrade 헤더를 백엔드로 전달
proxy_set_header Connection "upgrade"; # Connection 헤더를 "upgrade"로 설정
proxy_set_header Host $host;
}
}
Docker 및 Kubernetes 환경에서의 Nginx
컨테이너 기반의 현대 인프라에서 Nginx는 더욱 중요한 역할을 합니다. Docker 컨테이너 내에서 Nginx를 실행하거나 Kubernetes Ingress Controller로 활용하여 트래픽 관리를 자동화할 수 있습니다.
Docker 컨테이너에서 Nginx 사용
Dockerfile을 사용하여 커스텀 Nginx 이미지를 빌드하고, docker-compose를 통해 애플리케이션 스택에 포함할 수 있습니다.
Dockerfile 예시:
# Dockerfile
# 공식 Nginx 이미지 사용
FROM nginx:latest
# 커스텀 Nginx 설정 파일 복사
# /etc/nginx/nginx.conf는 전역 설정, conf.d/는 개별 서비스 설정
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
# 80번, 443번 포트 노출
EXPOSE 80 443
# Nginx를 foreground로 실행하여 Docker 컨테이너가 종료되지 않도록 함
CMD ["nginx", "-g", "daemon off;"]
docker-compose.yml 예시:
# docker-compose.yml
version: '3.8'
services:
nginx:
build: . # 현재 디렉토리의 Dockerfile을 사용하여 빌드
ports:
- "80:80" # 호스트 80번 포트를 컨테이너 80번 포트에 매핑
- "443:443" # 호스트 443번 포트를 컨테이너 443번 포트에 매핑
volumes:
- ./conf.d:/etc/nginx/conf.d # 호스트의 conf.d 디렉토리를 컨테이너에 마운트
- ./nginx.conf:/etc/nginx/nginx.conf # 호스트의 nginx.conf를 컨테이너에 마운트
- ./log:/var/log/nginx # Nginx 로그를 호스트에 저장
depends_on:
- webapp # webapp 서비스가 먼저 시작되도록 의존성 설정
restart: always # 컨테이너 종료 시 항상 재시작
webapp:
image: my-webapp:latest # 미리 빌드된 웹 애플리케이션 이미지
ports:
- "8080:8080" # Nginx 컨테이너 내부에서 접근할 수 있도록 포트 노출 (외부 노출은 Nginx가 담당)
restart: always
이 설정으로 docker-compose up -d 명령어를 실행하면 Nginx와 백엔드 웹 애플리케이션이 함께 컨테이너로 배포되며, Nginx가 외부 트래픽을 웹 애플리케이션으로 프록시하게 됩니다.
Kubernetes Ingress Controller와 Nginx
Kubernetes 환경에서는 Ingress 리소스를 사용하여 클러스터 외부에서 내부 서비스로 들어오는 트래픽을 관리합니다. Nginx Ingress Controller는 이 Ingress 리소스를 모니터링하고, Nginx 설정을 동적으로 생성하여 트래픽을 적절한 서비스로 라우팅하는 역할을 합니다.
Nginx Ingress Controller를 사용하면, 개발자는 YAML 파일로 간단하게 Ingress 규칙을 정의하고, Nginx Ingress Controller가 자동으로 Nginx를 설정하여 복잡한 트래픽 라우팅, SSL/TLS Termination, 로드 밸런싱 등을 처리합니다. 이는 Kubernetes 환경에서 Nginx 리버스 프록시 기능을 추상화하고 자동화하는 핵심적인 방법입니다.
# Kubernetes Ingress Resource 예시
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # Nginx Ingress Controller 특정 어노테이션
spec:
ingressClassName: nginx # Nginx Ingress Controller 사용 지정
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service # Kubernetes 서비스 이름
port:
number: 8080 # 서비스 포트 번호
tls: # SSL/TLS 설정
- hosts:
- myapp.example.com
secretName: my-app-tls-secret관련 게시글
GitOps Workflow 설계 가이드: Kubernetes와 CI/CD를 활용한 자동화
GitOps는 선언적 인프라 및 애플리케이션 관리를 위한 강력한 패러다임입니다. 이 가이드에서는 Git을 Single Source of Truth로 활용하여 Kubernetes 환경에서 안정적이고 효율적인 GitOps 워크플로우를 설계하는 방법을 Docker, CI/CD 자동화 예시와 함께 상세히 설명합니다.
GitHub Actions Advanced Workflows: Docker, Kubernetes CI/CD
GitHub Actions를 활용한 Docker, Kubernetes 기반 CI/CD 파이프라인 구축 심화 가이드. DevOps 엔지니어링 관점에서 자동화 전략을 탐구합니다.
Terraform Infrastructure Automation: DevOps 엔지니어링 가이드
Terraform을 활용한 인프라 자동화의 핵심 개념부터 실제 AWS 환경에서의 배포 예시까지, DevOps 엔지니어링 관점에서 자세히 알아봅니다. IaC, Docker, Kubernetes, CI/CD 파이프라인 통합 전략을 다룹니다.