BLUEGYU

3편: GitHub Actions로 블로그 자동 배포 파이프라인 구축하기

2025-08-24

왜 Github Actions를 사용했을까?

GitHub Actions는 CI/CD 파이프라인을 구축할 수 있는 툴입니다. 비슷한 툴로는 Jenkins, GitLab CI 등이 있지만, GitHub Actions는 GitHub 저장소와 밀접하게 통합되어 있어 별도의 환경 세팅 없이 빠르게 사용할 수 있다는 장점이 있습니다. 특히 특정 이벤트 발생 시 레포지토리에 정의된 워크플로우가 자동으로 실행되도록 설정할 수 있어, 작은 프로젝트에도 부담 없이 적용할 수 있습니다.

이번 블로그 구축 프로젝트에서는 CI보다는 CD(Continuous Delivery)에 초점을 맞췄습니다. 콘텐츠 변경이나 태그 생성 같은 이벤트를 감지해 썸네일을 자동 생성하고, 블로그를 빌드 및 배포하며, PR 관리를 자동화하는 흐름을 만들었습니다. 이를 통해 반복적인 수작업을 줄이고 배포 안정성을 높이는 것이 주요 목표였습니다.

GitHub Actions 워크플로우 구성

GitHub Actions 워크플로우는 이벤트 기반(트리거)으로 실행되며, 기본 동작 흐름은 다음과 같습니다.

이벤트 발생 → 소스 체크아웃 → Node.js 설치 → 의존성 설치 → 동작 실행 → 결과 확인

아래는 이번 프로젝트에서 구축한 주요 워크플로우들입니다.

1. 썸네일 자동 생성

마크다운 파일이 추가되거나 수정되면 satoriresvg-js를 활용해 제목 기반 썸네일 이미지를 생성하도록 했습니다. 이렇게 하면 콘텐츠 작성자가 직접 이미지를 준비할 필요 없이, 블로그에 일관된 스타일의 썸네일이 자동으로 붙습니다.

# 썸네일 자동 생성 워크플로우
on:
  push:
    paths:
      - "posts/**/*.mdx"
      - "posts/**/*.md"

jobs:
  generate-thumbnails:
    runs-on: ubuntu-latest
    needs: validate-markdown
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        ...
      - name: Generate thumbnails
        if: steps.changed-files.outputs.changed_files != ''
        run: |
          node scripts/generate-thumbnail.mjs ${{ steps.changed-files.outputs.changed_files }}

      - name: Commit and push thumbnails
        if: steps.changed-files.outputs.changed_files != ''
        run: |
          git config --local user.email "bluegyufordev@gmail.com"
          git config --local user.name "blueGyu"
          git add .
          git commit -m "Auto-generate thumbnails for changed posts" || echo "No changes to commit"
          git push

2. 태그 기반 소스 빌드 및 배포

버전 태그(v1.0.0 같은 형태)가 생성되면 자동으로 블로그를 빌드하고 GitHub Pages에 배포되도록 했습니다. 태그 기반 배포를 선택한 이유는 명확한 배포 시점을 관리할 수 있기 때문입니다. 단순히 main 브랜치에 push되는 것과 달리, 의도하지 않은 배포를 방지할 수 있습니다.

# 태그 기반 배포 워크플로우
on:
  push:
    tags:
      - "v*" # v로 시작하는 태그 (예: v1.0.0, v2.1.3)

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        ...
      - name: Install dependencies
        run: npm ci

      - name: Build Gatsby site
        run: npm run clean && npm run build

      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.DEV_BLOG_DEPLOY }}
          publish_dir: ./public
          force_orphan: true

3. dispatch 이벤트를 이용한 소스 빌드

블로그 콘텐츠 저장소와 소스 저장소를 분리했기 때문에, 콘텐츠 변경만으로는 배포가 자동으로 이뤄지지 않습니다. 이를 해결하기 위해 repository_dispatch 이벤트를 활용했습니다. 콘텐츠 저장소에서 이벤트를 발행하면, 소스 저장소가 이를 받아 빌드 및 배포를 실행하도록 했습니다.

이 방식의 장점은 저장소 간 독립성을 유지하면서도 필요한 경우 즉시 배포를 트리거할 수 있다는 점입니다.

// GitHub API를 통한 dispatch 이벤트 전송
curl -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer ${{ secrets.PERSONAL_TOKEN }}" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/blueGyu/dev-blog/dispatches \
  -d '{"event_type": "build-triggered"}'
# 블로그 소스코드 레포지토리에서 이벤트 수신
on:
  repository_dispatch:
    types: [build-triggered]

jobs:
  build-source:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Build project
        run: npm ci && npm run build

4. PR 자동 생성

Pull Request가 생성되면 OpenAI API를 이용해 변경점을 요약하고 PR 제목과 본문을 자동으로 채워 넣도록 했습니다. 이를 통해 리뷰어가 맥락을 빠르게 이해할 수 있고, 단순 요약 작성에 드는 시간을 줄일 수 있었습니다.

# AI 기반 PR 자동 생성 워크플로우
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  generate-pr-content:
    runs-on: ubuntu-latest
    env:
      OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
    outputs:
      pr-title: ${{ steps.generate.outputs.pr-title }}
      pr-body: ${{ steps.generate.outputs.pr-body }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "22"

      - name: Install dependencies
        run: npm install @actions/core openai tiktoken

      - name: Generate PR content
        id: generate
        run: |
          node scripts/generate-pr-content.mjs origin/${{ github.event.pull_request.base.ref }} origin/${{ github.event.pull_request.head.ref }} ${{ github.event.pull_request.number }}

  update-pr-content:
    runs-on: ubuntu-latest
    needs: generate-pr-content
    permissions:
      pull-requests: write
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Update PR description
        uses: actions/github-script@v7
        env:
          PR_TITLE: ${{ needs.generate-pr-content.outputs.pr-title }}
          PR_BODY: ${{ needs.generate-pr-content.outputs.pr-body }}
        with:
          script: |
            await github.rest.pulls.update({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.issue.number,
              title: process.env.PR_TITLE,
              body: process.env.PR_BODY
            });

정리하며

이번 프로젝트에서는 GitHub Actions를 활용해 블로그에 필요한 CD(Continuous Delivery) 파이프라인을 구축했습니다. 콘텐츠 변경 시 썸네일을 자동 생성하고, 태그와 dispatch 이벤트 기반으로 빌드와 배포를 자동화했으며, PR 자동 생성 기능을 통해 협업 효율성을 높일 수 있었습니다.

특히 배포 자동화에 집중함으로써 반복 작업 및 실수를 줄여 블로그 운영의 안정성과 생산성을 높일 수 있다는 것을 확인했습니다. 이번 경험은 GitHub Actions을 CD로서 사용하는 것만으로도 실용적인 운영 환경을 마련할 수 있음을 보여주었습니다.

이번 프로젝트로 자동화는 작은 프로젝트에서도 가치를 발휘하며, GitHub Actions는 간단한 방법으로 빠르게 실현할 수 있는 툴이라는 것입니다. 앞으로는 워크플로우 이벤트 발생 조건을 더 세밀히 조정하여 불필요한 실행을 줄이고, CI까지 시도해 볼 계획입니다.

참고

이번 글에서 다룬 워크플로우는 아래 링크에서 확인할 수 있습니다.

이전 포스트

1편: Gatsby 블로그 프로젝트 구조 설계로 시작하기

Built withGatsby

© 2025 blueGyu. All rights reserved.