Published on

무중단 배포를 위한 Next.js Static 파일 관리 전략

Authors
  • avatar
    Name
    최영준 (Youngjun Choi)
    Twitter
HTML: <script src="...page-OLD_HASH.js">
브라우저: page-OLD_HASH.js 다운로드 ✅


┌─────────────────────────────────────────────────────────┐
T=1: 새 버전 배포 시작 (--delete 옵션 사용)└─────────────────────────────────────────────────────────┘

블루 서버 (v1) 계속 실행          S3/CDN 업데이트
├─ manifest                       ├─ page-OLD_HASH.js ❌ 삭제!
│  └─ page-OLD_HASH.js 참조       └─ page-NEW_HASH.js ✅ 업로드
└─ 여전히 트래픽 받는 중

그린 서버 (v2) 시작
├─ manifest
│  └─ page-NEW_HASH.js 참조
└─ 헬스체크 대기 중


┌─────────────────────────────────────────────────────────┐
T=2: 문제 발생! (블루-그린 전환 전)└─────────────────────────────────────────────────────────┘

사용자 B/about 접속
로드밸런서 → 블루 서버(v1)로 라우팅
블루 서버 SSR 실행
HTML: <script src="...page-OLD_HASH.js">
브라우저: page-OLD_HASH.js 요청
S3/CDN:404 Not Found (이미 삭제됨)
ChunkLoadError 발생!


┌─────────────────────────────────────────────────────────┐
T=3: 블루-그린 전환 완료                                 │
└─────────────────────────────────────────────────────────┘

블루 서버 (v1) 종료               S3/CDN
                                  └─ page-NEW_HASH.js그린 서버 (v2) 활성화
├─ manifest
│  └─ page-NEW_HASH.js 참조
└─ 모든 트래픽 수신

사용자 C/about 접속
그린 서버 SSR 실행
HTML: <script src="...page-NEW_HASH.js">
브라우저: page-NEW_HASH.js 다운로드 ✅
정상 동작 ✅

실제 재현 결과

개발 환경에서 재현하기 위해 빌드 후 특정 청크를 삭제했다:

# 빌드
npm run build

rm .next/static/chunks/app/about/page-817d6baba2395b08.js

# 서버 시작
npm run start

브라우저에서 /about 접속 시:

해결 방법

해결방법은 새로운 버전의 결과물을 배포할 때에도 이전 버전의 static 결과물을 서빙가능하도록 해주는 것이다.

그러기 위해서 static 결과물은 따로 CDN에서 서빙하도록 수정했고, 해당 CDN 주소는 BUILD_ID를 기반으로 구분된 폴더로 서빙해서 독립적으로 관리할 수 있도록 했다. 사실 코어에서는 이미 해당방법을 사용하고 있어서 아주 간단하게 CLI 옵션을 키고 CDN의 동작을 수정하면 되는 상황이었다.

기존 CSR 서비스에서 SSR 기반 서비스로 전환하면서 해당 CLI 옵션과 동작 설정이 누락되면서 발생했던 것 같다.


정리

해당 이슈를 수정하면서 프론트 서버에 대한 이해도를 조금 더 높여야겠다는 생각이 들었다. 노드 개발자분이 제보하지 않으셨다면 지속적으로 트래픽이 떨어지는 구간이 발생했을 것이란 생각에 아찔했다.

한편으로는 해당 이슈를 디버깅하면서 그냥 사용하고 있던 Next Build 결과물에 대한 이해와 배포 프로세스, 인프라 세팅에 대한 이해도가 한층 높아져 많이 배울 수 있었다.