
블로그에 글 하나 올리려면 꽤 번거롭다. CMS 로그인하고 제목 쓰고 본문 작성하고 카테고리 고르고 태그 달고 저장. 여기에 소셜 미디어 공유까지 더하면 같은 내용을 플랫폼마다 포맷 바꿔서 올려야 한다. 매번 이걸 반복하다 보니 '주제만 말하면 발행까지 알아서 해주는 흐름'을 만들고 싶어졌다.
Claude Code의 서브에이전트 시스템과 PayloadCMS의 MCP 프로토콜을 조합하면 이게 가능하다. 이번 글에서는 content-publisher라는 서브에이전트를 만들어서 블로그 콘텐츠 생성부터 CMS 저장까지 자동화한 과정을 정리했다.
파이프라인 구조는 단순하다.
메인 Claude Code 세션에서 "블로그 글 써줘"라고 하면 content-publisher 서브에이전트가 호출된다. 서브에이전트는 MCP로 PayloadCMS에 직접 접근해서 초안을 저장하고 사용자 확인을 기다린다. 확인되면 published로 전환하고 afterChange 훅이 n8n 웹훅을 트리거한다. n8n에서 Postiz API로 소셜 미디어에 자동 배포하는 구조다.
Claude Code는 agents/ 디렉토리에 마크다운 파일을 두면 서브에이전트로 인식한다. content-publisher의 핵심 설정은 이렇다.
---
name: content-publisher
description: 블로그 글 작성과 PayloadCMS 발행을 처리하는 콘텐츠 발행 에이전트.
tools: Read, Write, Grep, Glob
model: sonnet
mcpServers:
payloadcms:
command: npx
args:
- "-y"
- mcp-remote
- https://museck.com/api/mcp
- "--header"
- "Authorization: Bearer ${PAYLOAD_MCP_API_KEY}"
---포인트가 몇 가지 있다.
model: sonnet으로 지정했다. 블로그 글 생성에 Opus까지 쓸 필요는 없고 Sonnet이면 충분하다. 비용도 훨씬 저렴하다.mcp-remote 패키지가 원격 MCP 서버를 로컬처럼 쓸 수 있게 해준다.~/.claude/.env에서 환경변수로 관리한다. 서브에이전트 정의 파일에 시크릿을 하드코딩하지 않는다.서브에이전트의 행동을 결정하는 건 결국 프롬프트다. 이걸 에이전트 정의 파일 안에 다 넣으면 수정할 때마다 에이전트 설정 자체를 건드려야 해서 불편하다. 그래서 프롬프트를 별도 파일로 분리했다.
블로그 글 생성 가이드(prompts/blog-post.md)의 핵심 부분을 보면 이렇다.
## 구조
1. 제목: 핵심을 담은 한줄 (SEO 친화적, 60자 이내)
2. 요약: 2-3문장 (검색 결과/SNS 미리보기용)
3. 본문: 도입(문제) → 본론(과정, 코드) → 결론(배운 점)
4. 태그: 3-5개 기술 키워드
5. 카테고리: voice-ai | app-web-dev | tech블로그 글 외에 소셜 미디어용 프롬프트도 플랫폼별로 따로 만들었다. LinkedIn, X, Threads, Instagram 각각의 포맷과 톤에 맞춘 템플릿이다. 서브에이전트가 실행될 때 이 파일을 읽고 가이드라인을 따르게 된다.
이 구조에서 제일 편한 건 서브에이전트가 PayloadCMS의 스키마를 MCP를 통해 자동으로 이해한다는 점이다. REST API를 직접 호출하려면 필드 이름이 뭔지, 어떤 타입인지, 관계 필드는 ID를 어떻게 넣는지 일일이 알려줘야 한다. MCP를 쓰면 이런 것들을 에이전트가 알아서 파악한다.
다만 까다로운 부분이 하나 있었는데 PayloadCMS의 richText 필드다. Lexical 에디터 포맷을 사용해서 단순 문자열이 아니라 구조화된 JSON을 넣어야 한다.
{
"root": {
"type": "root",
"children": [
{
"type": "heading",
"tag": "h2",
"children": [{"type": "text", "text": "섹션 제목"}]
},
{
"type": "paragraph",
"children": [{"type": "text", "text": "본문 텍스트"}]
}
]
}
}이 JSON 구조를 서브에이전트 프롬프트에 예시로 넣어줘야 했다. heading의 tag 값이 "h2"인지 "2"인지, code block은 code-highlight 노드를 써야 하는지 같은 세부 사항에서 삽질을 좀 했다. 한번 잡아두면 그 다음부터는 잘 동작한다.
자동화라고 해서 글을 바로 발행하면 위험하다. 서브에이전트가 생성한 글이 항상 완벽할 수는 없으니까. 그래서 반드시 draft로 먼저 저장하고 사용자가 확인한 뒤에 published로 전환하는 방식을 택했다.
흐름을 정리하면 이렇다.
_status: "draft"로 저장이 Human-in-the-loop 패턴이 자동화의 편의성과 품질 관리 사이에서 균형을 잡아준다. 완전 자동은 편하지만 실수가 그대로 나간다. 완전 수동은 안전하지만 번거롭다. 중간이 딱 맞다.
이번 작업에서 얻은 교훈을 정리해봤다.
MCP는 REST API보다 에이전트 연동에 훨씬 적합하다. REST API를 쓰면 에이전트에게 엔드포인트 URL, 인증 방식, 요청 형식을 모두 알려줘야 한다. MCP를 쓰면 에이전트가 사용 가능한 도구 목록을 자동으로 발견하고 스키마도 파악한다. 프롬프트가 훨씬 간결해진다.
프롬프트 외부화는 유지보수 측면에서 큰 차이를 만든다. 처음에는 에이전트 정의 파일 안에 모든 가이드라인을 넣었는데 금방 관리가 안 됐다. 블로그 포맷이 바뀌면 에이전트 정의를 고쳐야 하고 소셜 미디어 포맷이 바뀌면 또 고쳐야 하고. 파일로 분리하니까 각각 독립적으로 수정할 수 있어서 편하다.
서브에이전트 모델 선택은 비용에 직접적으로 영향을 준다. 블로그 글 하나 쓰는 데 Opus를 돌릴 필요는 없다. Sonnet으로도 충분히 좋은 초안이 나온다. 다만 Lexical JSON 같은 복잡한 구조를 다룰 때는 예시를 풍부하게 제공해야 한다. 모델 능력이 조금 부족한 부분은 프롬프트로 보완하는 전략이다.
지금은 블로그 글 생성과 CMS 저장까지가 서브에이전트의 역할이다. 다음 글에서는 PayloadCMS의 afterChange 훅과 n8n을 연결해서 발행된 글이 자동으로 소셜 미디어에 올라가는 파이프라인을 다룰 예정이다. "글 써줘" 한마디로 블로그 발행부터 소셜 공유까지 한번에 끝나는 흐름이 목표다.