📅 Sense Stock 개발 일지 (2025-06-23)
n8n 기반 뉴스 요약 자동화 시스템 Sense Stock 구축 중 진행한 작업들을 정리합니다.
오늘은 기존에 구현해놨던 Slack Trigger + Block Kit 기반의 UI(User Interface) 흐름을 보다 구조화하고,
RAG 기반 분석 워크플로우로 확장 가능한 형태로 리팩토링 했습니다.
기존 구조의 한계점 분석
초기 설계: Slack Trigger + Block Kit UI
기존 시스템은 다음과 같은 흐름으로 작동했다:
- 사용자가 Slack에서 질문 입력
- Slack Trigger가 질문을 수신
- Block Kit 메시지(UI)가 전송되어 "디테일 분석" 버튼 제공
- 사용자가 버튼 클릭 시 추가 분석 수행
핵심 문제점: Context 손실
가장 큰 문제는 사용자 Action 이후의 흐름이 Webhook으로 분기된다는 점이었다. Slack Block Kit에서 사용자가 액션을 취하면, 해당 이벤트는 기존 워크플로우와 완전히 분리된 새로운 Webhook Workflow에서 처리된다.
이로 인해 초기 사용자 질문(chatInput)이 후속 워크플로우에 전달되지 않는 치명적인 문제가 발생했다.
🧠 해결을 위한 방법 3가지
- Google Sheet에 저장 & 불러오기
- 우선 DB적재 방식(Stack?)이 아니라, Update방식으로
- Redis / Supabase에 저장 연동
- n8n 내부 전역 변수 사용 방식 (단, Workflow 재시작 시 초기화됨)
- Slack Trigger Test 진행중, Webhook Trigger Test Workflow시 초기화됨.
방식 | 설명 | 추천 여부 |
Set → Static Data | 워크플로우 내부 변수에 저장 | ⚠️재시작 시 초기화됨 |
Redis or Google Sheet | 외부 DB로 저장 | ✅ 지속성 확보 |
chatInput을 Slack metadata로 보내기 | Slack에서 button 클릭 시 value에 넣기 | ⚠️ payload 크기 제한 있음 |
1. ❌ n8n 내부 전역 변수(Global Variable)
$global, $env, set('key', value) 등의 방식으로 전역에 값을 저장하고 불러오려 했지만,
전역 변수는 동일 워크플로우 내에서만 유효하고,
Webhook Trigger가 있는 다른 Workflow에서는 초기화된 상태로 재시작됨.
특히 Webhook 테스트 중엔 완전히 새로운 인스턴스로 실행되기 때문에 context가 소실됨.
→ 사용 불가.
그래도 이걸 직접 해보면서 "아, 단일 워크플로우 내에서 흐름을 분기할 땐 유용하겠구나" 라는 걸 알게 됐다.
복잡한 조건 분기나 임시 캐싱이 필요한 경우에는 꽤 괜찮은 도구라는 생각이 들었다.
$getWorkflowStaticData('global')
https://docs.n8n.io/code/cookbook/builtin/get-workflow-static-data/
getWorkflowStaticData | n8n Docs
docs.n8n.io
this.getWorkflowStaticData() 또는 $workflow.staticData과 $getWorkflowStaticData('global')의 차이는
노드 버전과 스코프 제공 방식의 차이
방식 | 작동 여부 | 설명 |
this.getWorkflowStaticData('global') | ❌ (Code 노드 v2에서 안됨) | Function v1 노드에서만 사용 가능 |
$workflow.staticData | ⚠️ 조건부 작동 | Code 노드 v2에서 사용 가능하긴 하지만, 직접 초기화/관리 필요하고 context 문제 발생 |
$getWorkflowStaticData('global') | ✅ Code 노드 전용 안전 방식 | Code 노드에서 static data에 접근하는 공식 지원 함수 |
📌 왜 $getWorkflowStaticData()만 되는가?
this.getWorkflowStaticData() 는…
- Function Node v1에서 this 객체가 제공되기 때문에 작동
- *Code Node(v2)**에서는 this가 없거나 정의되지 않음 → 에러 발생
$workflow.staticData 는…
- Code Node에서 실행 컨텍스트에 따라 undefined가 될 수 있음
- 예를 들어, **수동 실행(Execute Workflow)**에서는 값이 없어서 .global 접근 시 에러 발생
- 수동 테스트나 디버깅 시에는 불안정함
$getWorkflowStaticData() 는…
- n8n에서 공식적으로 제공하는 Code 노드 전용 함수
- 내부적으로 context와 초기화까지 알아서 처리해줌
- 항상 안전하게 staticData.global 또는 staticData.node 접근 가능
2. ✅ Google Sheet에 저장 → 매칭 후 불러오기 (최종 선택)
간단하고 직관적인 상태 관리 방식.
이미 Credential 등록되어 있어 바로 사용 가능했고,
Sheet 구조도 다음과 같이 명확하게 정의했다
[userId, userName, channelId, chatInput, timestamp, selectedValues]
데이터 저장 방식은 DB 삽입(Stack)처럼 append가 아니라,
userId 기반으로 Update (중복 저장 방지)
Webhook으로 들어온 userId와 매칭해서:
- 사용자가 원래 했던 질문(chatInput)을 불러오고
- 새로 선택된 값(selectedValues)을 업데이트
결과적으로, Slack에서 발생하는 여러 이벤트를 하나의 사용자 중심 데이터로 통합할 수 있게 됨
KYC(Know Your Customer) 성향 분석 구조 구성
이후 흐름은 아래처럼 구성했다
🧱 Workflow 구조
Step 1. Slack Trigger로부터 선택값(userId, channelId, ...) 파싱
→ JSON 파싱으로 [userId, userName, channelId, chatInput, timestamp, selectedValues] Data 저장
Step 2. Google Sheet → userId 기준으로 사용자의 질문(chatInput) 검색
→ DB Get Node: userID 매칭을 통해 사용자 질문 추출
Step 3. GPT에게 chatInput + selectedValues 전달
→ 디테일 분석 요청시, 선택되는 항목들(selectedValues) Google Sheet Update후 GPT 전달
Step 4. GPT가 수행하는 일
- 질문 의도 재해석
- 예/아니오 기반 보완 성향 질문 5개 생성
- Slack에서 Form 형태로 사용자에게 전달
1단계: 의도 해석
사용자의 질문과 선택된 항목들을 바탕으로 사용자의 핵심 의도 파악
- 선택된 카테고리(categories)
- 핵심 의도(coreIntent)
- 세부 동기(detailMotivations)
- 카테고리별 구체적 관심사 분석
투자 목적, 정보 수집 목적, 학습 목적 등 구분
단기/중기/장기 관점 중 어느 것에 초점을 두는지
- 카테고리별 구체적 관심사 분석
2단계: 의도 파악을 위한 추가 질문 생성
사용자의 의도를 더 정확히 파악하기 위해 다음 원칙에 따라 정확히 5개의 질문을 생성
- 성향 보완용 질문
- 추가 질문(followUpQuestions)
[
{
"categories": [
"market_analysis",
"risk_factors",
"scenario_prediction"
],
"coreIntent": "최근 경제 상황에 대한 정보를 파악하고, 시장 흐름 및 리스크 요인, 향후 시나리오를 이해하고자 함. 사용자는 경제 전반에 대한 통찰력을 원하고 있음.",
"detailMotivations": [
"현재 경제 상황이 주어진 맥락에서 어떻게 움직이고 있는지에 대한 분석 필요",
"리스크 요인에 대한 이해를 통해 투자 또는 소비 결정에 영향을 미치고자 함",
"향후 경제 시나리오에 대한 다양한 예측을 통해 정보 기반의 결정 내리기를 원함"
],
"followUpQuestions": [
"최근 경제 동향이 투자 결정에 영향을 준다고 생각하시나요?",
"리스크 요인(예: 인플레이션, 금리 인상)에 대해 우려하고 계신가요?",
"향후 경제 성장 전망에 대한 예측이 중요하다고 생각하시나요?",
"특정 산업군보다 전체 경제 동향에 더 관심이 있으신가요?",
"정책 변화가 경제 상황에 큰 영향을 미친다고 보시나요?"
]
}
]
Step 5. 사용자의 응답 → Google Sheet에 다시 업데이트(추가 예정)
이제 이 시점에서 사용자 성향을 해석하고,
그에 따라 투자 시나리오를 추천하거나 리스크 인식을 제공하는 구조가 완성된 것.
[
{
"data": {
"최근 경제 동향이 투자 결정에 영향을 준다고 생각하시나요?": [
"Yes"
],
"리스크 요인(예: 인플레이션, 금리 인상)에 대해 우려하고 계신가요?": [],
"향후 경제 성장 전망에 대한 예측이 중요하다고 생각하시나요?": [
"Yes"
],
"특정 산업군보다 전체 경제 동향에 더 관심이 있으신가요?": [
"Yes"
],
"정책 변화가 경제 상황에 큰 영향을 미친다고 보시나요?": []
}
}
]
향후 발전 방향: RAG 기반 시스템으로의 전환
현재 vs 목표 구조
현재 구조 | 목표 구조 |
사용자 질문 → 분석 | 이슈/자료 선택 → 성향 기반 분석 |
질문 중심 | 콘텐츠 중심 |
단방향 분석 | 인터랙티브 분석 |
- 사용자가 먼저 기사/자료/이슈를 선택하거나 업로드
- GPT가 이슈 기반 보완 질문을 생성
- 사용자가 답변
- 이를 기반으로 GPT가 맥락 기반 분석/리스크 진단 수행
→ 이것이 바로 사용자 참여 기반 RAG(정보 검색 기반 생성) 구조의 시작점.
RAG 시스템 전환 계획
1단계: 콘텐츠 우선 접근
- 사용자가 먼저 관심 있는 기사/자료/이슈를 선택
- 선택한 콘텐츠를 기반으로 맞춤형 질문 생성
2단계: 사용자 참여 기반 분석(구현 완료)
- KYC 성향 질문에 대한 응답 수집
- 개인화된 투자 관점으로 콘텐츠 분석
3단계: 맞춤형 인사이트 제공(How?)
- 사용자 성향 + 선택 콘텐츠 기반 종합 분석
- 리스크 요인 및 투자 시나리오 제시
웹 크롤링에 지양 Why?
무분별한 데이터 수집의 문제점
- 시간과 비용 대비 효과 미미
- 사용자 니즈와 무관한 정보 과부하
- 분석 품질 저하 위험
선별적 콘텐츠 큐레이션의 중요성
- 사용자 관심도가 높은 자료 우선 선별
- 사용자 선택 → GPT 분석 순서로 진행
- 명확한 맥락 하에서 정확한 분석 제공
❓ 다음 단계에서 고민 중인 점들
오늘 구현한 시스템은 단순한 Slack 봇을 넘어서, 사용자의 초기 질문과 후속 성향 분석을 유기적으로 연결하는 KYC 기반 RAG 분석 프레임워크의 핵심 구조를 완성한 것이다.
이번 구조는 질문 → 성향 분석 → 맞춤형 답변이라는 기본 흐름을 잘 정리해줬다.
이제는 여기에 아래 세 가지를 더하면서, 시스템을 실제 '서비스'처럼 다듬어야 할 시점이다.
1. 🔍 RAG 기반 외부 자료 분석 흐름 설계
현재 구조는 사용자가 질문을 먼저 입력하고 흐름이 시작된다.
하지만 진짜 투자자들은 "이 기사, 이 뉴스, 이 정책"을 보고 질문이 생긴다.
전환 방향
- 사용자가 기사/자료를 업로드하거나 선택
- 해당 콘텐츠에서 핵심 정보를 추출(File형태라면, Embedding/VectorDB(Supabase) 활용)
- GPT가 질문을 생성하고 사용자의 성향을 기반으로 대답을 맞춤화
- 이 흐름을 통해 'RAG 구조'의 자연스러운 인터페이스가 만들어진다
2. 📊 사용자별 분석 히스토리 추적 시스템
지금은 질문/선택 응답이 Google Sheet에 저장되는 수준이지만,
이를 기반으로 사용자 개인별 투자 성향 변화, 분석 히스토리, 추천 트렌드 등을 추적하고 싶다.
이후 대시보드까지 만들 수 있다면....
고려 중인 흐름
- userId를 기준으로 질문/응답/GPT 결과를 누적 기록
- 결과 기반으로 다음과 같은 데이터 시각화가 가능
- 자주 묻는 섹터/이슈(카테고리 분할 필요)
- 위험 성향의 변화 추이(DB 구성 필요)
- 디테일 분석 vs 요약 분석 선호 비율(구현 예정)
- 히스토리는 슬랙 명령어(/history)로 확인하거나
외부 대시보드(예: Google Looker Studio, Notion DB 연동 등)로 확인 가능하게 설계
기술적 포인트
- 현재 Google Sheet 기반 저장 구조에서 RDB 또는 Firebase 수준으로 이관 필요 여부
- GPT 응답 요약을 저장할지, 원문 전체를 저장할지
- Slack 메시지와 분석 히스토리를 어떻게 연결할 것인지 (메시지 링크 포함 등)
'Automation Tool > n8n Project' 카테고리의 다른 글
Sense Stock, D+11 (1) | 2025.06.26 |
---|---|
Sense Stock, D+10 (0) | 2025.06.24 |
Sense Stock 개발 회고, 첫 번째 (0) | 2025.06.20 |
Sense Stock, D+8 (0) | 2025.06.19 |
Sense Stock, D+7 (0) | 2025.06.18 |
댓글