무색
기술블로그
에세이
연구
소개

무색

소프트웨어로 비즈니스의 가능성을 만듭니다. 웹·앱 개발, 음성 AI, 자동화 콘텐츠 제작까지 — 기술이 필요한 곳에 무색이 있습니다.

연락처

contact@museck.com

사업자 정보

상호: 무색

대표: 배성재

사업자등록번호: 577-58-00836

인천광역시 연수구 인천타워대로 323, 에이동 8층 801-802호 AB-132 (송도동, 송도 센트로드)

© 2026 무색. All rights reserved.
개인정보처리방침·이용약관·연락처
INCHEON, KR
블로그 SNS 자동 공유 키 비주얼
Claude Code로 2주 만에 만든 것들 — 소셜 자동화편
2026. 1. 22.

블로그 발행하면 4개 SNS에 자동 공유되게 만든 과정

n8nPostizClaude API자동화소셜미디어

이전 글에서 Claude Code 서브에이전트로 블로그 글 발행을 자동화했다. 근데 글을 발행한 다음이 문제였다. LinkedIn 열어서 요약 쓰고, X에서 280자 맞춰 트윗 쓰고, Threads랑 Instagram에도 올리고. 글 하나 쓸 때마다 네 번 반복이다.

이걸 자동화하고 싶었다. PayloadCMS에서 글을 발행하면 n8n이 웹훅을 받아서 Claude API로 플랫폼별 요약을 만들고, Postiz를 통해 네 곳에 동시에 올리는 파이프라인을 만들었다.

전체 흐름

파이프라인은 6개 노드짜리 n8n 워크플로우 하나로 돌아간다.

PayloadCMS의 afterChange 훅이 글 발행을 감지하면 n8n 웹훅으로 POST 요청을 보낸다. n8n은 블로그 콘텐츠를 조회하고 Claude API를 호출해서 LinkedIn, X, Threads, Instagram 각각에 맞는 요약문을 생성한다. 마지막으로 Postiz API를 통해 네 플랫폼에 동시 배포한다.

Claude API로 플랫폼별 요약 생성

n8n에서 Claude API를 연동하는 방법은 두 가지가 있다. 커뮤니티 노드를 쓰거나, HTTP Request 노드로 직접 호출하거나. 나는 후자를 골랐다. 프롬프트와 파라미터를 세밀하게 제어하고 싶어서.

프롬프트는 단순하게 짰다. 블로그 본문을 넘기면서 플랫폼별 글자 수 제한과 톤을 지정하고, JSON으로만 응답하라고 했다.

Based on the following blog post, generate optimized social media
summaries for 4 platforms.

1. LinkedIn (max 1300 chars): Professional tone, key insights
2. X/Twitter (max 280 chars): Concise and punchy
3. Threads (max 500 chars): Conversational, engaging hook
4. Instagram (max 2200 chars): Storytelling, hashtags at end

Return JSON only: {"linkedin","x","threads","instagram"}

한 가지 주의할 점이 있다. Claude가 JSON을 반환할 때 가끔 markdown code fence로 감싸서 보내준다. 그래서 파싱 전에 fence를 벗기는 로직을 추가했다.

// Claude API 응답에서 JSON 추출
let textContent = response.content
  .filter(b => b.type === 'text')
  .map(b => b.text).join('');

// markdown code fence 제거
textContent = textContent
  .replace(/```json\n?/g, '')
  .replace(/```\n?/g, '').trim();

const summaries = JSON.parse(textContent);

Postiz API 삽질 3연속

솔직히 이 글의 본체는 여기다. Postiz의 Public API 문서가 불완전해서 같은 날 커밋을 세 번이나 고쳤다.

첫 번째 삽질은 엔드포인트였다. /api/posts로 보냈더니 404. 실제 경로는 /public/v1/posts였다.

두 번째는 인증 형식. Bearer {key} 형식으로 보냈더니 401. Postiz는 API 키를 raw로 보내야 했다. Authorization 헤더에 키 값만 넣으면 된다.

세 번째는 request body 구조. 단순히 content 필드에 텍스트를 넣는 게 아니라, value 배열 안에 content와 image를 넣고, settings에 __type으로 플랫폼을 지정하는 구조였다.

{
  "type": "now",
  "posts": [
    {
      "integration": { "id": "linkedin-integration-id" },
      "value": [{ "content": "요약문", "image": [] }],
      "settings": { "__type": "linkedin" }
    }
  ]
}

n8n 환경변수 이슈

n8n에서 Anthropic API 키를 쓰려면 크리덴셜 시스템을 이용하는 게 정석이다. $credentials.anthropicApi.apiKey 같은 식으로 접근하면 되는데, HTTP Request 노드의 헤더에서는 이 참조가 제대로 동작하지 않았다. 결국 $env.ANTHROPIC_API_KEY로 환경변수를 직접 참조하는 방식으로 바꿨다. 배포 환경에서 관리하기도 더 편하다.

정리하면

CMS 훅으로 이벤트를 잡고, AI로 콘텐츠를 변환하고, 외부 API로 배포하는 패턴은 꽤 범용적이다. 블로그 말고도 제품 업데이트 공지나 뉴스레터 같은 곳에 비슷하게 적용할 수 있을 것 같다.

다만 외부 API 연동에서 삽질은 피할 수 없다. 특히 Postiz처럼 문서가 불완전한 서비스는 시행착오가 필수다. 이번에도 하루 만에 커밋 4개를 찍었으니까. 그래도 한번 파이프라인을 만들어두면 글 발행 버튼 하나로 네 곳에 동시 공유가 되니 충분히 값어치가 있다.

자주 묻는 질문

PayloadCMS afterChange 훅으로 블로그 발행 시 자동으로 SNS에 공유하려면?
afterChange 훅에서 _status가 published로 바뀔 때 n8n 웹훅 URL로 POST 요청을 보냅니다. n8n이 Claude API로 플랫폼별 요약을 생성하고 Postiz API로 4개 플랫폼에 동시 배포합니다.
Postiz API에서 인증이 실패하는 이유는?
Postiz는 Bearer 토큰이 아니라 API 키를 Authorization 헤더에 raw로 넣어야 합니다. 또한 엔드포인트가 /api/posts가 아닌 /public/v1/posts이고, body 구조도 value 배열과 settings.__type을 사용하는 독자적 포맷입니다.
Claude API 응답에서 JSON 파싱이 실패할 때 대처법은?
Claude가 JSON을 markdown code fence로 감싸서 반환하는 경우가 있습니다. 파싱 전에 ```json과 ``` 패턴을 제거하는 전처리 로직을 추가해야 합니다.
Claude Code로 2주 만에 만든 것들 — 소셜 자동화편(1/2)
Next

서브에이전트로 블로그 발행 자동화하기