최근에 블로그 글 작성을 AI로 자동화하면 어떨까 싶어서 며칠정도 작업했던 내용을 공유드립니다. GitHub Issue에 원하는 블로그 글 제목과 간단한 내용만 작성하면, AI가 해당 이슈를 기반으로 글을 자동으로 작성하고, 번역하고, PR을 올리고, 최종적으로 GitHub Pages로 배포까지 하는 파이프라인입니다.
전체적인 코딩은 직접 할 수도 있었지만 그렇게 열심히 하고 싶지는 않아서 ㅎㅎ.. 클로드 코드한테 전부 위임했고, 중간중간 오류나는 부분들만 살펴보면서 수정해줬습니다. 퇴근하고 남는 자투리시간에 약 2시간씩 작업했고, 전체 블로그를 완성하는데는 3일 정도 걸렸던 것 같습니다.
Workflow Overview
파이프라인의 전체 흐름은 다음과 같습니다.
- GitHub Issue 생성: 유저가 깃헙 저장소에 이슈를 등록하고, 특정 라벨(
content-request
)을 붙입니다. - AI 콘텐츠 생성: 해당 이슈를 Github Action이 감지하고 파이썬 코드를 실행시킵니다. 파이썬 코드에는 OpenAI API를 활용해 한국어 블로그 글을 자동 생성하는 로직이 담겨있습니다.
- AI 번역: 생성된 한국어 블로그 글을 영어로 번역합니다.
- PR 자동 생성: AI가 생성해낸 2개의 마크다운 파일을 Github Action을 통해 PR을 올립니다.
- 리뷰 및 머지: 결과물을 검토하고, Approve하고, Merge 합니다.
- 자동 배포: Merge가 완료되면 Github Action을 통해 블로그가 빌드되고 GitHub Pages로 자동 배포됩니다.
Example Results
아래처럼 이슈를 작성하면
AI 한국어 & 영어로 블로그 글을 생성하여 PR을 올리고
PR을 merge하면 블로그에 자동으로 배포됩니다!
- https://yuhodots.github.io/invest-notes/kor/25-09-10-1757496027/
- https://yuhodots.github.io/invest-notes/eng/25-09-10-1757496027/
출퇴근 길에 개인적으로 궁금한 내용에 대해서 핸드폰 깃헙 앱으로 이슈를 등록해놓으면 글이 알아서 작성되고, PR이 올라오면 바로 깃헙 앱으로 알림이 오니 확인하기도 편했습니다.
물론 아직 글에서 AI 티가 많이 나고 사실상 ChatGPT 내용을 블로그 포스팅하는 것과 다를 바 없긴 하지만, 어딘가에 내가 궁금한 내용들만 기록해서 업로드 해놓으니 좀 더 자주 보게 되는 것 같고, 나중에는 블로그에 구글 애드센스를 붙여봐도 좋겠다는 생각입니다.
Pipeline
전체 코드는 https://github.com/yuhodots/invest-notes 저장소에서 확인 가능합니다.
블로그/
├── .github/
│ └── workflows/
│ ├── auto-content-generator.yml # 콘텐츠 생성 워크플로우 (한국어 & 영어 번역)
│ └── deploy-blog.yml # 블로그 배포 워크플로우
└── ai_workflows/
├── writer.py # AI 작가 모듈
├── translator.py # AI 번역가 모듈
└── prompts/ # 프롬프트 템플릿
Step 1: GitHub Issue 트리거 설정
글 생성에 사용되는 action 파일은 .github/workflows/auto-content-generator.yml
입니다.
[opened, labeled]
: 이슈가 새로 열리거나 라벨이 추가될 때 트리거됩니다.content-request
라벨이 있고, 특정 사용자(yuhodots
)가 올린 이슈만 처리합니다. 이 처리를 따로 해주지 않으면 다른 사람이 올린 이슈에 대해서도 블로그 글이 생성되어서 OpenAI 크레딧이 소진될 수 있기 때문에 설정을 추가해줬습니다.
name: Auto Content Generator
on:
issues:
types: [opened, labeled]
jobs:
generate-content:
if: |
contains(github.event.issue.labels.*.name, 'content-request') &&
(github.event.issue.user.login == 'yuhodots')
runs-on: ubuntu-latest
Step 2: AI 콘텐츠 생성
uv 기반으로 의존성을 설치합니다.
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: "latest"
- name: Install dependencies
run: uv sync --locked
이슈 제목과 이슈의 내용에 대해서 읽어들입니다. 클로드코드에게 코드 구현해달라고 했더니 아래처럼 작성해줬습니다.
EOF
구분자를 사용해 여러 줄의 이슈 본문을 처리 가능합니다.- 추출한 정보들을 GITHUB_ENV에 저장해둡니다 (다음 task들에서 활용)
- name: Extract issue information
id: issue-info
run: |
echo "ISSUE_TITLE=${{ github.event.issue.title }}" >> $GITHUB_ENV
echo "ISSUE_NUMBER=${{ github.event.issue.number }}" >> $GITHUB_ENV
# Multi-line variable for body
echo "ISSUE_BODY<<EOF" >> $GITHUB_ENV
echo "${{ github.event.issue.body }}" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
# Create slug from issue title
SLUG=$(echo "${{ github.event.issue.title }}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9가-힣]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')
echo "SLUG=$SLUG" >> $GITHUB_ENV
아래 코드는 좀 길어서 중간중간 생략했는데, 위에서 추출한 정보들을 활용해서 ai_workflows/writer.py
파일이 실질적으로 글을 생성하고, ai_workflows/translator.py
파일이 생성된 글에 대한 영어 번역을 수행하는 것이 핵심입니다.
- GENERATEDFILE(KOREANFILE)라는 경로에 한국어 파일이 저장되고, ENGLISHFILE라는 경로에 영어로 번역된 파일이 저장됩니다. 자세한 코드 내용은 [코드 파일](https://github.com/yuhodots/invest-notes/tree/develop/aiworkflows) 직접 참고하시면 좋습니다.
- OpenAI API Key는 Github secret에 미리 등록해둬야 합니다.
- name: Generate Korean content
id: generate-korean
run: |
... 내용 생략
# Run writer.py and capture the last line (file path)
GENERATED_FILE=$(uv run python ai_workflows/writer.py \
--title "${{ env.ISSUE_TITLE }}" \
--body "${{ env.ISSUE_BODY }}" | tail -1)
... 내용 생략
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Generate English content
run: |
... 내용 생략
# Run translator from root directory
uv run python ai_workflows/translator.py \
--input "$KOREAN_FILE" \
--output "$ENGLISH_FILE"
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
Step 3: Pull Request 자동 생성
AI가 만들어낸 2개의 마크다운 파일을 PR로 올립니다. 이 때, 저장소 내에서 아래 두 가지 설정이 필요합니다.
- Settings/Actions/General - Read and write permissions
- Settings/Actions/General - Allow GitHub Actions to create and approve pull requests
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }}
commit-message: |
feat: auto-generated content for issue #${{ env.ISSUE_NUMBER }}
- Generated Korean content: ${{ env.DATE }}-${{ env.SLUG }}.md
- Generated English content: ${{ env.DATE }}-${{ env.SLUG }}.md
Closes #${{ env.ISSUE_NUMBER }}
title: "Auto-generated content: ${{ env.ISSUE_TITLE }}"
branch: auto-content/${{ env.ISSUE_NUMBER }}-${{ env.SLUG }}
labels: |
auto-generated
content
reviewers: |
${{ github.event.issue.user.login }}
Step 4: 배포 워크플로우
제 블로그는 gatsby 기반으로 만들어져 있고, package.json
파일을 확인해보시면 알 수 있는 것 처럼 yarn deploy
명령어를 통해 github pages로 배포가 가능합니다.
그래서 블로그 배포를 위한 action인 deploy-blog.yml
에도 딱히 별 다른 작업은 없고, develop branch에 코드 변경사항이 push되면 yarn deploy
를 수행하라는 명세 정도가 적혀있습니다.
name: Deploy Blog
on:
push:
branches:
- develop
paths:
- 'contents/**'
- 'src/**'
- 'package.json'
- 'yarn.lock'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Deploy blog
run: yarn deploy
Conclusion
AI가 제 의도에 맞게 블로그 글을 작성하되, 그 결과물을 바로 배포하지 않고 한 번 검토해서 수정이나 보완한 뒤 승인된 내용만 업로드하는 방식을 선호했는데, 이러한 요구조건에 알맞은 플로우라서 좋은 것 같습니다. 사용자의 의도도 잘 반영하고, 품질 관리나 human feedback도 줄 수 있다는 점에서 나름 괜찮은 형태라고 생각합니다. 물론 지금 만들어진 초안에 대해 제가 직접 PR 내용을 수정해야 하는 번거로움은 있지만, 나중에는 PR에 대한 피드백을 바탕으로 AI가 PR을 다시 수정하도록 만드는 기능도 추가해볼 수 있을 것 같습니다.
실제 사용해보면서 느낀 가장 큰 장점은, 핸드폰만으로 간편하게 깃헙 블로그 글을 작성하고, 원하는 부분만 수정하고, 배포까지 된다는게 꽤 편리했습니다. 프롬프트는 아직 더 잘 다듬어야 할 것 같긴 하지만, 비슷한 파이프라인을 고민하시는 분들은 한번 참고해서 AI 블로그 자동화 시도해보셔도 좋을 것 같습니다 :)