📅 Sense Stock 개발 일지 (2025-09-01)
n8n, 사용자 질의 기반 경제/시장/주식 분석 자동화 파이프라인 구축 중 진행한 작업들을 정리합니다.
오늘은 구조 개선 작업을 정리했습니다.
한동안 블로그 글이 뜸했는데, 사실 지난주부터 ERR_NGROK_727 에러 때문에 개발 환경에 접속조차 못 하고 있었다. Webhook 테스트를 위해 무료 Ngrok을 사용하고 있는데, 갑자기 분당 요청 수 제한(HTTP Request Limit)에 걸려버린 것이다.
이전에는 한 번도 이런 적이 없었는데, 정책이 바뀌었는지 아무것도 할 수가 없었다.
유료 플랜을 써야 하나.... 일단 다른 문제들부터 해결하기로 마음먹었다.
❓ 지난번 고민
- Data Search 노드의 결과값 분리
현재는 기업과 매칭되는 데이터를 'context'라는 하나의 키에 전부 담아서 추출(Output)하고 있다. 앞으로 프롬프트에서 '기업 개요', '최신 뉴스'처럼 필요한 정보만 개별로 참조할 수 있도록, 결과값을 명확히 구분해서 추출하는 구조로 변경해야 한다.
✔문제 및 해결
- Data Search 노드 결과값 분리
모든 정보를 context 하나에 담아 반환하던 구조에서, 기업 개요, 최신 뉴스 등 목적에 맞게 데이터를 분리하여 반환하도록 변경했다.
더보기
Output(코드 장문 주의)
- 빈값을 가져오는 부분이 있는데
1. Sector Performance, 해결
- 섹터명이 달라서 매칭이 안돼서 값을 못 가져옴
2. Tesla 주당순이익, 해결
- Sheet에 함수가 적용되지않았어서 값을 못 가져옴
3. Earning
- 관련 실적이 없다면 빈값을 내놓음, 정상
[
{
"companies": [
"Tesla",
"Ford",
"General Motors",
"NIO",
"Rivian"
],
"stockPerformance": {
"daily": [
{
"row_number": 3,
"종목명": "General Motors",
"종가": 58.28,
"고가": 58.42,
"저가": 57.88,
"변동": -0.1,
"변동률": -0.0016,
"거래량": "3.77M",
"티커": "GM",
"섹터명": "Consumer Discretionary",
"평균거래량": "9.28M",
"총 시가": "55.55B",
"매출": "187.60B",
"주가수익비율": 9.2,
"주당순이익": 6.3348
},
{
"row_number": 11,
"종목명": "Ford Motor",
"종가": 11.79,
"고가": 11.85,
"저가": 11.68,
"변동": 0.05,
"변동률": 0.0038,
"거래량": "44.55M",
"티커": "F",
"섹터명": "Consumer Discretionary",
"평균거래량": "81.59M",
"총 시가": "47.04B",
"매출": "185.25B",
"주가수익비율": 14.87,
"주당순이익": 0.7929
},
{
"row_number": 330,
"종목명": "Tesla",
"종가": 346.53,
"고가": 349.53,
"저가": 335.03,
"변동": 6.52,
"변동률": 0.0192,
"거래량": "84.94M",
"티커": "TSLA",
"섹터명": "Consumer Discretionary",
"평균거래량": "100.4M",
"총 시가": "1.12T",
"매출": "92.72B",
"주가수익비율": 190.88,
"주당순이익": ""
}
],
"weekly": [
{
"종목명": "General Motors",
"일간": "-0.16%",
"주간": "+3.65%",
"월간": "+9.14%",
"YTD": "+9.40%",
"1년": "+19.55%",
"3년": "+48.56%"
},
{
"종목명": "Ford Motor",
"일간": "+0.38%",
"주간": "+2.88%",
"월간": "+2.79%",
"YTD": "+21.01%",
"1년": "+7.83%",
"3년": "-18.46%"
},
{
"종목명": "Tesla",
"일간": "+1.92%",
"주간": "+3.39%",
"월간": "+9.64%",
"YTD": "-14.19%",
"1년": "+62.53%",
"3년": "+20.29%"
}
]
},
"sectorInfo": {
"relatedSectors": [
"Consumer Discretionary"
],
"performance": {
"daily": [],
"weekly": [
{
"섹터명": "Consumer Cyclical",
"Perf Week": "1.21%",
"Perf Month": "2.52%",
"Perf Quart": "9.70%",
"Perf Half": "6.29%",
"Perf Year": "21.14%",
"Perf YTD": "4.67%",
"Recom": "1.84",
"Avg Volume": "1.45B",
"Rel Volume": "0.85",
"Change": "-0.20%",
"Volume": "1.24B"
}
]
}
},
"earnings": [],
"originalRequest": "테슬라 알려줘"
}
]
- Google Sheet 노드 인증 방식 변경
주기적으로 인증이 풀리던 OAuth 방식에서 Service Account 방식으로 모두 전환했다. - S&P500 섹터명 표준화
Wikipedia에서 동적으로 가져오던 섹터명을 미리 정의된 고정 값으로 변경하여 데이터 일관성을 확보했다.
<고정 섹터명>
Basic Materials | Communication Services | Consumer Cyclical | Consumer Defensive | Energy |
Financial | Healthcare | Industrials | Real Estate | Technology |
Utilities |
<위키피디아 다른 섹터명>
- Consumer Cyclical(경기 소비재), Consumer Staples는 Consumer Defensive(필수 소비재)
Consumer Discretionary -> Consumer Cyclical
Consumer Staples -> Consumer Defensive
Financials -> Financial
Health Care -> Healthcare
Information Technology -> Technology
Materials -> Basic Materials
🗂 데이터 또는 작업 흐름 정리
개선된 Data Search 노드의 작업 흐름은 다음과 같다.
- 사용자가 특정 기업의 정보(예: '최신 뉴스')를 요청한다.
- Data Search 노드가 요청에 해당하는 데이터를 외부 소스에서 가져온다.
- 기존에는 모든 정보를 context 키에 통합해서 저장했지만, 이제는 개별 키에 나누어 저장한다.
- 최종적으로 분리된 데이터가 담긴 JSON 객체를 다음 노드로 전달하여, 프롬프트에서 필요한 정보만 명확하게 참조(진행예정)
🧠 진행 중 고민한 점들
- Ngrok 사용 지속 여부
가장 큰 고민거리이다. 무료 버전의 요청 제한이 너무 강력해져서 개발 테스트가 거의 불가능한 수준이다. 월 결제를 하고 유료 플랜으로 전환할지, 아니면 Cloudflare Tunnel 같은 다른 무료 대안을 찾아봐야 할지 계속 고민 중이다. - 데이터 필드 표준화
현재는 각 데이터 소스마다 사용하는 필드명이 조금씩 다르다. 장기적으로는 어떤 데이터가 들어오든 내부적으로 표준화된 필드명(e.g., publication_date -> publishedAt)으로 한번 정제하는 과정이 필요하지 않을까 생각한다.
오랜만에 접속해서 묵혀뒀던 문제들을 해결하니 속이 다 시원하다. 특히 매주 말썽을 부리던 구글 시트 인증 문제가 드디어 해결되어서 마음이 놓인다. 하지만 Ngrok이라는 더 큰 산이 남아있어서 마냥 기뻐할 수만은 없는 상황이다.
❓ 다음 단계에서 고민 중인 것들
- Best Keyword Extract 프롬프트 수정 질문의 '유효성 검사' 기능을 별도의 Agent로 분리했기 때문에, 기존 Agent의 역할을 재정의해야 한다. 이제 이 Agent는 유효성 검사 없이, 이미 검증된 질문에서 순수하게 핵심 키워드를 추출하는데만 집중하도록 프롬프트를 수정할 필요가 있다.
- JSON 형태
- 해당 자료를 바탕으로 콘텐츠 제작(블로그, Youtube 숏츠, 인스타 스토리 및 게시물)
- 기업/섹터 변동률 전부, 실적/경제발표 데이터 전부
- 해당 데이터 기반 설명 추가가
- JSON 형태
- Keyword Parsing Node 에러 Best Keyword Extract Agent에서 결과값이 정상적으로 나왔음에도, 바로 다음 노드인 Keyword Parsing Node에서 에러가 발생하고 있다. 두 노드 사이에 오고 가는 데이터의 형식이 맞지 않는 것으로 추정됨.
- Best Keyword Extract Agent, 프롬프트 변경(Output 고정)
// Fail
// 'json'으로 감싸져있다.
[
{
"output": "`json\\n{\\n \\"analysis_plan\\": {\\n \\"question_type\\": \\"direct_company\\",\\n \\"answer_type\\": \\"in-depth_company_analysis\\"\\n },\\n \\"derived_data\\": {\\n \\"request\\": \\"테슬라 알려줘\\",\\n \\"inferred_companies\\": [\\n \\"Tesla\\",\\n \\"Ford\\",\\n \\"General Motors\\",\\n \\"NIO\\",\\n \\"Lucid Motors\\"\\n ],\\n \\"inferred_tickers\\": [\\n \\"TSLA\\",\\n \\"F\\",\\n \\"GM\\",\\n \\"NIO\\",\\n \\"LCID\\"\\n ],\\n \\"related_keywords\\": [\\n \\"전기차\\",\\n \\"배터리 기술\\",\\n \\"자율주행\\",\\n \\"재생 에너지\\",\\n \\"친환경 이동수단\\"\\n ]\\n }\\n}\\n`"
}
]
// Success
[
{
"output": "{\n \"status\": \"success\",\n \"analysis_plan\": {\n \"question_type\": \"industry_theme\",\n \"answer_type\": \"theme_based_company_analysis\"\n },\n \"derived_data\": {\n \"request\": \"AI 행보\",\n \"inferred_companies\": [\n \"NVIDIA\",\n \"AMD\",\n \"Intel\",\n \"Broadcom\",\n \"Qualcomm\"\n ],\n \"inferred_tickers\": [\n \"NVDA\",\n \"AMD\",\n \"INTC\",\n \"AVGO\",\n \"QCOM\"\n ],\n \"related_keywords\": [\n \"GPU\",\n \"Data Center\",\n \"Foundry\",\n \"Semiconductor Fabless\",\n \"AI Chip Market\"\n ]\n }\n}"
}
]
- 실시간(Chat Streaming)을 답변 기능 확인
'Automation Tool > n8n Project' 카테고리의 다른 글
Sense Stock, D+25 (3) | 2025.08.24 |
---|---|
Sense Stock, D+24 (5) | 2025.08.14 |
💣 프로젝트 트러블슈팅 및 삽질 기록 (4) | 2025.08.12 |
Sense Stock 개발 회고, 세 번째 (3) | 2025.08.12 |
Sense Stock, D+23 (2) | 2025.08.11 |
댓글