손으로 올리던 글을 자동 발행으로

2026.09 ~ 2026.09 (운영 중)

포트폴리오 정본 변경 반영과 블로그 발행을 무인으로 돌리는 파이프라인입니다.

과제

  • 정본을 고칠 때마다 사이트 반영·색인을 손으로 돌리고 블로그는 수동 발행
  • 다른 자동화가 6일간 죽어 있어도 발견되지 않은 전례

담당 범위

  • 게이트·발행 CLI·주기 스케줄러: Python 표준 라이브러리 (설계·구현·운영 전담)
  • launchd 에이전트 2종, 알림 폴백과 워치독 감시

설계 판단

  • AI는 원고 파일만 작성하고 발행은 검증된 경로가 수행 → 게이트 우회 차단
  • 주기 판정을 launchd 대신 코드에서 수행 → 무작위 주기 표현, 매일 기동으로 감시
  • 알림 실패를 작업 실패로 처리하지 않음 → 저장된 초안이 누락되는 상황 방지

결과 지표

  • 테스트 184건 통과
  • 외부 의존성 0개 (표준 라이브러리만)
  • 게이트 검사 6종, 무인 실행 11단계
원문 자세히 보기

과제

정본(JSON)을 고칠 때마다 사이트 반영·색인·이력서 PDF 를 손으로 돌려야 했고, 블로그 글은 아예 수동이었다. 무인화하면 실패했을 때 아무도 모른다는 문제가 따라온다 — 실제로 다른 자동화가 6일간 죽어 있었는데 발견되지 않은 적이 있다. 자동화 자체보다 '조용한 실패'를 어떻게 드러낼지가 핵심 과제였다.

담당 범위

Python 3.9 표준 라이브러리만(외부 의존성 0) · lib 2,879줄 · 테스트 193건 · 게이트 6종 · launchd 에이전트 2종 · 무인 실행 11단계

설계·구현·운영 전부

보기

선택안 · 대안 · 근거 · 비용

글쓰기는 AI 에게 맡기되 발행 권한은 주지 않는다

대안AI 에게 발행 명령까지 위임근거AI 가 발행 CLI 를 직접 부르면 게이트를 우회하거나 인자를 잘못 줄 여지가 생긴다. 원고 파일 하나만 쓰게 하고, 검사와 발행은 검증된 경로가 한다.비용셸이 AI 를 호출하는 계층이 하나 늘었다. 대신 게이트를 통과하지 않은 글은 구조적으로 나갈 수 없다.

주기 판정을 launchd 가 아니라 코드가 한다

대안StartCalendarInterval 로 주기 고정근거18~24일 랜덤은 launchd 로 표현할 수 없다. 그리고 매일 깨우는 편이 감시에 유리하다 — 3주에 한 번 도는 잡은 죽어도 3주 뒤에나 드러난다.비용대부분의 실행이 '아직 아니다'로 끝나 로그에 빈 실행이 쌓인다. 워치독이 '이틀 안 돌면 경보'로 감시할 수 있는 이득이 더 크다고 봤다.

알림 실패가 작업 실패가 되지 않게 한다

대안알림 실패 시 예외를 올려 종료코드를 오염근거초안이 저장된 뒤에는 되돌릴 수 없다(발행용 키에 삭제 권한이 없다). 알림 실패로 작업을 실패 처리하면 글은 서버에 남았는데 재실행은 중복 게이트에 막혀, 사람이 그 초안의 존재를 영영 모른다.비용알림이 안 갔는데 종료코드가 0 이라 로그를 봐야 안다. 대신 폴백 경로를 둬서 알림이 통째로 사라지지는 않게 했다.

사용 기술

PythonpytestlaunchdDockerPostgreSQLCloudflare R2