이 글은 “AI가 알아서 고품질 글을 발행한다”는 홍보 문구가 아니라, 이 블로그 저장소에 들어 있는 자동화 구성을 2026년 7월 23일 기준으로 확인한 기록이다. 자동 생성과 자동 배포는 가능하지만, 사실 검증과 공개 판단까지 자동화할 수 있다는 뜻은 아니다.
저장소에서 확인한 구성
| 단계 | 실제 파일 | 확인한 동작 |
|---|---|---|
| 예약 실행 | .github/workflows/auto_post.yml | 6시간 간격의 cron과 수동 실행을 제공한다. |
| 글 생성·검사 | scripts/auto_post.py | Gemini 호출, YAML 파싱, 필수 필드·본문 길이 검사, 중복 주제 검사, AI 재검수를 수행한다. |
| 검수용 보관 | .github/workflows/auto_post.yml | 예약 실행은 AUTO_POST_DRAFT를 true로 넘겨 초안으로 저장한다. |
| 보조 동기화 | scripts/git_to_notion.py | 생성된 글을 Notion으로 동기화한다. |
| 사이트 빌드 | package.json, quartz/bootstrap-cli.mjs | Node.js 22 이상에서 Quartz 정적 사이트를 생성한다. |
| CI | .github/workflows/ci.yaml | 형식·타입 검사, 테스트, 콘텐츠 빌드를 순서대로 실행한다. |
현재 예약식은 다음 한 줄이다.
- cron: "17 */6 * * *"
GitHub Actions의 예약 실행은 UTC 기준이며 정확한 시각을 보장하는 실시간 스케줄러가 아니다. 실행 지연 가능성은 GitHub Actions의 schedule 이벤트 문서에서 확인할 수 있다.
생성 스크립트의 실제 안전장치
scripts/auto_post.py 상단의 값은 다음과 같다.
MAX_ATTEMPTS = 4
MIN_BODY_LENGTH = 1000
MIN_REVIEW_SCORE = 70
AUTO_POST_DRAFT = env_bool("AUTO_POST_DRAFT", default=True)
이 값으로 확인되는 사실은 네 가지다.
- 생성 또는 검수가 실패하면 최대 네 번 시도한다.
- 본문이 1,000자 미만이면 거부한다.
- 별도 Gemini 검수 응답이 70점 미만이면 거부한다.
- 환경 변수가 없으면 공개가 아니라 초안이 기본값이다.
또한 스크립트는 title, tags, description을 파싱하고 기존 파일명·제목과 새 주제를 비교한다. “상위 노출 보장”, “고수익” 같은 운영자용 표현도 별도 금칙어 목록으로 검사한다.
다만 같은 계열의 모델이 초안을 만들고 다시 평가하는 구조이므로, 이 검수 결과를 사람의 사실 확인과 동일하게 취급하면 안 된다. AI 점수는 문장 구조의 이상을 찾는 보조 신호일 뿐이다.
발행 흐름을 재현하는 명령
저장소 루트에서 아래 순서로 정적 검사를 재현할 수 있다. 이 프로젝트의 package.json은 Node.js 22 이상과 npm 10.9.2 이상을 요구한다.
node --version
npm --version
node scripts/analyzePosts.cjs
npm run check:types
npm test
node ./quartz/bootstrap-cli.mjs build
Windows에서 시스템 Node가 오래됐다면 저장소에 포함된 로컬 Node 실행 파일을 명시할 수 있다.
.\.tools\node-v22.16.0-win-x64\node.exe .\quartz\bootstrap-cli.mjs build
analyzePosts.cjs는 frontmatter, description, tags, 로컬 이미지 경로를 확인한다. CI는 이보다 넓게 TypeScript 타입, 테스트, 전체 빌드를 확인한다. 둘 중 하나만 통과했다고 콘텐츠가 정확하다고 결론 내릴 수는 없다.
현재 구현과 공개 전 필요한 추가 검수
| 항목 | 현재 자동 검사 | 공개 전 추가 확인 |
|---|---|---|
| YAML 형식 | 있음 | 날짜·제목이 실제 내용과 맞는지 확인 |
| 본문 길이 | 1,000자 하한 | 길이가 아니라 고유한 근거가 있는지 확인 |
| 중복 주제 | 제목·키워드 기반 | 검색 의도와 결론이 실질적으로 중복되는지 확인 |
| 과장 표현 | 일부 금칙어 | 모든 수치·비교·최상급 표현의 근거 확인 |
| 출처 | 강제하지 않음 | 공식 문서 또는 원자료 링크 확인 |
| 이미지 | 로컬 경로 존재 여부 | 직접 만든 화면인지, 설명과 일치하는지 확인 |
| 고위험 주제 | 별도 사람이 판단해야 함 | 건강·금융·법률·세금 글은 원칙적으로 비공개 유지 |
자동화가 공개 버튼을 대신하지 않도록 “초안 생성 → 사람 검수 → CI 통과 → 공개”를 분리하는 편이 안전하다. 워크플로의 concurrency 설정은 같은 그룹의 중복 실행을 제한한다. 동작 원리는 GitHub Actions concurrency 공식 문서에서 확인할 수 있다.
비용과 서비스 한도
이 구성은 별도 가상 서버를 운영하지 않지만 “영구 0원”을 보장하지 않는다. API 사용량, GitHub 요금제, Cloudflare 요금제와 한도는 바뀔 수 있다.
- Google은 Python용 공식 라이브러리로 google-genai를 안내한다. 최신 설치법은 Gemini API 라이브러리 문서에서 확인한다.
- Cloudflare Pages 무료 플랜은 현재 월 빌드 수와 파일 수 등에 한도가 있다. 고정 숫자를 기억하기보다 Cloudflare Pages 한도 문서를 배포 전에 확인해야 한다.
- GitHub Actions 사용량과 동시성은 저장소 공개 여부와 계정 요금제에 따라 달라질 수 있다.
한계
- 이 글은 저장소 파일을 읽어 확인한 구조 설명이며, Gemini 응답 품질이나 Cloudflare 배포 시간을 벤치마크한 결과가 아니다.
- API 키가 필요한 실제 생성 작업은 재실행하지 않았다. 따라서 성공률이나 모델별 품질 수치를 제시하지 않는다.
- Notion 동기화는 별도 사본을 만드는 데 도움을 주지만, 복구 절차를 시험한 백업이라는 뜻은 아니다.
- 자동화된 AI 검수는 출처 확인, 저작권 판단, 전문가 검토를 대체하지 못한다.
- 이 글에는 검증 가능한 실행 화면이 없어 스크린샷을 넣지 않았다. 화면을 추가한다면 실행 시각, 커밋, 명령과 함께 다시 캡처해야 한다.
자동화의 가치는 발행량이 아니라 반복 가능한 검수 절차에 있다. 이 저장소에서 가장 중요한 기본값도 공개가 아니라 draft: true다.