자동화가 멈췄는데, 사이트는 배포됐다

GitHub Actions 작업이 코드 한 줄 실행하기도 전에 멈췄다. 실패한 테스트도, 잘못된 YAML도 아니었다. 화면에는 최근 계정 결제가 실패했거나 지출 한도를 올려야 한다는 안내가 붙어 있었다. 그런데 그날 iloura.co.kr에는 새 페이지가 올라갔다.

이 장면은 처음엔 이상하게 보인다. 자동 배포가 막혔는데 배포는 어떻게 됐을까? 답은 간단했다. 나는 배포와 부가 자동화를 하나의 문으로 묶지 않았고, 사이트는 GitHub Actions만 바라보고 있지 않았다. 이 경험 이후 자동화의 기준을 “모든 작업이 한 번에 성공하는가”에서 “한 경로가 멈춰도 핵심 결과가 살아남는가”로 바꿨다.

문제는 실패가 아니라, 실행조차 시작되지 않았다는 사실이었다

이번 장애에서 중요한 단서는 before steps였다. 워크플로가 실행된 뒤 특정 step에서 실패한 것이 아니다. Actions가 작업을 예약하고 준비하는 단계에서 차단됐기 때문에, 로그를 따라가며 애플리케이션 버그를 찾을 수도 없었다.

수동으로 deploy-only 워크플로를 호출해도 Cloudflare hook까지 도달하지 못했다. 이 상황에서 “한 번 더 재실행”은 해결책이 아니다. 코드가 틀린 게 아니라 실행 플랫폼의 계정 상태가 작업을 받지 않은 것이기 때문이다. 디버깅 대상을 코드에서 운영 조건으로 옮겨야 했다.

여기서 많은 자동화가 취약해진다. Notion 동기화, 이미지 처리, 빌드, 배포, 알림을 하나의 Actions 성공 여부에 연결해두면, 가장 바깥쪽의 결제나 계정 제한이 안쪽의 콘텐츠 배포까지 함께 멈춘다. 실제 원인은 작아도 영향 범위는 커진다.

내가 실제로 확인한 두 개의 경로

상호작용 기록에 기반한 확인이다. Actions가 막힌 뒤 나는 커밋 ed65560을 origin/main에 push했고, 저장소와 연결된 사이트 배포가 /iloura-fragrance/를 라이브에 반영했다. 이후 Aside로 실제 경로, 이미지, 선택 UI, 홈페이지 내비게이션을 확인했다.

경로담당 작업당시 결과
Git push → 연결된 배포커밋된 사이트 파일을 실제 서비스에 반영성공 — 새 페이지 라이브 확인
GitHub ActionsNotion sync, deploy-only 호출, Cloudflare hook차단 — step 전 계정 결제·지출 한도 안내

이 표에서 중요한 건 “Actions가 나빴다”가 아니다. 두 경로가 서로 다른 역할을 하고 있었기 때문에 한쪽의 장애가 다른 쪽의 성공까지 지우지 못했다는 점이다. 배포는 이미 존재하는 산출물을 전달하는 일이고, Notion sync나 이미지 처리 같은 자동화는 산출물을 만드는 일이다. 이 둘을 같은 실패 도메인에 넣을 이유가 없다.

자동화를 도입할 때 먼저 분리해야 하는 세 가지

이 경험에서 내가 가져간 설계 원칙은 거창한 새 도구가 아니다. 지금 쓰는 도구의 책임을 나누는 일이다.

  • 소스 생성: Notion에서 페이지를 읽고 Hugo 파일과 이미지를 만든다.
  • 검증: 생성된 파일, 링크, 이미지, 선택 UI가 기대한 상태인지 확인한다.
  • 전달: 검증된 커밋을 서비스에 배포한다.

이 세 단계가 한 workflow에 있더라도, 각각의 실패가 어디까지 영향을 주는지는 분리해야 한다. 특히 전달 단계는 이미 커밋된 결과를 서비스에 내보내는 마지막 안전망이어야 한다. 소스 생성기가 잠깐 고장 났다고 과거에 검증된 페이지까지 배포할 수 없어지는 구조는 회복성이 낮다.

실제로 적용할 수 있는 최소 워크플로

