3줄 요약
- 핵심: n8n 자동 포스팅 가이드: Google Sheets 기반 워드프레스 발행 자동화의 설치/구성 흐름을 한 번에 따라갈 수 있도록 단계와 체크포인트를 정리했습니다.
- 실전: 실패가 잦은 구간(권한, 네트워크, 버전/의존성)을 먼저 점검해 재시도 비용을 줄입니다.
- 운영: 적용 후 검증 기준(로그·접속·동작 확인)을 남겨 유지보수 난이도를 낮춥니다.
트러블슈팅
- 설정 적용이 안 되면 브라우저 캐시/서비스 재시작 후 동일 증상을 로그 기준으로 재현하세요.
- 외부 접속 문제가 있으면 DNS/포트포워딩/리버스프록시 순서로 분리 진단하세요.
- 업데이트 이후 오류는 직전 버전·설정 백업 기준으로 롤백 경로를 먼저 확보하세요.
결론 + 다음 단계
이 글의 절차를 기준으로 기본 동작을 안정화한 뒤, 모니터링/백업/자동복구를 추가하면 장기 운영 품질이 크게 올라갑니다.
내부 링크
이 글은 n8n + Google Sheets + WordPress 조합으로 “자동 포스팅 파이프라인”을 운영 가능한 형태로 만드는 과정을 정리한다. 핵심은 단순히 글을 생성하는 것이 아니라, 주제 큐(Queue) 관리 → 프롬프트/출력 규격화(JSON) → 워드프레스 발행(Draft/Publish) → 상태 업데이트(시트)까지 폐쇄 루프(Closed Loop)를 만드는 것이다.
이 글의 목표(성공 기준)
이 글을 끝까지 따라가면 ① Google Sheets에서 “발행할 주제”를 안정적으로 가져오고 ② Gemini 같은 모델이 SEO에 맞춘 결과를 JSON 스키마로 일관되게 출력하며 ③ n8n이 결과를 정제해 WordPress에 발행(Draft 권장)하고 ④ 발행 성공 시 시트 상태를 갱신하는 흐름까지 완성되어야 한다.
구성 요소(한눈에 보기)
- n8n: 워크플로우 오케스트레이터
- Google Sheets: 주제/상태 큐(Queue) 데이터베이스
- LLM(API): 본문/SEO 메타 생성(Gemini 등)
- WordPress REST API: 글 생성/발행(Draft → 검수 → Publish)
n8n을 활용한 자동 포스팅의 시작
Gemini와 구글시트 기반 n8n 자동 포스팅의 심화 과정으로, 미리 정해둔 주제를 하나씩 뽑아내고 지난 글과 다음 글의 맥락을 자연스럽게 연결하면서 SEO 최적화까지 자동화한 실전 과정을 기록한다.
매일 꾸준히 블로그에 양질의 콘텐츠를 올리는 일은 호흡 운동처럼 규칙적이고 고된 노동이었다. 나의 N100 미니 PC는 24시간 깨어 있으면서 이 모든 작업을 감당할 준비가 되어 있었다. 이전 글에서 Proxmox 위에 n8n을 설치하고 Gemini API를 연동하여 기본적인 블로그 글 자동 생성 시스템을 구축했다(N100 Proxmox 기반 n8n 워드프레스 자동화: Gemini API 연결 및 매일 자동 포스팅 워크플로우 구축).
이제 이 시스템을 한 단계 발전시켜, 단순히 글을 생성하는 것을 넘어 콘텐츠의 질과 발행 스케줄까지 완벽하게 관리하는 자동 포스팅 워크플로우를 완성할 차례였다. 목표는 명확했다. 구글 시트에 미리 등록된 주제 리스트를 매일 하나씩 가져와, SEO 최적화 점수(Rank Math 기준) 90점 이상을 달성하는 글을 자동으로 작성하고 발행하는 것이었다. 이 흐름의 핵심은 Gemini와 구글시트 기반 n8n 워크플로우를 끊김 없이 이어가는 데 있다. 실제 운영에서 Gemini와 구글시트 기반 n8n 구성은 주제 큐 관리, 프롬프트 일관성, 발행 안정성을 동시에 확보해준다.
구글 시트를 활용한 자동 포스팅의 큐(Queue) 시스템 구축
자동화된 콘텐츠 발행 시스템의 가장 큰 문제는 ‘무엇을 쓸 것인가’에 대한 결정이었다. AI에게 매번 무작위 주제를 선정하도록 맡겨도 되겠지만, 블로그의 방향성은 내가 경험한 것들에 대한 기록을 하고 공유하는 것이 우선이기에 내가 미리 쓰려고 계획한 주제를 제공하는 편이 훨씬 취지에 맞는 방향이었다. 그래서 나는 구글 시트를 콘텐츠 큐(Queue)이자 마스터 데이터베이스로 사용하기로 결정했다. 이 설계 덕분에 Gemini와 구글시트 기반 n8n 자동화가 단순 테스트를 넘어 운영 가능한 시스템으로 바뀌었다. 이 방식은 서버에 불필요한 데이터베이스를 추가 설치할 필요 없이, 가장 범용적인 도구를 사용하는 합리적인 선택이었다. 또한 주제를 선정하는 것도 API 토큰을 소모하는 작업인데 이것 역시 세이브되니 일석이조다.
구글 시트는 간단하게 작성했다.’주제 (Topic)’, ‘상태 (Status)’ 딱 두줄이다. n8n 워크플로우는 매일 아침 9시에 실행되도록 예약 설정했다. 워크플로우는 구글 시트 노드(Google Sheets Node)를 사용해 ‘상태’ 열이 비어있는 값들만 불러오도록 설정했다. 하나만 불러와도 글을 쓰는데 지장은 없지만 이렇게 다음 주제까지 불러오게 하면 글을 일단 쓰고 마지막에는 “다음에는 이런 주제로 써보겠다.”라는 내용으로 마무리 할 수 있다. 그리고 SEO를 위해서는 핵심 키워드도 필요한데 구글 시트에 키워드를 미리 채워 넣는 대신 Gemini에게 프롬프트로 검색에 유리한 핵심 키워드를 추천하도록 요청했다. 자세한 함수 문법은 n8n 문서 – Current node input를 참고하면 빠르게 이해할 수 있다.
그러면 이제 n8n에서 이 구글 시트를 읽어오도록 해야 한다. n8n에서 구글 시트 “Get row(s) in sheet” node를 추가하고 아래와 같이 설정해줬다. 이 스텝은 아주 쉽고 간단하다.

