n8n Data Table 처음 써보기 — 트렌드 3개를 합쳐 매일 아침 분석 주제 뽑는 워크플로우
이 글과 연결된 글 보기
드래그로 이동 · 휠/두 손가락으로 확대 · 방향키로 글 선택 · 0으로 맞춤. 실선: 본문 링크, 점선: 시리즈·주제의 대표 연결.표시된 글 35편 목록
n8n Data Table 하나만 추가하면, 구글시트 없이도 워크플로우가 지난 실행 이력을 스스로 기억하고 참고해 오늘의 주제를 고르게 만들 수 있습니다. 이 워크플로우는 RSS 2개와 Data Table 이력을 Merge로 합쳐 AI Agent에게 넘기고, 중복되지 않는 분석 주제 1개를 ICE 점수까지 매겨 매일 아침 6시 Slack으로 보냅니다.
이 워크플로우 하나로 보여줄 수 있는 것
지금까지 이 시리즈는 상태를 저장할 일이 있으면 대부분 구글시트를 썼습니다. 이 워크플로우는 Data Table의 조회(Get)와 삽입(Insert)을 처음부터 끝까지 온전히 써보는 편으로, 시트 없이 워크플로우 혼자 "어제까지 뭘 다뤘는지"를 기억하게 만듭니다.
- Data Table 다루기 — 시트 없이 워크플로우 안에서 상태를 저장·조회하는 경험
- 여러 소스 병합 — RSS 2개와 Data Table 조회 결과를 Merge(append)로 합치는 경험
- AI 구조화 출력 + 의사결정 프레임워크 — LLM 답을 ICE 점수 스키마로 강제해 우선순위를 매기는 경험
- "학습하는" 워크플로우 설계 — 매 실행마다 이력을 쌓아 다음 실행이 참고하게 만드는 경험
배경 — 시트 없이도 상태를 기억하는 워크플로우
지난 편(시트 데이터를 인스타그램 카드뉴스로 발행하는 편)의 캔버스에도 Data Table 노드가 하나 있습니다. "Get TOKEN"이라는 이름으로 저장된 액세스 토큰을 조회해오지만, 정작 그 값을 쓰는 노드는 여전히 문자열을 직접 넣어둔 상태라 흐름에 완전히 연결되지는 않았습니다. Data Table을 처음 올려본 흔적은 있지만, 조회와 삽입을 온전히 써보는 건 이번 편이 처음입니다.
Data Table은 n8n 인스턴스 안의 내장 미니 데이터베이스입니다. 컬럼과 타입을 가진 진짜 테이블이고, dataTable 노드로 조회·삽입·수정·삭제를 합니다. 구글시트처럼 외부 API 호출이 없어 쿼터 걱정이 없고, 공유·편집이 필요 없는 데이터일수록 가볍습니다. 반대로 다른 사람과 같이 보거나 손으로 고칠 일이 있다면 시트가 낫습니다. "AI가 다음 실행 때 참고할 이력"이 전부인 이 워크플로우에는 Data Table이 맞습니다.
설치나 기본 노드 설명은 n8n으로 반복업무 자동화 포트폴리오 만들기에 있으니, 이 글은 워크플로우만 다룹니다.
구조 — Trigger / Task / Target
- Trigger — 매일 06:00(KST) 스케줄
- Task — RSS 2개와 Data Table 이력을 모아 합치고 Code로 정리한 뒤 AI가 주제 1개를 구조화된 JSON으로 생성
- Target — Data Table에 이력 저장, Slack 채널로 결과 발송
만들기
1. Schedule Trigger + 병렬로 시그널 3종 모으기
Schedule Trigger는 Days 인터벌에 triggerAtHour 6, triggerAtMinute 0으로 둬 매일 아침 6시(KST) 실행됩니다. 여기서 세 갈래가 동시에 뻗어 나가는데, RSS 노드 두 개는 구글 트렌드 KR(https://trends.google.co.kr/trending/rss?geo=KR)과 매경 헤드라인(https://www.mk.co.kr/rss/30000001/)을 읽고, onError: continueRegularOutput 설정 덕분에 RSS 서버가 잠깐 응답 없어도 워크플로우는 멈추지 않습니다(자세히는 아래 "흔적" 참고).
세 번째 갈래는 Data Table Get 노드입니다. daily_analysis_topics 테이블에서 createdAt 기준 내림차순으로 정렬해 최근 30개 행만 가져옵니다.
- Operation: Get
- Return All: 꺼짐, Limit: 30
- Order By:
createdAt, Direction: DESC - Always Output Data: 켜짐
Always Output Data를 켠 이유가 중요합니다. 테이블이 비어 있는 첫 실행에도 에러 없이 빈 결과를 다음 노드로 넘겨줍니다.
2. Merge — append 모드로 3개 입력 합치기
Merge 노드를 Number of Inputs 3, Mode를 Append로 설정합니다. Append 모드는 짝짓지 않고 입력 0번(구글 트렌드) → 1번(매경 헤드라인) → 2번(Data Table 이력) 순서로 아이템을 이어 붙여, 성격이 다른 데이터도 매칭 없이 하나의 리스트가 됩니다.
3. Code — 시그널과 이력을 텍스트로 정리
합쳐진 아이템에는 RSS 기사(title 필드)와 Data Table 이력 행(topic 필드)이 섞여 있습니다. Code 노드(Run Once for All Items)가 필드 유무로 갈라 각각 텍스트로 정리합니다.
const items = $input.all();
const signals = [];
const recent = [];
for (const item of items) {
const j = item.json || {};
if (j.topic) {
recent.push(j.topic);
} else if (j.title) {
signals.push(j.title);
}
}
return [{ json: {
signalsText: signals.slice(0, 40).map(s => '- ' + s).join('\n') || '- (수집된 시그널 없음)',
recentText: recent.slice(0, 30).map(t => '- ' + t).join('\n') || '- (없음)'
} }];
recent 배열이 최근 이력을 워크플로우 안에서 직접 조회한 결과가 프롬프트에 들어가는 지점으로, AI에게 "이미 다룬 주제는 피하라"는 근거가 됩니다.
4. AI Agent — 시스템 프롬프트와 구조화 출력
AI Agent Text에는 오늘의 시그널(signalsText)과 최근 주제(recentText)를 넣습니다.
오늘의 트렌드 시그널:
{{ $json.signalsText }}
최근에 이미 다룬 주제(중복 금지):
{{ $json.recentText }}
위 시그널을 참고해 오늘의 데이터 분석 주제 1개를 JSON으로 생성하라.
System Message 규칙 8개 중 핵심은 이렇습니다.
monetization_path는 주식/투자 정보, 창업 아이템 검증, 분석 리포트 판매 중 하나로 한정data_sources는 개인이 무료·저비용으로 접근 가능한 것만(API 유무·무료 여부 명시)duration은 1시간·하루·1주일 중 하나ice는 Impact·Confidence·Ease 각 1~10점,total은 합계,rationale은 한 줄 근거
Structured Output Parser는 이 스키마를 예시 JSON으로 강제합니다.
{
"topic": "...",
"ice": { "impact": 7, "confidence": 6, "ease": 8, "total": 21, "rationale": "..." },
"data_sources": [{ "name": "...", "access": "..." }]
}
ICE는 Impact(임팩트)·Confidence(확신도)·Ease(실행 용이성) 세 축을 점수로 매겨 더하는, 아이디어 우선순위를 정할 때 흔히 쓰는 프레임워크입니다. "재미있으면서 돈이 되는 주제 1개"라는 모호한 기준을 AI가 매번 같은 잣대로 채점하게 만드는 데 씁니다. Chat Model은 Gemini 3 Flash로, 무료 티어로 매일 한 번 도는 호출량은 충분히 감당합니다.
5. Data Table Insert — 이력 저장
AI 답변 뒤, 같은 daily_analysis_topics 테이블에 새 행을 씁니다.
topic_date: {{ $now.setZone("Asia/Seoul").toFormat("yyyy-MM-dd") }}
topic: {{ $json.output.topic }}
category: {{ $json.output.category }}
duration: {{ $json.output.duration }}
monetization:{{ $json.output.monetization_path }}
ice_total: {{ $json.output.ice.total }}
여기서 저장하는 필드는 6개뿐입니다. background, ICE 세부 점수, data_sources, first_step은 저장하지 않습니다. 다음 실행에 필요한 건 "이미 다룬 주제"와 "언제 다뤘는지" 정도라, 이 정도 요약이면 충분하다고 판단한 것으로 보입니다.
6. Slack — 오늘의 주제 발송
마지막 Slack 노드는 채널을 골라 텍스트를 보냅니다. 눈여겨볼 부분은 참조 방식으로, 바로 앞 Data Table Insert 노드의 $json(삽입 응답의 id·createdAt 등) 대신 $("주제 생성 AI").item.json.output.topic처럼 AI Agent 노드를 이름으로 직접 가리켜 값을 가져옵니다.
*주제:* {{ $("주제 생성 AI").item.json.output.topic }}
*ICE 점수:* Impact {{ $("주제 생성 AI").item.json.output.ice.impact }} · ...총 {{ $("주제 생성 AI").item.json.output.ice.total }}점
Data Table Insert 노드는 자신이 쓴 6개 필드 외의 값(예: first_step)을 갖고 있지 않아, 바로 앞 노드의 $json만 믿으면 값이 비어버립니다. 노드 이름으로 짚으면 중간에 어떤 노드가 끼어 있어도 원하는 값을 정확히 가져옵니다.
원본 캔버스에 남아 있는 흔적
이 워크플로우에는 스티키 노트가 없습니다. 대신 노드 파라미터에 설계 의도가 남은 지점을 몇 군데 옮깁니다.
RSS 노드 두 개에만 onError: continueRegularOutput이 설정돼 있고, 뒤쪽 AI Agent·Data Table Insert·Slack 노드에는 별도 에러 처리가 없습니다. 앞단은 "하나쯤 실패해도 계속 간다"로 설계했지만, 뒤쪽 단계는 실패하면 조용히 멈춥니다. Code 노드의 || '- (수집된 시그널 없음)' 부분도 흔적으로, RSS 두 개가 동시에 실패해도 그 문구가 그대로 프롬프트에 들어가 최근 이력만으로 주제를 뽑게 됩니다.
한계
- 이력 조회가 최근 30개로 고정 — 하루 한 번 기준 대략 한 달치 이력만 돌아본다는 뜻이라, 오래전 주제와는 다시 겹칠 수 있습니다.
- 중복 방지가 프롬프트 지시에만 의존 — 시스템 메시지 규칙이 유일한 장치이고, Data Table
rowExists사전 체크나 코드 레벨 강제 로직은 없어서 AI가 지시를 놓치면 중복 주제가 저장될 수 있습니다. - 이력에 요약 필드만 남음 —
background나 ICE 세부 점수,data_sources는 저장하지 않아 나중에 "왜 그 점수를 줬는지"를 이력만 보고 되짚기는 어렵습니다.
포트폴리오·면접 포인트
면접에서 "왜 구글시트 대신 Data Table을 썼나요?"라는 질문에는, 사람이 공유할 데이터가 아니라 워크플로우 내부 상태라서 내장 DB가 가볍다고 답하면 됩니다. Slack의 노드-이름 참조 방식까지 곁들이면 설계를 이해했다는 인상을 줍니다.
포트폴리오로 가져가려면 분석 주제 대신 관심 주제(운동 루틴, 독서 목록, 채용 공고)로 스키마를 바꿔보길 권합니다. Data Table Get orderBy·limit과 Insert 컬럼 매핑만 바꾸면 완전히 다른 "매일 기억하는 워크플로우"가 됩니다.
다음 액션
다음 편에서는 벡터DB 없이 실시간으로 사이트를 읽는 챗봇을 다룹니다. 이 편이 이력을 미리 쌓아두고 참고하는 방식이었다면, 다음 편은 저장해두는 것 없이 질문이 들어올 때마다 사이트를 직접 조회해 답하는 정반대 접근입니다.
