server { listen 80; server_name _; root /usr/share/nginx/html; index index.html; # index.html은 캐시 금지 (배포 반영 핵심) location = /index.html { add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; try_files $uri =404; } # 정적 리소스는 장기 캐시 (Vite 해시 파일) location /assets/ { add_header Cache-Control "public, max-age=31536000, immutable"; try_files $uri =404; } # travel thumbnails (generated by travel-proxy, stored in /data/thumbs) location ^~ /media/travel/.thumb/ { alias /data/thumbs/; expires 30d; add_header Cache-Control "public, max-age=2592000, immutable" always; autoindex off; } # travel media (images) - nginx가 직접 파일 서빙 location ^~ /media/travel/ { alias /data/travel/; # ✅ /media/travel/... -> /data/travel/... expires 7d; add_header Cache-Control "public, max-age=604800" always; # 옵션: 폴더리스팅 막기 autoindex off; } # 기타 정적 파일(예: vite.svg 등) 기본 캐시(원하면 조정) location ~* \.(?:ico|png|jpg|jpeg|gif|svg|webp|css|js)$ { add_header Cache-Control "public, max-age=604800"; try_files $uri =404; } # travel API location /api/travel/ { 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; proxy_pass http://travel-proxy:8000/api/travel/; } # stock API location /api/stock/ { 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; proxy_pass http://stock-lab:8000/api/stock/; } # trade API (Stock Lab Proxy) location /api/trade/ { 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; proxy_pass http://stock-lab:8000/api/trade/; } # API 프록시 (여기가 포인트: /api/ 중복 제거) location /api/ { 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; proxy_pass http://backend:8000; } # webhook receiver (handle both /webhook and /webhook/) location = /webhook { 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; proxy_pass http://deployer:9000/webhook; } location /webhook/ { 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; proxy_pass http://deployer:9000/webhook; } # SPA 라우팅 (마지막에 두는 게 안전) location / { try_files $uri $uri/ /index.html; } # gzip (옵션) gzip on; gzip_types text/plain text/css application/json application/javascript application/xml+rss; gzip_min_length 1024; }