빌드된 SPA(Single-Page Application: React·Vue 등)는 정적 파일 묶음이라 nginx 같은 웹 서버로 바로 서빙할 수 있다. 핵심은 try_files로 없는 경로를 index.html로 돌려보내 클라이언트 라우터(client-side router)가 주소를 처리하게 하는 것이다.
server {
listen 80;
server_name example.com;
root /var/www/app/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}try_files $uri $uri/ /index.html: 요청한 파일이 있으면 그 파일, 디렉터리면 그 안의 index, 둘 다 없으면index.html을 준다. 이게 없으면/users/1에서 새로고침할 때 404가 난다- 해시가 붙은 정적 파일은 길게 캐시하고,
index.html은 캐시를 짧게 두어 새 배포가 바로 보이게 한다(브라우저 캐시) - API는 같은 서버에서
location /api/ { proxy_pass http://backend:8080; }로 넘기면 출처가 같아져 CORS 설정이 필요 없다
운영 팁
- 설정은
/etc/nginx/sites-available에 두고sites-enabled로 링크하는 배포판이 많다. 바꾼 뒤nginx -t로 검사하고systemctl reload nginx - 500·403이 나면 nginx 작업 계정(
www-data등)이 정적 파일 경로를 읽을 수 있는지 본다.user root로 바꿔 해결하는 글이 있지만 권한을 넓히는 위험한 방법이다. 파일·상위 디렉터리 권한을 고친다 - 다른 서비스가 80번을 쓰고 있다면
listen포트를 바꾸거나 그 프로세스를 정리한다(포트를 쓰는 프로세스 찾아 종료하기)
HTTPS는 Let's Encrypt로 HTTPS 적용, 어떤 렌더링 방식이 정적 서빙에 맞는지는 CSR·SSR·SSG·ISR를 본다. 컨테이너로 묶을 때는 빌드 단계와 nginx 단계를 나눈 멀티 스테이지 빌드가 흔하다.