lifecarelog
개발일지

블로그 자동 발행을 launchd로 무인화한 기록 — 게이트·빌드·푸시를 하나로

자체 블로그는 git push만으로 Cloudflare Pages에 배포돼요. 그 점을 이용해 거짓정보 게이트 → 빌드 → 커밋 → 푸시를 매일 자동으로 돌리는 발행 파이프라인을 launchd로 묶은 과정을 정리했어요.

4분 읽기

이 블로그는 글 파일을 저장소에 커밋하고 푸시하면 Cloudflare Pages가 받아서 빌드·배포해요. 그래서 "발행"이라는 동작이 사실상 git push 한 번이에요. 이 점을 이용해 매일 글을 자동으로 올리는 파이프라인을 만들었어요.

파이프라인 단계

발행을 네 단계로 나눴어요.

  1. 거짓정보 게이트 — 초안에 사실이 아닌 내용이 있는지 점검해요. 통과한 글만 다음 단계로 가요.
  2. 빌드pnpm build로 정적 페이지를 생성해요. 여기서 frontmatter 검증이나 타입 오류가 있으면 멈춰요.
  3. 커밋 — 통과·빌드된 글만 저장소에 커밋해요.
  4. 푸시git push로 Cloudflare Pages 배포를 트리거해요.

fail-closed 원칙

핵심은 "막히면 발행하지 않는다"예요. 게이트에서 사실 검증을 통과하지 못한 글은 사이트로 나가지 않고 quarantine/ 폴더로 따로 빼둬요. 삭제가 아니라 격리라서, 나중에 사람이 직접 보고 판단할 수 있어요.

# 게이트 실패 시: 발행 중단 + 격리 (배포 트리거 없음)
if ! blog-fact-gate.sh "$draft"; then
  mv "$draft" "$QUARANTINE_DIR/"
  exit 1   # push 단계까지 가지 않음
fi

"실수로 잘못된 글이 공개되는 것"보다 "발행이 한 번 안 되는 것"이 회복하기 쉬우니까요.

왜 launchd인가

제 작업 환경이 macOS라서, 정해진 시각에 스크립트를 돌리는 일은 launchd로 맡겼어요. StartCalendarInterval에 시각을 넣으면 그 시간에 발행 스크립트를 실행해요. 노트북이 꺼져 있던 시간대의 작업은 다음에 깨어났을 때 실행되도록 동작해요.

<key>StartCalendarInterval</key>
<dict>
  <key>Hour</key><integer>9</integer>
  <key>Minute</key><integer>0</integer>
</dict>

발행 후 확인

스크립트가 끝났다고 글이 실제로 보이는 건 아니에요. 배포에는 시간이 걸리고, 빌드가 성공했는데도 페이지가 비어 있을 수 있어요. 그래서 마지막에 실제 글 주소가 200으로 응답하는지, 본문이 렌더되는지까지 확인하는 단계를 넣었어요. 작업 상태가 "성공"이라고 떠도 실제 화면을 한 번 더 보는 게 안전하더라고요.

다음 글에서는 이 게이트가 거짓정보를 어떻게 거르는지 더 자세히 다뤄볼게요.

#devlog#automation#launchd#cloudflare-pages#ci

라이프케어로그 서비스가 궁금하신가요?

AI 기반 건강·일정·재활 관리 앱을 직접 써보세요.

서비스 살펴보기

관련 글