sy/dev
Tutorial
8 min read

블로그 만들기 4편 — 배포 자동화 (빌드 캐시 · PR 프리뷰)

3편까지 글 쓰고 발행하는 콘텐츠 파트는 끝냈다. 이제 배포 인프라다 — GitHub Actions로 빌드 캐시를 활용해 배포 속도를 10배 줄이고, PR마다 자동 프리뷰 URL을 만들자.

이어서 — 이번엔 배포 자동화

1~3편에서 댓글 · 검색 노출 · SEO 마감까지 했다. 콘텐츠 파트는 이제 완성이다. 하지만 블로그가 운영되려면 배포 인프라가 필요하다 — 매일 새 글을 밀어내는 CI/CD 파이프라인.

이 편에서는 GitHub Pages(GitHub Actions 기반)를 기준으로 한다. Vercel을 쓰면 이 단계는 자동화되어 있으니 건너뛰어도 좋다.

지금 상황:

  • 커밋하면 CI 파이프라인이 무조건 전체 빌드를 처음부터 시작 → 5~10분 대기
  • PR에 올려도 배포 미리보기(preview)가 없어 리뷰가 답답함
  • 메인 브랜치에 merge되기 전까진 실제 결과를 모름

3가지 다 GitHub Actions 몇 줄로 해결한다:

  1. 빌드 캐시 — Node 모듈 + Next.js 캐시 → 빌드 2~3분으로 단축
  2. PR 프리뷰 — 각 PR마다 자동으로 배포 URL 생성
  3. 배포 최적화 — main 브랜치만 공식 배포, PR은 임시 배포

빌드 캐시 — Node 모듈과 .next 캐싱하기

GitHub Actions의 actions/cache 액션을 쓰면 CI 러너 간 파일을 재사용할 수 있다. 목표는:

  • node_modules/ 캐시 → npm ci 스킵 (또는 5초 안에 끝남)
  • .next/cache 캐시 → next build 재계산 스킵
.github/workflows/build-and-deploy.yml (캐시 파트만)
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      # 캐시 키 전략: npm 의존성이 바뀌면 캐시 무효화
      - uses: actions/cache@v4
        with:
          path: |
            ~/.npm
            node_modules
            .next/cache
          key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-
      
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      
      - run: npm ci  # npm install 대신 ci (lockfile 기반 설치)
      - run: npm run build

핵심:

  • keypackage-lock.json 해시를 포함. 의존성이 바뀌면 자동으로 새 캐시 생성
  • restore-keys — lockfile 변화가 없으면 이전 캐시 쓰기
  • .next/cache — Next.js 자체 캐시도 포함. 이미지 최적화 + JS 번들링 결과 재사용

효과:

  • 첫 실행: ~5분 (캐시 없음)
  • 2~10번째: ~30초 (캐시 히트)
  • package-lock.json 변경: ~2분 (부분 캐시)

PR 프리뷰 배포 — Netlify 또는 Vercel 연동

GitHub Pages는 기본적으로 main 브랜치만 배포한다. PR마다 프리뷰를 만들려면 Netlify 또는 Vercel 같은 서비스를 써야 한다.

옵션 1: Netlify (무료, GitHub Pages 병행 가능)

Netlify는 각 PR마다 자동으로 배포 URL을 생성한다. GitHub 마켓플레이스에서 Netlify 앱을 설치하면 끝.

.github/workflows/netlify-preview.yml (선택사항)
name: Netlify Preview
on:
  pull_request:
    types: [opened, synchronize]
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npm run build
      
      # Netlify CLI로 배포
      - run: |
          npx netlify-cli deploy \
            --prod \
            --message "PR #${{ github.event.number }}" \
            --dir=out
        env:
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

이렇게 하면 PR이 열릴 때마다 배포되고, 댓글로 프리뷰 URL이 자동 등록된다.

옵션 2: Vercel (Nextjs 최적화)

Next.js를 쓴다면 Vercel을 쓰는 게 가장 간단하다. GitHub와 연동한 뒤 저장소 설정만 하면 자동으로:

  • main → 공식 배포 (production)
  • feature 브랜치 → 프리뷰 배포 (preview)
  • PR → 자동 배포 후 댓글로 URL 등록

Vercel 대시보드 설정 하나면 되므로 workflow YAML을 따로 짤 필요가 없다.

main 브랜치 배포 최적화 — GitHub Pages 자동 푸시

GitHub Pages에 배포할 때는 gh-pages 브랜치나 docs/ 폴더를 쓴다. 일반적인 구조:

.github/workflows/deploy.yml (main 브랜치 전용)
name: Deploy to GitHub Pages
on:
  push:
    branches: [main]
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.npm
            node_modules
            .next/cache
          key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-
      
      - run: npm ci
      - run: npm run build
      - run: npm run export  # static HTML 생성 (Next.js)
      
      # gh-pages 브랜치에 푸시
      - uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./out
          cname: your-blog.com  # 커스텀 도메인 있으면

흐름:

  1. main에 커밋 푸시
  2. Actions 워크플로 트리거
  3. 캐시에서 빌드 + 테스트
  4. npm run export로 정적 HTML 생성
  5. gh-pages 브랜치에 자동 푸시
  6. GitHub Pages가 gh-pages에서 배포

통합 워크플로 예제 — 캐시 + PR 프리뷰 + main 배포

.github/workflows/ci-cd.yml (통합 예제)
name: Build and Deploy
 
on:
  push:
    branches: [main]
  pull_request:
    types: [opened, synchronize]
 
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      
      # 캐시 — 핵심!
      - uses: actions/cache@v4
        with:
          path: |
            ~/.npm
            node_modules
            .next/cache
          key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
          restore-keys: ${{ runner.os }}-build-
      
      - run: npm ci
      - run: npm run build
      - run: npm run lint  # 선택사항
      - run: npm run test  # 선택사항
      
      # main 브랜치면 GitHub Pages에 배포
      - if: github.ref == 'refs/heads/main'
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./out
      
      # PR이면 임시 배포 (Netlify 예제)
      - if: github.event_name == 'pull_request'
        run: |
          npx netlify-cli deploy \
            --message "PR #${{ github.event.number }}" \
            --dir=out
        env:
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

의존성 업데이트 자동화 (Dependabot)

매주 의존성을 최신으로 유지하려면 Dependabot을 켜자:

.github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      time: "03:00"
    allow:
      - dependency-type: "direct"
      - dependency-type: "indirect"
    reviewers:
      - "당신의-github-username"

이러면 매주 월요일 3시에 자동으로 PR을 열어 테스트하고, 모든 테스트가 통과하면 자동 merge까지 가능하게 할 수 있다.

배포 체크리스트

  • .github/workflows/ci-cd.yml 파일 추가
  • actions/cache 설정 — package-lock.json 기반 키 설정
  • npm ci 사용 (npm install 대신)
  • PR 프리뷰 설정 (Netlify 또는 Vercel)
  • main 배포 자동화 설정
  • Dependabot 활성화 (선택사항)
  • npm run build가 로컬에서 성공하는지 확인

다음 편 예고

블로그 만들기 시리즈는 여기까지다 — 댓글 · 검색 · SEO · 배포 자동화 전부 챙겼다. 다음은 글쓰기 워크플로가 있을 수 있다:

  • /new-post — 새 글 초안 자동 생성 (frontmatter + 템플릿)
  • /review-post — 발행 전 체크리스트 (frontmatter 검증, 빌드 테스트)
  • 이미지 파이프라인 — Unsplash/Pexels 자동 다운로드

하지만 그건 선택사항이다. 지금도 충분히 돌아간다.

참고

Comments