Next.js 앱을 개발한 뒤 가장 먼저 맞닥뜨리는 질문은 "어디에 어떻게 올릴 것인가"다. Vercel은 설정 없이 바로 동작하지만, 인프라 통제권이 필요하거나 비용을 최적화해야 할 때는 self-hosting이 현실적인 선택이 된다. 각 방식의 동작 원리와 트레이드오프를 이해하면 프로젝트 요구사항에 맞는 결정을 내릴 수 있다.
Vercel은 Next.js 제작사가 운영하는 플랫폼으로, git push 한 번으로 배포가 완료된다. App Router의 Server Component, Edge Runtime, ISR 등 Next.js 기능을 추가 설정 없이 지원한다.
# Vercel CLI로 배포
npm i -g vercel
vercel --prod
배포 흐름은 다음과 같다.
GitHub push
│
▼
Vercel Build (next build)
│
├─ Static assets → CDN Edge Network (전 세계)
├─ Server Components → Serverless Function (리전별)
└─ API Routes → Serverless Function
Serverless Function — 요청이 올 때만 실행되는 함수 단위 컴퓨팅. 항상 켜진 서버가 없어 유휴 비용이 없다.
환경별 설정은 Vercel 대시보드의 Environment Variables에서 Production / Preview / Development로 분리 관리한다.
# 로컬에서 Vercel 환경변수 풀다운
vercel env pull .env.local
서버를 직접 제어해야 하거나 사내 Kubernetes 클러스터에 올려야 한다면 Docker 이미지를 빌드하는 방식을 선택한다. Next.js는 output: 'standalone' 옵션으로 node_modules 없이 실행 가능한 최소 번들을 생성한다.
// next.config.ts
const nextConfig = {
output: 'standalone',
};
export default nextConfig;
FROM node:20-alpine AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build
FROM node:20-alpine AS runner
WORKDIR /app
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"]
Multi-stage build — 빌드 도구와 의존성을 최종 이미지에 포함하지 않아 이미지 크기를 줄이는 Dockerfile 패턴.
환경별 설정은 컨테이너 실행 시 -e 플래그나 Kubernetes ConfigMap / Secret으로 주입한다.
docker run -e DATABASE_URL=... -e NEXT_PUBLIC_API_URL=... -p 3000:3000 my-next-app
백엔드 로직이 없는 마케팅 페이지나 문서 사이트는 static export로 순수 HTML/CSS/JS 파일만 생성해 GitHub Pages에 올릴 수 있다.
// next.config.ts
const nextConfig = {
output: 'export',
basePath: '/my-repo', // GitHub Pages 서브경로
trailingSlash: true,
};
export default nextConfig;
# .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./out
output: 'export'를 사용하면 Server Component의 동적 데이터 페칭, API Routes, Middleware는 동작하지 않는다.
| 항목 | Vercel | Docker | GitHub Pages |
|---|---|---|---|
| 설정 난이도 | 낮음 | 중간 | 낮음 |
| Server Component 지원 | 완전 지원 | 완전 지원 | 미지원 |
| 비용 | 트래픽 기반 | 인프라 고정비 | 무료 |
| 인프라 통제 | 불가 | 완전 통제 | 불가 |
| 적합한 케이스 | SaaS, 빠른 출시 | 사내망, 규정 준수 | 정적 문서/랜딩 |
동적 기능이 필요하다면 Vercel 또는 Docker를, 완전히 정적인 콘텐츠라면 GitHub Pages가 가장 단순한 선택이다. 팀의 인프라 역량과 비용 구조를 함께 고려해 결정한다.