1. 파일 구조
your-project/
├── docker-compose.yml
├── nginx/
│   ├── nginx.conf
│   ├── certs/
│   │   ├── fullchain.pem
│   │   └── privkey.pem
│   └── logs/                  # 로그 디렉토리 (마운트됨)
├── static/
│   └── index.html
└── backend/
    ├── Dockerfile
    └── (Spring 소스 코드 등)
  1. docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:stable
    container_name: nginx
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./static:/usr/share/nginx/html:ro
      - ./nginx/certs:/etc/nginx/certs:ro
      - ./nginx/logs:/var/log/nginx
    depends_on:
      backend:
        condition: service_healthy
    networks:
      - frontend

  backend:
    image: your-backend-image   # 예: junhyunny/my-spring-app
    container_name: backend
    restart: always
    ports:
      - "8080:8080"              # 필요시 외부 접근 허용, 내부만 사용시 expose로 변경 가능
    environment:
      - SPRING_PROFILES_ACTIVE=prod
    healthcheck:
			test: ["CMD", "curl", "--fail", "--silent", "--connect-timeout", "5", "<http://localhost:8080/actuator/health>"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - frontend

networks:
  frontend:
    driver: bridge
  1. nginx.conf
worker_processes auto;

events {
    worker_connections 1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;

    # Gzip 압축
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;

    # 캐시 처리 (정적 리소스)
    open_file_cache max=1000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # HTTP → HTTPS 리디렉션
    server {
        listen 80;
        server_name localhost;
        return 301 https://$host$request_uri;
    }

    # HTTPS 메인 서버
    server {
        listen 443 ssl http2;
        server_name localhost;

        ssl_certificate     /etc/nginx/certs/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/privkey.pem;

        location / {
            root   /usr/share/nginx/html;
            index  index.html;
            try_files $uri $uri/ /index.html;  # SPA 라우팅 대응
        }

        location /api/ {
            rewrite ^/api(/.*)$ $1 break;      # prefix 유지
            proxy_pass <http://backend:8080>;
            proxy_http_version 1.1;
            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;
        }

        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
            expires 7d;
            add_header Cache-Control "public";
        }
    }
}
항목 Perplexity 예제 개선된 버전 (GPT)
API 경로 proxy /api/ → /로 prefix 손실 rewrite로 prefix 유지
gzip 압축 ❌ 없음 ✅ 실무에서 필수 적용
정적 파일 캐싱 ❌ 없음 ✅ Cache-Control, expires
HTTP/2 지원 ❌ 없음 ✅ listen 443 ssl http2;
healthcheck 기본 curl만 --silent, --connect-timeout 추가
로그 디렉토리 폴더 유무 확인 안됨 :rw 권한 명시 및 폴더 구성 제안
SPA 지원 ❌ 없음 ✅ try_files $uri /index.html
설정 유효성 검사 ❌ 없음 📌 운영 시 nginx -t 필수 검증 필요

주요 피드백 반영 포인트