배포 — Vercel과 셀프 호스팅
배포 — Vercel과 셀프 호스팅
Next.js 프로젝트를 완성했습니다. 이제 배포를 해야 하는데, Vercel을 쓰면 간편하다고 합니다. 그런데 회사에서는 자체 서버에 배포해야 한다면 어떻게 해야 할까요?
Next.js는 Vercel이 만든 프레임워크이므로 Vercel 배포가 가장 매끄럽습니다. 하지만 Docker 컨테이너, Node.js 서버, Cloudflare Pages 등으로 셀프 호스팅도 충분히 가능합니다. 각 방식의 차이와 트레이드오프를 이해하고 선택하는 것이 중요합니다.
Vercel — 원클릭 배포
왜 Vercel이 가장 간편한가
- GitHub 저장소를 연결하면 push할 때마다 자동 배포 됩니다.
- SSR, ISR, 미들웨어, 이미지 최적화 등 Next.js의 모든 기능이 별도 설정 없이 동작합니다.
- PR마다 Preview 배포 가 자동 생성되어 리뷰가 편합니다.
- 전 세계 Edge Network에 배포되어 응답 속도가 빠릅니다.
배포 과정
1. GitHub 저장소에 push
2. vercel.com에서 "Import Project"
3. 저장소 선택 → Deploy
4. 끝. https://프로젝트명.vercel.app 에서 확인
환경 변수는 Vercel 대시보드의 Settings > Environment Variables에서 설정합니다.
Vercel의 한계
| 항목 | 내용 |
|---|---|
| 비용 | 무료 플랜은 개인/취미용. 상용은 Pro/Enterprise 필요 |
| 벤더 종속 | Vercel 인프라에 의존. 이전이 쉽지 않을 수 있음 |
| 서버리스 제한 | 함수 실행 시간 제한 (무료 10초, Pro 60초) |
| 리전 선택 | 무료 플랜은 리전 제한 있음 |
Docker 셀프 호스팅 — standalone 출력
회사 서버, AWS EC2, GCP VM 등에 직접 배포해야 할 때 사용하는 방식입니다.
standalone 모드 설정
// next.config.ts
const nextConfig = {
output: 'standalone',
};
export default nextConfig;
이 설정을 추가하고 빌드하면, .next/standalone 폴더에 실행에 필요한 모든 파일 이 모입니다.
node_modules 전체를 복사할 필요 없이 이 폴더만으로 서버를 실행할 수 있습니다.
Dockerfile 예시
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# standalone 출력 복사
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
핵심은 멀티 스테이지 빌드 입니다.
builder스테이지에서 빌드합니다.runner스테이지에서 빌드 결과물만 복사합니다.- 최종 이미지에는 소스 코드와 devDependencies가 포함되지 않아 이미지 크기가 작습니다.
셀프 호스팅에서 추가로 신경 쓸 것
| 항목 | Vercel | 셀프 호스팅 |
|---|---|---|
| ISR 캐시 | 자동 관리 | 파일 시스템 기본. 다중 인스턴스면 공유 캐시 필요 |
| 이미지 최적화 | 자동 | sharp 패키지 설치 필요 (npm install sharp) |
| 환경 변수 | 대시보드 | .env 파일 또는 Docker env |
| HTTPS | 자동 | nginx/traefik 등 리버스 프록시 필요 |
| CDN | 내장 Edge Network | 별도 CDN(CloudFront 등) 설정 필요 |
정적 내보내기 — next export
서버 기능이 필요 없다면 완전한 정적 사이트로 내보낼 수 있습니다.
// next.config.ts
const nextConfig = {
output: 'export',
};
export default nextConfig;
npm run build 후 out/ 폴더에 정적 HTML/CSS/JS가 생성됩니다.
이 폴더를 **아무 정적 호스팅 **(GitHub Pages, S3, Netlify)에 올리면 됩니다.
** 제한사항 **: SSR, ISR, 미들웨어, 이미지 최적화, Route Handler 등 ** 서버 기능을 사용할 수 없습니다 **.
Cloudflare Pages
Cloudflare Pages는 Edge Runtime 기반으로 Next.js를 배포할 수 있습니다.
npm install @cloudflare/next-on-pages
Vercel과 비슷하게 Git 연동으로 자동 배포가 가능하며, Edge Network를 활용합니다. 다만 Node.js Runtime의 모든 API를 지원하지는 않으므로, Edge 호환성을 확인해야 합니다.
배포 방식 선택 가이드
| 상황 | 추천 방식 |
|---|---|
| 개인 프로젝트, 빠른 배포 | Vercel |
| 회사 서버, 온프레미스 | Docker + standalone |
| 완전 정적 사이트 (블로그, 문서) | output: 'export' + 정적 호스팅 |
| Edge 우선, Cloudflare 생태계 | Cloudflare Pages |
| 비용 최소화, 서버 기능 필요 | Docker + 저렴한 VPS (EC2, DigitalOcean) |
주의할 점
standalone에서 static 폴더를 빼먹으면 CSS가 안 나온다
output: 'standalone' 빌드 결과에는 .next/static과 public 폴더가 ** 포함되지 않습니다 **.
Dockerfile에서 이 폴더들을 명시적으로 복사해야 합니다.
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
이걸 빠뜨리면 배포 후 CSS, JS, 이미지가 전부 깨져 보입니다.
ISR을 셀프 호스팅할 때 다중 인스턴스 문제
ISR의 캐시는 기본적으로 ** 파일 시스템 **에 저장됩니다. 서버 인스턴스가 여러 개이면 각 인스턴스가 서로 다른 캐시를 가지게 되어 ** 사용자마다 다른 버전의 페이지 **를 볼 수 있습니다.
해결 방법은 ** 공유 캐시 핸들러 **(Redis, S3 등)를 설정하는 것입니다. Next.js 문서에서 Custom Cache Handler 가이드를 확인할 수 있습니다.
정리
| 방식 | 장점 | 단점 |
|---|---|---|
| Vercel | 설정 0, 모든 기능 지원 | 비용, 벤더 종속 |
| Docker standalone | 어디서든 실행 가능 | 인프라 직접 관리 |
| 정적 내보내기 | 가장 단순, 무료 호스팅 | 서버 기능 불가 |
| Cloudflare Pages | Edge 성능, 저렴 | Node.js API 제한 |
기억할 한 줄: "Vercel이 가장 편하고, 셀프 호스팅이라면 standalone + Docker가 정석이다."