처음부터 멀티 리전, 별도 오케스트레이터, 복잡한 재시도 정책을 만들 필요는 없다. 아래 네 가지 질문만 먼저 문서와 설정에 박아두면 된다.

  1. Actions가 오늘 멈추면, 마지막으로 검증된 커밋을 배포할 수 있는가?
    배포 경로가 Actions 하나뿐이라면 답은 보통 “아니오”다. Git-connected deploy처럼 독립된 전달 경로를 준비한다.
  2. 실패가 step 전인지 step 후인지 구분되는가?
    step 전 차단은 코드 로그가 아니라 계정, 결제, runner, 권한 문제일 수 있다. 알림 문구와 실행 상태를 먼저 기록한다.
  3. 배포 성공을 무엇으로 판정하는가?
    초록색 workflow만 보지 않는다. 실제 URL, 이미지, 핵심 인터랙션, 홈페이지 링크를 확인한다.
  4. 복구 후 자동화가 다시 같은 결과를 만들 수 있는가?
    수동 우회로 배포했다면, 원래 sync 경로를 복구하고 다음 실행에서 재현 여부를 확인한다.

특히 세 번째가 중요하다. 이번에도 “배포가 됐다”는 말만으로 끝내지 않고, Aside를 이용해 페이지 경로와 이미지, 선택 UI, 홈페이지 내비게이션까지 확인했다. 배포 버튼이 눌렸다는 사실은 사용자에게 페이지가 정상적으로 보인다는 증거가 아니다.

이 구조가 주는 이득은 ‘무중단’보다 정확한 복구다

독립 경로를 두면 모든 장애가 사라지는 것은 아니다. 대신 장애의 종류를 빠르게 분리할 수 있다. 코드가 깨졌는지, Actions 계정이 막혔는지, 배포 서비스가 문제인지가 섞이지 않는다. 원인과 영향 범위를 따로 볼 수 있으니 복구 순서도 선명해진다.

이번 사례에서 내가 얻은 실질적인 이득은 새 페이지 하나가 올라갔다는 데만 있지 않다. 자동화 플랫폼의 결제 상태가 콘텐츠 전달 전체를 인질로 잡지 못한다는 사실을 확인했다. 동시에 GitHub Actions billing 문제는 별도로 해결해야 한다는 것도 분명해졌다. 우회 배포가 정식 복구를 대신할 수는 없기 때문이다.

결론: 자동화는 한 줄의 성공이 아니라, 실패해도 남는 경로다

AI 도구와 자동화를 붙일수록 워크플로는 더 똑똑해진다. 하지만 똑똑한 워크플로가 반드시 튼튼한 워크플로는 아니다. 계정 결제나 실행 플랫폼의 정책처럼 내 코드 밖에 있는 조건은 언제든 파이프라인 앞을 막을 수 있다.

그래서 나는 이제 새 자동화를 붙일 때 먼저 묻는다. “이 경로가 멈추면, 사용자가 보는 핵심 결과를 다른 경로로 확인하고 전달할 수 있는가?” 이 질문에 답할 수 있다면 도구를 더 추가하지 않고도 운영의 회복성이 올라간다.

당신의 프로젝트에서도 오늘 Actions를 잠시 멈춘다고 가정해보자. 마지막 검증 커밋을 배포할 수 있는지, 실제 URL을 확인할 수 있는지, 원래 자동화를 복구할 체크리스트가 있는지 적어보면 된다. 그 세 줄이 없다면 다음 자동화는 기능보다 먼저 두 번째 경로부터 설계해보길 권한다.

근거 출처

상호작용(에이전트-드루 대화·작업)

  • iloura-notion2web GitHub Actions 작업이 step 실행 전에 계정 결제 실패 또는 지출 한도 상향 안내로 차단된 작업 기록.
  • 수동 deploy-only workflow가 Cloudflare hook까지 실행되지 않은 기록.
  • 커밋 ed65560 push 뒤 Git 연결 배포로 /iloura-fragrance/가 라이브에 반영된 기록.
  • Aside를 통한 실제 경로, 이미지, 선택 UI, 홈페이지 내비게이션 검증 기록.

외부 정보(하베스터 수집)

이번 글에서는 외부 기사·트렌드·통계를 사용하지 않았다. 따라서 GitHub Actions의 일반 정책이나 요금제에 관한 외부 주장은 포함하지 않고, 위 상호작용 기록과 그로부터 도출한 워크플로 설계만 다뤘다.