한 줄: Vercel deploy --prebuilt에서 --archive=tgz는 파일 수 한도를 우회하지만, 이미지·정적 자산이 많은 사이트는 개별 업로드(아카이브 없이)로 전송량·실패 범위를 줄이는 편이 낫다.
로컬에서 vercel build로 .vercel/output을 만든 뒤 올리는 프리빌트 배포는 서버 빌드 시간을 아끼지만, 업로드 방식에 따라 대역·재시도 비용이 갈린다. 15,000개 파일 한도에 걸리면 아카이브가 필수이고, 이미지 폴더가 비대한 콘텐츠 사이트는 자산 제외·CDN 분리·증분 패턴을 먼저 짜 둔다. 호스팅 한도 자체는 Vercel 무료 플랜 한도 글과 같이 보면 된다.
일반 vercel deploy는 원격에서 설치·빌드를 돌린다. 프리빌트는 로컬(또는 CI 러너)에서 이미 만든 Output File System 트리를 그대로 올린다.
# 환경 설정 동기화 → 로컬 빌드 → 프리빌트 업로드
vercel pull --yes --environment=production --token "$VERCEL_TOKEN"
vercel build --prod --token "$VERCEL_TOKEN"
vercel deploy --prebuilt --prod --token "$VERCEL_TOKEN"
산출물은 보통 .vercel/output 아래에 모인다. Next.js 정적·서버리스 라우트, public/ 정적 파일, 설정 JSON이 포함된다. 서버 빌드를 스킵하므로 Node 버전·캐시 불일치를 줄이고, macOS에서 flaky 한 .next rmdir 이슈를 로컬에서 재시도 루프로 감싸기 쉽다.
배포 체크리스트 관점의 백엔드 공통 항목은 프로덕션 배포 체크리스트를 참고하고, 이 글은 업로드 패키징 방식에 집중한다.
CLI 옵션 --archive=tgz는 산출물을 tar.gz 한 덩어리로 묶어 올린다. 옵션을 빼면 파일을 개별(또는 배치)로 전송한다. 둘 다 같은 프리빌트 트리에서 출발하지만 운영 특성이 다르다.
| 항목 |
--archive=tgz |
개별 업로드(아카이브 없음) |
| 파일 수 한도 |
다수 파일을 1개 아카이브로 우회 |
파일 개수 한도에 직접 걸림 |
| 전송 단위 |
한 번에 전체 묶음 |
파일·청크 단위, 부분 재시도에 유리 |
| 이미지 비중 큰 사이트 |
매번 전체 압축·업로드 비용 |
변경 파일 위주 전략과 맞추기 쉬움 |
| 실패 시 |
묶음 단위 재전송 |
실패 파일만 재시도 가능(클라이언트·버전에 따라) |
| 추천 상황 |
파일 수만 많고 용량 중간, 한도 우회 우선 |
용량·이미지 절약·디버깅·네트워크 불안정 |
# 파일 수 한도 우회 (아카이브)
vercel deploy --prebuilt --prod --archive=tgz --token "$VERCEL_TOKEN"
# 개별 업로드 (아카이브 생략) | 이미지·용량 전략과 병행
vercel deploy --prebuilt --prod --token "$VERCEL_TOKEN"
CLI 버전·플랜에 따라 한도 숫자와 플래그 기본값이 바뀔 수 있다. 배포 로그에 file limit / archive 관련 경고가 보이면 그때 전환한다. 엣지·함수 비용 쪽은 Edge Function 비용 최적화를 같이 본다.
콘텐츠 사이트의 public/images/posts/·썸네일은 수천 장이 되면 프리빌트 트리가 수 GB에 가깝다. 업로드 방식만 바꿔서는 한계가 있고, 배포에 넣을 자산 예산을 먼저 정한다.
- 객체 스토리지·별도 CDN: 본문 이미지는 S3/R2/Cloudflare Images 등으로 두고, 앱 배포에는 최근 N건·필수 아이콘만 남긴다.
- 생성 시 압축: JPEG quality, WebP, 1200px 폭 제한. 원본 4K PNG를 public에 넣지 않는다.
- .vercelignore / 빌드 전 정리: 로컬 전용 스크린샷, 중복 썸네일, 미사용 크롤 결과를 산출물 전에 제외한다.
- Next images unoptimized: 이미 unoptimized면 최적화 파이프라인 산출이 늘지 않는지 확인한다.
- 증분 배포 습관: 글 3편 추가마다 전체 이미지 트리를 다시 묶지 않도록, 변경 분량 로그를 남긴다.
# 산출물·public 용량 스냅샷 (배포 전)
du -sh public/images public .vercel/output 2>/dev/null || true
find public/images -type f | wc -l
# 큰 파일 top 20
find public/images -type f -exec ls -la {} + 2>/dev/null | sort -k5 -n -r | head -20
아카이브를 쓰면 압축으로 전송 바이트가 줄 수는 있어도, 매 배포마다 전체 묶음을 다시 만드는 비용은 남는다. 이미지가 병목이면 “압축 포맷”보다 “배포 세트에 이미지를 덜 넣기”가 효과가 크다.
macOS에서 Next 빌드가 .next·.vercel/output rmdir ENOTEMPTY로 간헐 실패하는 경우가 있다. 프리빌트 스크립트는 쓰기 권한 부여 후 디렉터리를 비우고, 빌드를 수 회 재시도하는 편이 안전하다.
#!/bin/bash
set -e
: "${VERCEL_TOKEN:?VERCEL_TOKEN 필요}"
MODE="prod"; [ "$1" = "--preview" ] && MODE="preview"
# 스테일 산출물 정리
chmod -R u+w .next .vercel/output 2>/dev/null || true
rm -rf .next .vercel/output 2>/dev/null || true
build_retry() {
local n=0
until vercel build "$@" --token "$VERCEL_TOKEN"; do
n=$((n + 1)); [ "$n" -ge 4 ] && exit 1
chmod -R u+w .next .vercel/output 2>/dev/null || true
rm -rf .next .vercel/output 2>/dev/null || true
done
}
if [ "$MODE" = "prod" ]; then
vercel pull --yes --environment=production --token "$VERCEL_TOKEN"
build_retry --prod
# 파일 수 한도면 --archive=tgz 추가. 이미지 절약 우선이면 생략.
vercel deploy --prebuilt --prod --token "$VERCEL_TOKEN"
else
vercel pull --yes --environment=preview --token "$VERCEL_TOKEN"
build_retry
vercel deploy --prebuilt --token "$VERCEL_TOKEN"
fi
토큰은 환경변수·CI secret에만 두고 저장소에 커밋하지 않는다. 프로덕션/프리뷰 분기를 스크립트 인자로 고정하면 launchd·cron에서 실수 배포를 줄인다. 스케줄 연동은 cron 스케줄 가이드 패턴과 같다.
운영에서 쓰는 분기 순서다.
- 파일 개수가 플랫폼 한도를 넘으면 →
--archive=tgz 필수. 이미지를 빼도 청크·페이지 산출이 많으면 아카이브를 유지한다.
- 한도 안인데 du -sh .vercel/output이 크면 → 이미지·폰트·불필요 소스를 배포 세트에서 제거. 그다음 개별 업로드로 전환해 실패 범위를 줄인다.
- 네트워크가 불안정하면 → 개별 업로드 + 재시도 로그. 아카이브 한 방 실패보다 디버깅이 쉽다.
- CI 분(minute) 비용이 문제면 → 프리빌트 자체는 유지하고, 이미지 예산을 줄여 업로드 시간을 깎는다.
- sitemap·RSS는 배포 전에 로컬/CI에서 갱신한다. 피드 동기화는 prebuild sitemap·RSS 글을 따른다.
호스팅 비교(Netlify·Cloudflare Pages 등)는 Vercel vs Netlify vs Cloudflare Pages를 보면 되고, 여기서는 Vercel CLI 프리빌트 경로만 다룬다.
※ CLI 플래그·파일 수 한도는 Vercel 정책·버전 업데이트에 따라 바뀔 수 있다. 배포 로그 경고를 우선한다.
배포 전후로 같은 체크를 남기면 “이미지가 갑자기 느려진” 원인을 업로드 방식과 분리할 수 있다.
# 빌드 산출 존재
test -d .vercel/output && echo "output ok"
# 업로드 방식 기록 (스크립트에 로그 한 줄)
echo "deploy_mode=files" # 또는 archive=tgz
# 라이브 스모크
curl -sI "https://your-domain.example/" | head -5
curl -sI "https://your-domain.example/favicon.ico" | head -5
# 최근 배포 URL은 CLI 출력의 Production/Preview URL 사용
콘텐츠 추가 직후라면 npm run prebuild로 피드까지 맞춘 뒤 프리빌트를 돌린다. 빌드만 성공하고 검색 목록이 어제 상태인 사고는 업로드 방식과 무관하다.
CLI 옵션·한도는 Vercel 버전·플랜에 따라 다릅니다. 배포 로그와 공식 CLI 헬프(vercel deploy --help)를 기준으로 맞추면 됩니다.