본문 바로가기
Automation Tool/n8n Project

Sense Stock, D+26

by 그때 그때 끄적 2025. 9. 1.

📅 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 노드의 작업 흐름은 다음과 같다.

  1. 사용자가 특정 기업의 정보(예: '최신 뉴스')를 요청한다.
  2. Data Search 노드가 요청에 해당하는 데이터를 외부 소스에서 가져온다.
  3. 기존에는 모든 정보를 context 키에 통합해서 저장했지만, 이제는 개별 키에 나누어 저장한다.
  4. 최종적으로 분리된 데이터가 담긴 JSON 객체를 다음 노드로 전달하여, 프롬프트에서 필요한 정보만 명확하게 참조(진행예정)

🧠 진행 중 고민한 점들

  • Ngrok 사용 지속 여부
    가장 큰 고민거리이다. 무료 버전의 요청 제한이 너무 강력해져서 개발 테스트가 거의 불가능한 수준이다. 월 결제를 하고 유료 플랜으로 전환할지, 아니면 Cloudflare Tunnel 같은 다른 무료 대안을 찾아봐야 할지 계속 고민 중이다.
  • 데이터 필드 표준화
    현재는 각 데이터 소스마다 사용하는 필드명이 조금씩 다르다.
    장기적으로는 어떤 데이터가 들어오든 내부적으로 표준화된 필드명(e.g., publication_date -> publishedAt)으로 한번 정제하는 과정이 필요하지 않을까 생각한다.

오랜만에 접속해서 묵혀뒀던 문제들을 해결하니 속이 다 시원하다. 특히 매주 말썽을 부리던 구글 시트 인증 문제가 드디어 해결되어서 마음이 놓인다. 하지만 Ngrok이라는 더 큰 산이 남아있어서 마냥 기뻐할 수만은 없는 상황이다.

 

❓ 다음 단계에서 고민 중인 것들

  • Best Keyword Extract 프롬프트 수정 질문의 '유효성 검사' 기능을 별도의 Agent로 분리했기 때문에, 기존 Agent의 역할을 재정의해야 한다. 이제 이 Agent는 유효성 검사 없이, 이미 검증된 질문에서 순수하게 핵심 키워드를 추출하는데만 집중하도록 프롬프트를 수정할 필요가 있다.
    • JSON 형태
      • 해당 자료를 바탕으로 콘텐츠 제작(블로그, Youtube 숏츠, 인스타 스토리 및 게시물)
      • 기업/섹터 변동률 전부, 실적/경제발표 데이터 전부
        • 해당 데이터 기반 설명 추가가
  • 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

댓글