GCP에 Next.js 배포

발행: (2026년 2월 22일 오전 03:36 GMT+9)
5 분 소요
원문: Dev.to

I’m happy to help translate the article, but I’ll need the text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source line, formatting, markdown, and any code blocks exactly as they are while translating the rest into Korean.

왜 Vercel에서 GCP로 이동할까?

LLM Gateway는 여러 API와 프런트엔드를 갖춘 풀스택 애플리케이션입니다. 모든 것을 Vercel을 통해 배포하면 또 다른 대시보드, 또 다른 자격 증명 세트, 그리고 또 다른 관리 항목이 추가되었습니다. Google Cloud Platform을 직접 사용함으로써 인프라를 통합할 수 있습니다: API, 데이터베이스, 그리고 프런트엔드가 모두 같은 장소에 존재합니다.

아키텍처

모든 서비스는 GCP의 Kubernetes 클러스터에서 실행됩니다. 각 구성 요소—API, Gateway, UI, Playground, Docs, Admin, 그리고 Worker—는 별개의 컨테이너로 배포됩니다. Kubernetes는 리소스 사용량에 따라 자동 스케일링을 처리하여 트래픽 급증 시에는 확장하고 트래픽이 적을 때는 축소합니다.

빌드 및 배포 파이프라인은 GitHub Actions를 통해 완전 자동화됩니다. main 브랜치에 푸시될 때마다 각 서비스에 대한 Docker 이미지가 빌드되어 컨테이너 레지스트리에 푸시됩니다.

독립 실행형 모드에서 Next.js 앱 빌드하기

next.config.js에 다음을 추가합니다:

module.exports = {
  output: "standalone",
};

이렇게 하면 모든 종속성이 포함된 자체 포함 폴더로 앱이 번들됩니다.

Dockerfile

# Builder stage
FROM node:20-slim AS builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build

# Runner stage
FROM node:20-slim AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV HOSTNAME="0.0.0.0"
ENV PORT=80

COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public

EXPOSE 80
CMD ["node", "server.js"]

이미지 빌드 및 푸시

docker build -t gcr.io/your-project/your-app:latest .
docker push gcr.io/your-project/your-app:latest

Cloud Run에 배포

gcloud run deploy your-app \
  --image gcr.io/your-project/your-app:latest \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated

쿠버네티스 배포

apiVersion: apps/v1
kind: Deployment
metadata:
  name: your-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: your-app
  template:
    metadata:
      labels:
        app: your-app
    spec:
      containers:
        - name: your-app
          image: gcr.io/your-project/your-app:latest
          ports:
            - containerPort: 80
          resources:
            requests:
              memory: "256Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "500m"

다음 명령으로 적용:

kubectl apply -f deployment.yaml

수평 포드 자동 스케일러

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: your-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: your-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

이것은 CPU 사용량을 기준으로 배포를 2~10개의 복제본 사이로 자동으로 조정합니다.

GitHub Actions 워크플로우 (빌드 및 푸시)

다음 내용을 .github/workflows/build.yml 파일로 저장하세요:

name: Build and Push

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

Takeaway

이미 GCP를 사용하고 있다면 Vercel을 추가할 필요가 없을 수도 있습니다. Kubernetes와 Cloud Run은 Next.js를 잘 처리하며, 모든 것을 한 곳에 두면 운영이 간소화되고 뛰어난 성능과 낮은 지연 시간을 제공할 수 있습니다.

0 조회
Back to Blog

관련 글

더 보기 »

서브넷팅 설명

Subnetting이란 무엇인가? 큰 아파트 건물을 여러 층으로 나누는 것과 같다. 각 층 서브넷은 자체 번호가 매겨진 유닛(hosts)을 가지고, 그리고 건물…