๐ n8n์ผ๋ก VSCODE / Claude Code ๋ฆด๋ฆฌ์ค ๋ ธํธ ๋ฒ์ญ ํ์ดํ๋ผ์ธ ๋ง๋ค๊ธฐ
๐ ํ ์ค ์์ฝ: VS Code์ Claude Code ๋ฆด๋ฆฌ์ค ๋ ธํธ๋ฅผ ์๋์ผ๋ก ํ๊ตญ์ด ๋ฒ์ญํ์ฌ Ghost ๋ธ๋ก๊ทธ์ ๋ฐํํ๋ n8n ์ํฌํ๋ก์ฐ๋ฅผ ๋ง๋ ๊ณผ์ ๊ณผ, ๊ทธ ๊ณผ์ ์์ ๋ง์ฃผ์น ์ค์ ํธ๋ฌ๋ธ์ํ ์ ์ ๋ฆฌํฉ๋๋ค.
๊ฐ๋ฐ ๋๊ตฌ์ ๋ฆด๋ฆฌ์ค ๋ ธํธ๋ ๋๋ถ๋ถ ์์ด๋ก๋ง ์ ๊ณต๋ฉ๋๋ค. ๋งค์ฃผ ์ ๋ฐ์ดํธ๋๋ VS Code ๋ฆด๋ฆฌ์ค ๋ ธํธ์ ๊ฑฐ์ ๋งค์ผ ๋์ค๋ Claude Code ๋ณ๊ฒฝ ๋ก๊ทธ(Changelog)๋ฅผ ๋งค๋ฒ ์ง์ ์ฝ๊ณ ๋ฒ์ญํ๋ ๊ฒ์ ๋ฒ๊ฑฐ๋ก์ด ๋ฐ๋ณต ์์ ์ ๋๋ค.
**"๋ฐ๋ณต ์์ ์ด ๋ณด์ด๋ฉด ์๋ํํ๋ผ"**๋ ์์น์ ๋ฐ๋ผ, RSS ํผ๋๋ฅผ ๊ฐ์ํ๊ณ , AI ๋ชจ๋ธ๋ก ๋ฒ์ญํ ๋ค, Ghost CMS์ ์๋์ผ๋ก ๋ฐํํ๋ ํ์ดํ๋ผ์ธ์ n8n์ ํ์ฉํด ๊ตฌ์ถํด ๋ณด์์ต๋๋ค.
๐ก ํ์ดํ๋ผ์ธ ๊ตฌ์ถ ํต์ฌ ํฌ์ธํธ
1. ์์ค๋ณ ํน์ฑ์ ๋ง์ถ ๋ ๋ฆฝ์ ์ธ ์ํฌํ๋ก์ฐ ์ค๊ณ
์ํฌํ๋ก์ฐ๋ฅผ ์ค๊ณํ๊ธฐ ์ , ํผ๋ ๋ฐ์ดํฐ์ ์ค์ ๊ตฌ์กฐ๋ฅผ ํ์ ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. VS Code์ Claude Code ๋ชจ๋ Atom ํผ๋๋ฅผ ์ ๊ณตํ์ง๋ง, ๋ด๊ณ ์๋ ์ ๋ณด์ ๊น์ด๊ฐ ๋ฌ๋์ต๋๋ค.
- VS Code (
code.visualstudio.com/feed.xml): ์์ฝ๋ ํ ์ค๊ณผ ๋งํฌ๋ง ์ ๊ณตํฉ๋๋ค. ์ค์ ๋ฆด๋ฆฌ์ค ๋ ธํธ ์ ๋ฌธ์ ์ป์ผ๋ ค๋ฉด HTTP ์์ฒญ์ผ๋กcode.visualstudio.com/updates/v1_xxxํ์ด์ง๋ฅผ ๊ฐ์ ธ์<main>ํ๊ทธ์์ ๋ณธ๋ฌธ์ ์ถ์ถํ๋ ๊ณผ์ ์ด ์ถ๊ฐ๋ก ํ์ํฉ๋๋ค. ๋์rel="related"๋งํฌ์ ๋ฆด๋ฆฌ์ค ํ์ด๋ผ์ดํธ ์ด๋ฏธ์ง๊ฐ ์์ด Ghost์feature_image๋ก ๋ฐ๋ก ํ์ฉํ ์ ์๋ ์ฅ์ ์ด ์์ต๋๋ค. - Claude Code (
raw.githubusercontent.com/anthropics/claude-code/main/feed.xml): ํผ๋ ์์ฒด์ ๋ณ๊ฒฝ ๋ก๊ทธ HTML์ด ํต์งธ๋ก ๋ค์ด์์ต๋๋ค. ๋ณ๋์ ํ์ด์ง Fetch๊ฐ ํ์ ์์ด ์ํฌํ๋ก์ฐ ๋ ธ๋๋ฅผ 2๊ฐ ์ค์ผ ์ ์์ง๋ง, ๋ฆด๋ฆฌ์ค ๋น๋๊ฐ ๋์ ์ค๋ณต ๋ฐํ ๋ฐฉ์ง๊ฐ ํจ์ฌ ์ค์ํฉ๋๋ค.
์ด๋ฌํ ์ฐจ์ด์ ๋๋ฌธ์ ํ๋์ ํตํฉ ์ํฌํ๋ก์ฐ๊ฐ ์๋ ์์ค๋ณ ๋ ๋ฆฝ ์ํฌํ๋ก์ฐ๋ก ๋ถ๋ฆฌํ์ต๋๋ค. ์ด๋ฅผ ํตํด ํ์ชฝ ํผ๋ ๊ตฌ์กฐ๊ฐ ๋ฐ๋๊ฑฐ๋ ์ฅ์ ๊ฐ ๋ฐ์ํด๋ ๋ค๋ฅธ ์ชฝ์ ์ํฅ์ ๋ฐ์ง ์์ต๋๋ค.
2. ๋ฏธ๋ ๋ ์ง(Insiders ๋น๋) ํํฐ๋ง ํจ์
VS Code ํผ๋์๋ ์ข
์ข
Insiders(ํ๋ฆฌ ๋ฆด๋ฆฌ์ค) ๋น๋๊ฐ ์์ฌ ๋ค์ด์ค๋ฉฐ, ์ด ํญ๋ชฉ์๋ ๋ฏธ๋ ๋ ์ง๊ฐ ์ฐํ ์๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. (์: ์ค๋์ด 9์ 11์ผ์ธ๋ฐ v1.138 (Insiders)์ <updated>๊ฐ 9์ 16์ผ๋ก ์ค์ ๋จ)
์ ๋ชฉ์ "(Insiders)"๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ ํํฐ ๋ ธ๋์์ 1์ฐจ์ ์ผ๋ก ๊ฑธ๋ฌ๋ด์ง๋ง, ํ๊ทธ ์์ด ์ฌ์ ๋ฑ๋ก๋๋ ์ด๋ก ์ ์์ธ ์ํฉ์ ๋ฐฉ์ดํ๊ธฐ ์ํด ๋ ์ง ๊ธฐ๋ฐ ๊ฒ์ฆ ์ฝ๋๋ฅผ ์ถ๊ฐํ์ต๋๋ค.
// ๋ฏธ๋ ๋ ์ง ํญ๋ชฉ์ ๊ฑด๋๋ฐ๋ ์์ ์ฅ์น
const updatedAt = item.json.isoDate || item.json.pubDate || '';
if (updatedAt && new Date(updatedAt) > new Date()) continue;
์ด๋ฌํ ์๋ฐฉ ์ฐจ์์ ๋ก์ง ๋๋ถ์ ๋ฏธ๋ ๋ ์ง ํญ๋ชฉ์ ๋ค์ ํด๋ง(Polling) ์๊ธฐ์ ์์ฐ์ค๋ฝ๊ฒ ์ฒ๋ฆฌ๋ฉ๋๋ค.
3. Supabase๋ฅผ ํ์ฉํ ์ค๋ณต ๋ฐํ ์๋ฒฝ ์ฐจ๋จ
n8n ์ค์ผ์ค๋ฌ๋ฅผ 6์๊ฐ๋ง๋ค ์คํํ๋ฉด, ๊ฐ์ ๋ฆด๋ฆฌ์ค๊ฐ ์ฌ๋ฌ ๋ฒ ์ต์ ํญ๋ชฉ์ผ๋ก ์กํ ์ ์์ต๋๋ค. RSS Read ๋ ธ๋๊ฐ ์์ฒด์ ์ผ๋ก ๋ณธ ํญ๋ชฉ์ ๋ฉ๋ชจ๋ฆฌ์ ๊ธฐ๋กํ๊ธด ํ์ง๋ง, ์ํฌํ๋ก์ฐ๋ฅผ ์์ ํ๊ฑฐ๋ n8n์ด ์ฌ์์๋๋ฉด ์ด ๋ฐ์ดํฐ๋ ์ด๊ธฐํ๋ฉ๋๋ค.
ํ์คํ **๋ฐํ ์ด๋ ฅ์ ์์ฅ(Single Source of Truth)**์ด ํ์ํ๊ธฐ์, Supabase์ published_releases ํ
์ด๋ธ์ ์์ฑํ์ฌ ๊ด๋ฆฌํ์ต๋๋ค.
CREATE TABLE published_releases (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
slug TEXT UNIQUE NOT NULL,
source TEXT NOT NULL CHECK (source IN ('vscode', 'claude-code')),
version TEXT NOT NULL,
title TEXT NOT NULL,
original_url TEXT NOT NULL,
release_date TIMESTAMPTZ NOT NULL,
change_count INT,
content_length INT,
ghost_post_id TEXT,
ghost_url TEXT,
status TEXT NOT NULL DEFAULT 'published',
feature_image TEXT,
published_at TIMESTAMPTZ DEFAULT NOW(),
created_at TIMESTAMPTZ DEFAULT NOW()
);
ํต์ฌ ํ๋ฆ:
- RSS ํผ๋ ํด๋ง ๋ฐ ํํฐ๋ง
- Supabase์์
slug์กฐํ (์ด๋ฏธ ์กด์ฌํ๋ฉด ์ฆ์ ์ข ๋ฃ) - ํต๊ณผ๋ ํญ๋ชฉ๋ง Gemini ๋ฒ์ญ ๋ฐ Ghost ๋ฐํ
- Supabase์ ๋ฐํ ์ด๋ ฅ(INSERT) ๊ธฐ๋ก
์ด ๊ตฌ์กฐ์ ๊ฐ์ฅ ํฐ ์ฅ์ ์ ๋น์ฉ ์ ๊ฐ์
๋๋ค. ์ด๋ฏธ ๋ฐํ๋ ๋ฆด๋ฆฌ์ค๋ฅผ ํ์ธํ์ฌ Gemini API ํธ์ถ ์ ์ ์ฐจ๋จํ๋ฏ๋ก ๋ถํ์ํ ํ ํฐ ๋ญ๋น๋ฅผ ๋ง์ ์ ์์ต๋๋ค. ๋ํ slug์ UNIQUE ์ ์ฝ์ ๊ฑธ์ด๋์ด, ๋ ์ด์ค ์ปจ๋์
(Race Condition)์ด ๋ฐ์ํ๋๋ผ๋ DB ๋จ์์ ์์ ํ๊ฒ ์ฐจ๋จ๋ฉ๋๋ค.
4. Gemini ๋ชจ๋ธ ๋ง์ด๊ทธ๋ ์ด์ ๊ณผ ํ๋ผ๋ฏธํฐ ์ต์ ํ
์ด๊ธฐ์๋ gemini-2.5-flash ๋ชจ๋ธ๋ก ์ํฌํ๋ก์ฐ๋ฅผ ๊ตฌ์ฑํ์ผ๋, API ์ ์ฑ
๋ณ๊ฒฝ์ผ๋ก ์ธํด ์๋ฌ๋ฅผ ๋ง์ฃผํ์ต๋๋ค.
"This model models/gemini-2.5-flash is no longer available to new users. Please update your code to use models/gemini-3.6-flash."
์ด์ gemini-3.7-flash๋ก ๊ต์ฒดํ๋๋ ์ด๋ฒ์๋ ๊ณผ๋ถํ(high demand) ์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์ต์ข
์ ์ผ๋ก **gemini-3.6-flash**๋ก ์ ์ฐฉํ๊ณ , n8n ๋
ธ๋ ์ค์ ์์ ์๋ ์ฌ์๋(Retry On Fail, 3ํ, 10์ด ๊ฐ๊ฒฉ)๋ฅผ ํ์ฑํํ์ฌ ์ผ์์ API ์ฅ์ ์ ์ ์ฐํ๊ฒ ๋์ํ๋๋ก ๊ตฌ์ฑํ์ต๋๋ค.
๋ํ Gemini 3.6+ ๋ฒ์ ๋ถํฐ๋ ํ๋ผ๋ฏธํฐ ๊ตฌ์กฐ๊ฐ ๋ณ๊ฒฝ๋์์ต๋๋ค.
// ๋ณ๊ฒฝ ์ (2.5 ๋ฒ์ )
"generationConfig": {
"temperature": 0.3,
"topP": 0.95,
"maxOutputTokens": 32768
}
// ๋ณ๊ฒฝ ํ (3.6+ ๋ฒ์ ) - thinkingConfig ํ์ฉ
"generationConfig": {
"maxOutputTokens": 32768,
"thinkingConfig": { "thinkingLevel": "low" }
}
๋ฒ์ญ ์์
์ ๋์ ์ฐฝ์์ฑ์ ์๊ตฌํ์ง ์์ผ๋ฏ๋ก thinkingLevel: "low"๋ก ์ค์ ํ์ฌ ํ ํฐ ์๋ชจ์ ์๋ต ์๋๋ฅผ ์ต์ ํํ์ต๋๋ค.
5. n8n ํํ์ ํ์์ JSON ์ค์ฒฉ(Mobiledoc) ์ด์ ํด๊ฒฐ
Ghost Admin API์ ๊ฒ์๋ฌผ์ ๋ฑ๋กํ ๋ ๋ณธ๋ฌธ์ mobiledoc ํ์์ JSON ๋ฌธ์์ด๋ก ์ ๋ฌํด์ผ ํฉ๋๋ค. ์ด๋ HTTP Request ๋ฐ๋(JSON) ์์ ๋ ๋ค๋ฅธ JSON ๊ตฌ์กฐ(mobiledoc)๊ฐ ๋ฌธ์์ด๋ก ๋ค์ด๊ฐ์ผ ํ๋ ์ํฉ์ด ๋ฐ์ํฉ๋๋ค.
JSON.stringify ์์ ๋ JSON.stringify๊ฐ ์ค์ฒฉ๋๋ฉด n8n์ ํํ์ ํ์๊ฐ invalid syntax ์๋ฌ๋ฅผ ๋ฐ์์ํต๋๋ค. ์ด ๋ฌธ์ ๋ IIFE(์ฆ์ ์คํ ํจ์)๋ฅผ ์ฌ์ฉํ์ฌ ํด๊ฒฐํ ์ ์์ต๋๋ค.
={{ (function() {
var md = $json.markdownContent || '';
var mobiledoc = '{"version":"0.3.1","markups":[],"atoms":[],' +
'"cards":[["markdown",{"markdown":' + JSON.stringify(md) + '}]],' +
'"sections":[[10,0]]}';
return JSON.stringify({
posts: [{ title: $json.title, mobiledoc: mobiledoc }]
});
})() }}
JavaScript ์ฝ๋ ๋ธ๋ก ์์์ mobiledoc ๋ฌธ์์ด์ ๋ฏธ๋ฆฌ ์์ ํ๊ฒ ์กฐ๋ฆฝํ ๋ค, ์ต์ข ๊ฐ์ฒด๋ง ๋ฐํํ๊ฒ ํ๋ฉด ํ์๊ฐ ์ ์์ ์ผ๋ก ๋์ํฉ๋๋ค.
๐ ์ต์ข ์ํฌํ๋ก์ฐ ์ํคํ ์ฒ
๋ ํ์ดํ๋ผ์ธ์ ์ ์ฒด์ ์ธ ๋ ธ๋ ํ๋ฆ์ ์๋์ ๊ฐ์ต๋๋ค.
VS Code ์ํฌํ๋ก์ฐ - ์ด 11๋ ธ๋
Claude Code ์ํฌํ๋ก์ฐ - ์ด 9๋ ธ๋

