Next.js와 Hono, Bun, Cloud Run으로 구축하는 고성능 웹 사이트 배포 파이프라인

곽태욱·2026년 1월 29일

안녕하세요! 사이드 프로젝트에서 사용하고 있는 최신 웹 기술 스택과 배포 파이프라인을 소개하려고 합니다.

프론트엔드로 Next.js (App Router), 백엔드 로직 일부에 Hono를 사용하고 있으며, 모든 런타임과 빌드 도구로 Bun을 적극적으로 활용하고 있습니다. 이 글에서는 이 기술을 Google Cloud Run과 Cloud Build, 그리고 Cloudflare와 엮어 어떻게 효율적이고 자동화된 배포 환경을 구축했는지 공유합니다.

1. 아키텍처 개요

전체적인 아키텍처는 다음과 같습니다.

  • Frontend: Next.js 16 (Standalone Output)
  • Backend API: Hono
  • Runtime & Package Manager: Bun
  • Containerization: Docker
  • CI/CD: Google Cloud Build
  • Compute: Google Cloud Run (Serverless Container)
  • CDN & DNS: Cloudflare (by Terraform)

GitHub에 코드가 푸시되면 Cloud Build가 트리거되어 Docker 이미지를 빌드하고, Cloud Run에 배포된 후 서비스됩니다. 사용자는 Cloudflare CDN을 거쳐 최적화된 콘텐츠를 제공받습니다.

2. Docker와 Bun을 활용한 이미지 빌드 전략

빌드 속도와 런타임 성능을 모두 잡기 위해 Bun을 전면적으로 도입했습니다. 프론트엔드와 백엔드 각각에 맞는 최적화된 Dockerfile 전략을 사용합니다.

Frontend: Next.js + Bun + Alpine

Next.js 앱은 standalone 모드를 사용하여 꼭 필요한 파일만 포함한 경량 이미지를 만듭니다.

Dockerfile.nextjs 파일의 핵심 포인트:
1. Bun 기반 빌드: oven/bun:1.3 이미지를 사용해 의존성을 설치하고 빌드합니다. npm이나 yarn보다 훨씬 빠른 속도를 자랑합니다.
2. 보안 강화: 소스맵(sourceMappingURL)을 제거하여 코드를 보호하고 브라우저의 불필요한 요청을 방지합니다.
3. 경량화된 런타임: oven/bun:1.3-alpine을 베이스로 사용하여 이미지 크기를 줄이고, standalone 폴더와 static 에셋만 복사하여 실행합니다.

# Dockerfile.nextjs (요약)
FROM oven/bun:1.3 AS builder
# ... 의존성 설치 및 환경변수 설정 ...
RUN bun run build
# 소스맵 제거로 보안 강화
RUN find .next/static -type f -name '*.js' -exec sed -i -E 's@//# sourceMappingURL=.*$@@g' {} +

FROM oven/bun:1.3-alpine AS runner
# ...
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
CMD ["bun", "./server.js"]

Backend: Hono + Bun Compile + Distroless

Hono 기반의 백엔드 서비스는 Bun의 강력한 기능인 bun build --compile을 사용하여 단일 실행 파일로 컴파일합니다.

Dockerfile.hono 파일의 핵심 포인트:
1. Single Binary: 소스 코드를 실행 가능한 하나의 바이너리 파일(backend)로 만듭니다.
2. Distroless 이미지: 런타임에는 OS 쉘조차 없는 gcr.io/distroless/base-nossl-debian12:nonroot 이미지를 사용하여 보안성을 극대화하고 이미지 크기를 최소화했습니다.

# Dockerfile.hono (요약)
FROM oven/bun:1.3 AS builder
# ...
RUN bun build --compile \
  --minify \
  ./src/backend/index.ts \
  --outfile backend

FROM gcr.io/distroless/base-nossl-debian12:nonroot
COPY --from=builder /app/backend ./
ENTRYPOINT [ "./backend" ]

3. Google Cloud Build CI/CD