Gemini 프롬프트의 혁명: JSON 스키마를 이용한 SEO 최적화 강제
프롬프트는 크게 두 파트로 나뉘는데 하나는 AI에 역할을 부여하는 System Prompt(message)이고, 또 하나는 글 작성에 대한 내용과 세부 지침을 전달하는 Prompt(message)이다. 프롬프트는 내가 초안을 만들고 Gemini와 여러번 상의를 거쳐 아래와 같이 만들어봤다.
너는 N100 미니 PC와 Proxmox를 운영하며 AI의 도움을 받아 서버를 만들어가는 과정을 기록하는 테크 블로거야.
독자에게 말을 거는 말투(~했잖아, ~해요 등)는 절대 사용하지 마.
모든 문장은 경험이나 느낀점을 기록하는 수필처럼 평어체인 '--다', '--였다', '--한다'로 끝내줘.
나의 경험을 기록하는 데 집중하되 독자가 지루하지 않게 약간의 유머를 곁들여줘. 그리고 불필요한 인삿말이나 독자와의 대화 시도는 배제해줘.
아래 제공되는 [나의 과거 글 기록]을 완벽히 학습해서, 그동안의 경험과 문체, 그리고 글의 형식을 학습해서 앞으로 쓰게될 글에도 반영해줘.
[나의 과거 글 기록 (시간 순서대로)]
(링크 목록)
마지막에 나의 과거 글 기록을 참고하도록 한 이유는 글의 맥락 상 이전 내용 참고가 필요한 경우 자연스럽게 순환 링크를 걸기도 하고 과거의 내가 해둔 세팅이나 경험한 것들을 기억하고 다음 글에도 연속성 있게 반영하도록 하기 위함이다.
다음으로 본격적으로 글 작성을 지시하는 프롬프트는 아래와 같이 작성하였다. 기존과 다른점은 다음 스텝으로 깔끔하게 넘기기 위해 형식에 대한 지정을 디테일하게 해줬다는 것이다. 이전까지는 Gemini에게 단순히 글을 써 달라고 요청했지만, 이제는 결과물이 워드프레스에 최적화된 구조를 갖춰야 했다. 특히 Rank Math 같은 SEO 플러그인이 요구하는 메타 데이터, 제목, 슬러그, 핵심 키워드 등이 명확히 분리되어야 했다. 이 문제를 해결하기 위해 Gemini API 호출 시 JSON 스키마를 지정하는 방식을 도입했다. AI에게 글을 자유롭게 쓰게 두는 대신, 출력 형식 자체를 강제하는 강력한 방법이었다.
# 오늘 글의 주제:
"{{ $("Get Topic").all()[0].json["Topic"] }}"
# 다음 글 주제:
"{{ $("Get Topic").all()[1]?.json["Topic"] || "홈서버 운영 꿀팁" }}"
[작성 지침 - 엄격 준수]
1. 문체 제한: 반드시 '--다', '--였다', '--한다'로 끝나는 문어체(일기/기사 형식)로 작성해. 일상을 기록하는 수필 쓰듯이. 인삿말도 필요 없어.
- 잘못된 예: "설치해 봤잖아?", "정말 편했지?"
- 올바른 예: "설치를 시도했다.", "상당히 편리했다."
2. 직접 경험 강조: 내가 직접 작업하며 겪은 과정과 기술적 판단을 기반으로 써줘.
3. 분량 및 구성: 1000단어 이상의 길이로 상세하게 작성하되, 약간의 위트와 유머를 섞어줘.
4. 초보자가 보고 따라할 수 있을 만큼 단계별로 디테일하게 써줘.
5. SEO를 고려해서 먼저 핵심 키워드와 관련 키워드를 생각하고 글 전체에 고르게 여러번 분포하도록 써줘.
6. 글 제목은 인기있는 검색어와 주제 연관성, SEO를 고려하고 누구라도 보면 클릭하고 싶게 만드는 제목으로 선정해줘.
7. <h3> 태그로 소제목을 달고 문단을 나눠줘. 글의 포맷과 구성은 나의 지난 글의 형식을 참고해줘.
8. 글 내용 중 내 과거 글에서 언급할 만한 내용이 있을 때만 자연스럽게 짧게 언급하면서 링크 걸어줘.
9. 글 마지막에 다음 주제인 "{{ $("Get Topic").all()[1]?.json["Topic"] || "홈서버 운영 꿀팁" }}"를 너가 보고 적당한 키워드와 짧은 내용을 언급하며 "다음엔 이런 주제로 글을 써봐야 겠다." 라는 형식으로 끝 내줘.
# 반드시 아래의 순수 JSON 형식으로만 답변해:
{
"title": "SEO 최적화된 시선을 끄는 제목",
"content": "본문",
"slug": "english-url-slug",
"description": "핵심 키워드와 관련 키워드가 포함된 요약 문구",
"focus_keyword": "핵심 키워드"
}
내가 직접 테스트해본 결과, AI는 JSON 스키마를 강제할 때 결과물의 일관성이 극도로 높아졌다. 그러나 AI가 완벽하게 규정을 지키는 일은 드물어서, 출력된 JSON 문자열 주변에 불필요한 텍스트나 마크다운 기호(“`json)가 포함되는 경우가 빈번했다. 이 부분이 나에게 새로운 숙제를 안겨주었다.
난관 극복: n8n Code Node를 활용한 JSON 파싱 및 데이터 정제
Gemini에서 JSON 형식으로 결과물을 받았음에도 불구하고, 워드프레스 API로 곧장 전달하기는 어려웠다. 앞서 언급했듯이, AI가 생성한 JSON 문자열은 종종 유효성 검사에서 실패했다. 유머러스하게도, AI는 규칙을 만들지만 그 규칙을 가장 자주 어기는 주체이기도 했다. 이 문제를 해결하기 위해 n8n의 핵심 기능 중 하나인 코드 노드(Code Node)를 사용하기로 했다. 코드 노드는 JavaScript 환경을 제공하여 데이터 변환과 정제에 매우 유용했다.
// 1. n8n의 현재 아이템 데이터 가져오기
const rawData = $input.item.json.content.parts[0].text;
try {
// 2. 가장 처음 나타나는 '{'와 가장 마지막에 나타나는 '}' 위치 찾기
const startBrace = rawData.indexOf('{');
const endBrace = rawData.lastIndexOf('}');
if (startBrace === -1 || endBrace === -1) {
throw new Error("텍스트에서 JSON 구조({ })를 찾을 수 없습니다.");
}
// 3. 실제 JSON 부분만 추출
let jsonString = rawData.substring(startBrace, endBrace + 1);
// 4. JSON 파싱
const parsedData = JSON.parse(jsonString);
// 5. 결과 반환 (워드프레스 노드에서 쓰기 좋게 정리)
return {
title: parsedData.title || "제목 없음",
content: parsedData.content || "본문 내용 없음",
slug: parsedData.slug || "",
description: parsedData.description || parsedData.meta_description || "",
focus_keyword: parsedData.focus_keyword || ""
};
} catch (error) {
// 실패 시 디버깅을 위한 에러 정보 반환
return {
error: "파싱 실패: " + error.message,
rawData_preview: rawData.substring(0, 100) + "...", // 앞부분만 살짝 보기
status: "failed"
};
}
코드 노드에서 수행한 작업은 단순했지만 결정적이었다. 먼저, 이전 Gemini 노드에서 받은 결과물(텍스트)을 문자열로 읽어 들였다. 이 문자열에서 시작과 끝에 위치할 수 있는 모든 불필요한 마크다운 백틱(“`json)과 공백 문자(trim)를 제거했다. 이후 JavaScript의 `JSON.parse()` 함수를 사용하여 안전하게 객체로 변환했다. 혹시 모를 에러 발생에 대비하여 `try-catch` 구문을 사용한 것은 필수였다. JSON 파싱이 성공하면, 이제 워드프레스 발행에 필요한 깨끗한 데이터 필드(제목, 내용, 슬러그, 메타 디스크립션)를 다음 노드로 보낼 준비가 완료된다. 미니 PC에서 돌아가는 n8n의 자바스크립트 엔진은 이 복잡한 정제 작업을 초당 수십 회씩 처리할 수 있는 충분한 성능을 제공했다.
워크플로우의 마지막 단계: 워드프레스 글 자동 발행
정제된 데이터를 워드프레스로 보내는 과정은 비교적 간단했다. Code Node 다음에는 워드프레스 노드(WordPress Node)를 연결하고, 이전 노드에서 정리된 제목과 본문 데이터를 매핑하면 된다. 여기서 생성된 글은 Draft로 저장되도록 했다. 여기서 처음에 한가지 헤맸던 부분이 있는데 모든 입력창을 Fixed가 아닌 Expresssion으로 설정해야 한다는 점이다. 처음에 이거 몰라서 토큰을 몇번이나 날렸는지 모른다. 또 한가지 주의할 점은 테스트를 위해 실행을 누를 때 마다 다른 노드들도 다 돌아가는데 이걸 방지하기 위해서 각 노드마다 이전 출력을 유지해주는 PIN이라는 기능이 있다. 이걸 알고난 다음부터는 디버깅의 속도가 획기적으로 빨라졌다.
이로써 나는 로컬 N100 서버에서 돌아가는 n8n이 클라우드플레어 터널을 통해 외부 워드프레스 서버와 안전하게 통신하도록 구성했다. 이 방식은 나의 홈 서버 보안을 유지하는 동시에 외부 서비스와의 연동성을 극대화하는 방법이었다(셀프 호스팅 자동화의 심장, n8n 설치와 Cloudflare Tunnel 연결 완벽 가이드).
아쉬운 점들: 발행 및 상태 업데이트와 썸네일 자동 생성
마지막 단계는 구글 시트의 상태 업데이트였다. 글이 성공적으로 발행되었다면, 다시 구글 시트 노드를 연결하여 해당 행의 ‘상태’를 ‘Pending’에서 ‘Posted’로 변경해야 했다. 이 ‘폐쇄 루프(Closed-Loop)’ 시스템이야말로 진정한 n8n 자동 포스팅 워크플로우의 핵심이었다. 시트에 무한한 주제 리스트만 채워 넣으면, N100 서버는 내가 잠든 사이에도 꾸준히 SEO 최적화된 콘텐츠를 생산해내는 무인 공장이 되는 것이다. 하지만 이 단계까지 완성한 것만으로도 완전 자동은 아니지만 반 자동 수준은 되어서 일단 이대로 사용하기로 하고 나머지 부분을 보완하는 것은 다음 포스팅 주제로 남겨두려고 한다. 이후에는 Gemini와 구글시트 기반 n8n 파이프라인에 썸네일 생성과 상태 동기화를 추가해 완전 자동에 가깝게 올릴 계획이다. 정리하면 Gemini와 구글시트 기반 n8n 전략은 운영 효율과 SEO 품질을 동시에 챙기는 현실적인 선택이다.
함께 보면 좋은 글
관련 글을 같이 보면 설치와 운영 흐름을 더 빠르게 이해할 수 있습니다.