Claude Code์ ๋ ธ๋ ์๊ฐ 2๊ฐ ๋ ์ ์ ์ด์ ๋ ํผ๋ ์์ฒด์ ์ ์ฒด ๋ณ๊ฒฝ ๋ก๊ทธ๊ฐ ํฌํจ๋์ด ์์ด, ๋ณธ๋ฌธ์ ๊ฐ์ ธ์ค๋ Fetch ์์ ๊ณผ ์ถ์ถ ๊ณผ์ ์ด ์๋ต๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ฌ์ฉ๋ ํ์ ํ๊ฒฝ ๋ณ์ (4๊ฐ)
GEMINI_API_KEY=...
GHOST_ADMIN_API_KEY={id}:{secret}
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_ANON_KEY=...
๐ก ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์ด ํ์ดํ๋ผ์ธ ํ๋ก์ ํธ์ ์ง์ ํ ๊ฐ์น๋ ๋จ์ํ '์๋ํ'๋ฅผ ๋์ด์ **'๊ตฌ์กฐํ'**์ ์์ต๋๋ค.
Supabase์ ์ฒด๊ณ์ ์ผ๋ก ๋ฐํ ์ด๋ ฅ์ด ์ ์ฌ๋๋ฉด์, ๊ฐ ์์ค๋ณ ๋ฐํ ๋น๋, ๋ฒ์ญ๋ ์ฝํ
์ธ ์ ๊ธธ์ด ์ถ์ด, API ์คํจ์จ ๋ฑ์ ๋ฐ์ดํฐ ๊ธฐ๋ฐ์ผ๋ก ํ๋์ ํ์
ํ ์ ์๊ฒ ๋์์ต๋๋ค. ์์ผ๋ก ์๋ก์ด RSS ์์ค๋ฅผ ์ถ๊ฐํ๋๋ผ๋ ๊ธฐ์กด ์ํฌํ๋ก์ฐ๋ฅผ ๋ณต์ ํ ํ ํผ๋ URL๊ณผ ํํฐ ๋ก์ง๋ง ์์ ํ๋ฉด ๋๋ฏ๋ก ํ์ฅ์ฑ๋ ๋งค์ฐ ๋ฐ์ด๋ฉ๋๋ค.
๋ค์ ๋จ๊ณ๋ก๋ ๊ณต์ RSS๊ฐ ์๋ Anthropic ๋ด์ค ํผ๋ ๋ฑ์ ์ถ๊ฐํ๊ฑฐ๋, ๋ฆด๋ฆฌ์ค ๊ฐ Diff๋ฅผ ๋น๊ตํ์ฌ **"์ด๋ฒ ๋ฒ์ ์์ ์ฃผ๋ชฉํด์ผ ํ ํต์ฌ ๋ณํ"**๋ง ์ง์ด์ฃผ๋ ์ค๋งํธ ์์ฝ ๋ชจ๋๋ฅผ ๋์ ํด ๋ณผ ๊ณํ์ ๋๋ค.
"๋ฐ๋ณต ์์ ์ด ๋ณด์ด๋ฉด ์๋ํํ๋ผ. ๋จ, ํผ๋์ ์ค์ ๋ฐ์ดํฐ๋ฅผ ๊ผผ๊ผผํ ์ด์ด๋ณด๊ณ ๋์."