배포 자동화는 Google Cloud Build를 사용합니다. cloudbuild.prod.nextjs.yaml 설정 파일을 통해 빌드부터 배포까지의 과정을 정의했습니다.

주요 단계는 다음과 같습니다:
1. Build: Docker 이미지를 빌드합니다. 이때 Next.js 빌드에 필요한 환경변수(Sentry 키, API URL 등)를 --build-arg로 주입합니다.
2. Push: 빌드된 이미지를 Google Artifact Registry(GAR)에 푸시합니다.
3. Deploy: gcloud run services update 명령어로 Cloud Run에 새 버전을 배포합니다.

# cloudbuild.prod.nextjs.yaml (일부)
steps:
  - name: gcr.io/cloud-builders/docker
    args:
      - build
      - '--no-cache'
      - '-t'
      - '$_AR_HOSTNAME/...:$COMMIT_SHA'
      - .
      - '-f'
      - Dockerfile.nextjs
      # ... build-args ...
  - name: gcr.io/cloud-builders/docker
    args: ['push', '...']
  - name: gcr.io/google.com/cloudsdktool/cloud-sdk:slim
    args:
      - run
      - services
      - update
      - $_SERVICE_NAME
      - '--platform=managed'
      - '--region=$_DEPLOY_REGION'

이 구성 덕분에 main 브랜치에 코드가 병합되면 자동으로 프로덕션 환경에 배포가 이루어집니다.

4. Terraform으로 Cloudflare 관리

CDN, DNS, 캐싱 규칙 등 엣지(Edge)단의 설정은 Terraform을 사용하여 코드로 관리(IaC)하고 있습니다.

캐싱 전략

cloudflare/terraform/cache-rules.tf에서 서비스의 특성에 맞는 정교한 캐싱 규칙을 정의했습니다.

  • Respect Origin: /api/ 경로는 오리진 서버의 Cache-Control 헤더를 따릅니다.
  • Long-term Cache (30일): 변경이 적은 정적 자산(이미지, 폰트), /library, /doc 등의 경로는 엣지에서 30일간 캐싱하여 속도를 높입니다.
  • Short-term Cache (10초~3시간): 실시간성이 중요한 /ranking/(1일), /new/(3시간), /random(10초) 등은 짧은 TTL을 적용합니다.
  • Bypass Cache: 인증이 필요한 경로나 /.well-known/ 등은 캐시를 우회합니다.
# cache-rules.tf (예시)
resource "cloudflare_ruleset" "cache_rules" {
  # ...
  rules = [
    {
      description = "Cache with 30 days TTL"
      expression  = local.ttl_30d_expression
      action      = "set_cache_settings"
      action_parameters = {
        edge_ttl = { mode = "override_origin", default = 2592000 } # 30일
      }
    },
    # ...
  ]
}

이렇게 Terraform으로 규칙을 관리하면, 복잡한 캐싱 로직을 실수 없이 버전 관리하며 배포할 수 있습니다. 그리고 아래와 같이 원본 서버인 Cloud Run으로 가는 트래픽의 90%를 캐싱해 Cloud Run 서버 비용을 최대 10배까지 절약할 수 있습니다.

5. 마치며

이번 글에서는 Next.js와 Hono, Bun, 그리고 Google Cloud와
Cloudflare를 엮어 구축한 배포 시스템을 살펴보았습니다.

  • Bun 도입으로 Docker 빌드 시간과 런타임 성능을 개선했습니다.
  • Hono와 Single Binary 배포로 백엔드 컨테이너를 경량화했습니다.
  • Cloud Run Serverless 환경으로 인프라 관리 부담을 줄였습니다.
  • Terraform으로 Cloudflare의 복잡한 엣지 설정을 코드로 안전하게 관리합니다.

이 아키텍처는 초기 설정에 공수가 들지만, 한 번 구축하면 개발자는 비즈니스 로직에만 집중할 수 있는 안정적이고 빠른 배포 환경을 제공해 줍니다.

profile
이유와 방법을 알려주는 메모장 겸 블로그 (Frontend, AI, 경제, 책)

0개의 댓글