시작은 항상 스프레드시트였다
메디움스의 콘텐츠 운영은 처음에 구글 시트 한 장으로 시작했다. 주제, 키워드, 담당자, 발행 예정일을 열로 나누고, 상태값을 직접 입력하는 방식이었다. 소규모일 때는 충분히 작동했다. 그러나 주간 발행 목표를 높이고 파이프라인에 AI 라이터를 붙이면서 문제가 드러나기 시작했다.
문서형 큐의 본질적 한계는 '조회'와 '실행'이 분리되어 있다는 점이다. 큐를 확인하고, 다음 작업을 판단하고, 실제 도구를 호출하는 세 단계가 모두 사람의 손을 거쳐야 했다. AI 에이전트가 시트를 읽고 API를 호출하는 스크립트를 붙여봤지만, 시트 구조가 바뀔 때마다 스크립트가 깨졌다. 유지보수 비용이 자동화 이득을 잠식하는 구조였다.
실행형 큐로의 전환: 무엇이 달라졌나
전환의 핵심 아이디어는 단순하다. 큐 자체가 실행 가능한 단위여야 한다. 메타데이터를 담은 문서가 아니라, 에이전트가 직접 소비할 수 있는 작업 객체로 설계하는 것이다.
메디움스가 선택한 구조는 JSON 기반 작업 명세였다. 각 콘텐츠 작업은 다음 필드를 포함한다: 주제 카테고리, 참고 주제 예시, 최근 발행 목록(중복 방지), 목표 길이, 출력 포맷. 이 명세를 로컬 에이전트에 넘기면 에이전트는 프롬프트를 구성하고, AI 모델을 호출하고, 결과를 지정된 형식으로 반환한다. 사람이 개입하는 시점은 명세를 작성하거나 결과를 검토할 때뿐이다.
중요한 설계 결정이 하나 있었다. 큐를 중앙 서버에서 관리할 것인가, 로컬에서 관리할 것인가. 중앙 서버 방식은 여러 팀원이 동시에 접근하기 좋지만, 로컬 에이전트와 동기화 문제가 생긴다. 로컬 방식은 빠르고 단순하지만 확장이 어렵다. 결국 하이브리드를 택했다. 작업 명세는 서버의 데이터베이스에 저장하고, 실제 실행은 로컬 에이전트가 담당하되, 완료된 결과는 서버 API를 통해 워드프레스로 전달하는 구조다.
로컬 에이전트와 서버 자동화를 함께 굴리는 방식
로컬 에이전트는 Claude Code CLI를 기반으로 운영된다. 작업자가 명령어 하나를 실행하면, 에이전트는 서버에서 다음 작업 명세를 가져오고, 시스템 프롬프트와 결합해 모델을 호출하고, 반환된 JSON을 파싱해 워드프레스 REST API로 임시저장 상태로 발행한다. 여기서 중요한 것은 에이전트가 결과를 직접 발행하지 않는다는 점이다. 항상 임시저장(draft) 상태로 올리고, 검토 후 발행 여부는 사람이 결정한다.
서버 자동화는 별도의 역할을 맡는다. 주기적으로 큐 상태를 점검하고, 오래된 작업이 쌓이면 알림을 보내고, 발행된 포스트의 메타데이터를 수집해 다음 주제 선정에 반영한다. 이 부분은 Python 스크립트와 GitHub Actions의 조합으로 운영 중이다. 복잡한 오케스트레이션 플랫폼 없이도 cron 기반으로 충분히 돌아간다.
두 레이어가 직접 통신하지 않는 것도 의도적 선택이었다. 로컬 에이전트와 서버 자동화 사이에는 데이터베이스가 중재자 역할을 한다. 직접 API 호출 대신 상태 변경을 통해 소통하는 방식이다. 덕분에 한쪽이 잠시 멈춰도 다른 쪽은 영향을 받지 않는다.
지금까지 배운 것
가장 큰 교훈은 파이프라인 복잡도를 일찍 낮춰야 한다는 것이다. 처음 설계할 때는 상태 머신, 재시도 로직, 오류 알림 채널까지 모두 붙이고 싶었다. 실제로 운영해보니 단순한 것이 오래간다. 큐에 들어간 작업이 끝까지 실행되는지 여부만 추적해도 충분한 시점이 있었다.
또 하나는 사람이 개입하는 체크포인트를 명확히 설계해야 한다는 점이다. 완전 자동화를 목표로 잡으면 검토 단계를 줄이고 싶은 욕구가 생긴다. 그러나 헬스케어 콘텐츠는 사실 기반 검증이 특히 중요하다. 확인되지 않은 수치나 효능 단정 표현이 실수로 발행되면 신뢰 비용이 크다. 자동화는 반복 작업을 줄이는 도구여야지, 판단을 대체하는 도구가 되어서는 안 된다.
메디움스의 빌딩 로그는 계속된다. 다음 단계는 작업 명세 자체를 반자동으로 생성하는 파이프라인 앞단을 붙이는 것이다. 어떤 주제가 필요한지, 어떤 키워드 공백이 있는지를 분석해 큐를 채우는 방향이다. 이 과정도 실제로 운영하면서 겪는 결정들을 계속 기록할 예정이다.