AI 자동매매 시스템 만들기 #6 - 예외처리시간! (LLM 환각, WebSocket 재연결, API 비용 최적화)

2026. 2. 12. 15:37·일상다반사/개발

문제 1: LLM이 JSON 대신 마크다운을 뱉어버렸다

AI 분석이 간혹 가다 실패하기 시작했습니다. JSON을 달라고 했는데 마크다운으로 답변하고 있었습니다.

원인 분석

Qwen3 14B 모델은 "thinking 모드"를 지원합니다. 사고 과정을 <think>...</think> 태그 안에 쓰고, 그 다음에 JSON 응답을 줍니다. 그런데 간헐적으로 JSON 대신 마크다운으로 응답하는 경우가 생겼습니다.

해결: 정규표현식 폴백 파서

JSON 파싱 실패 시 마크다운에서 직접 데이터를 추출하는 폴백 로직을 추가했습니다. 정규표현식으로 "추천: BUY", "신뢰도: 75%" 같은 패턴을 찾아서 JSON으로 변환합니다.

JSON 파싱 성공률이 82% → 98%로 올라갔습니다.

문제 2: LLM 환각으로 감시 종목 절반을 매칭해버림

"반도체 업황 호조" 같은 일반적인 뉴스에 감시 종목 30개 중 12개를 매칭했습니다. 명백한 환각(hallucination)입니다.

원인 분석

LLM은 "반도체 업황"이라는 단어만 보고 반도체와 간접적으로라도 연관된 모든 종목을 매칭했습니다. 심지어 금융주까지 포함했죠 (반도체 주가 상승 → 코스피 상승 → 금융주 수혜라는 논리).

해결 방법

1. 프롬프트에 엄격한 규칙 추가: "직접 언급" 또는 "핵심 사업 연관"만 허용

2. 환각 탐지 로직: 감시 종목의 절반 이상 매칭되면 전체를 버림

if (matched.size > watchStocks.size / 2 && matched.size > 3) {
    logger.warn { "LLM 매칭 환각 감지 → 전체 무시" }
    return emptyList()
}

 

각 사례가 유의미하게 감소했습니다.

문제 3: Tavily URL 크롤링이 사이드바까지 긁어왔다

기사 주제는 "삼성전자 HBM 수주"인데 SK텔레콤, 현대차까지 매칭됐습니다.

원인 분석

Tavily는 URL의 전체 본문을 추출하는데, 뉴스 사이트의 사이드바, 관련 기사, 광고까지 포함됩니다. 전체 텍스트에서 종목명을 찾으니 관련 없는 종목까지 매칭됐습니다.

해결 방법

기사 본문은 대부분 앞쪽에 있습니다. 앞 1500자만 사용하도록 수정:

val allContent = extracts.joinToString(" ") {
    (it.rawContent ?: "").take(1500)  // 본문 앞부분만
}

 

TAVILY 매칭 정확도가 일부 상승했습니다.

문제 4: Mock 모드 WebSocket 실패 시 장 상태를 모르게 됨

개발 환경에서 Mock WebSocket이 실패하면 실제 장이 열려있어도 거래를 안 합니다.

해결 방법: 시간 기반 Fallback

WebSocket 실패 시 현재 시간으로 장 상태를 추정:

  • 1순위: WebSocket 실시간 상태
  • 2순위: 시간 기반 추정 (평일 09:00-15:30)

개발 환경에서 WebSocket 없이도 거래 테스트가 가능해졌습니다.

문제 5: Brave 검색 크레딧을 허공에 날려버림

Brave Search API는 유료입니다(월 2,000회 무료). 그런데 "코스피 장 마감", "달러 환율" 같은 일반 시황까지 검색하고 있었습니다.

해결 방법: LLM으로 검색 가치 판단

Brave 검색 전에 LLM으로 "검색할 가치가 있는가?"를 먼저 판단:

data class BraveQueryRefinementResult(
    val worthSearching: Boolean,
    val searchQuery: String,
    val reason: String
)

 

LLM이 worthSearching=false를 반환하면 검색을 스킵합니다.

요약: 실전 운영에서 배운 교훈

  1. LLM은 확률적 모델 → 다양한 출력 포맷 허용하는 견고한 파서 필요
  2. LLM 환각 대비 → 프롬프트 엔지니어링 + 코드 검증 병행
  3. Reactive Streams retry → retryWhen()으로 정교한 제어 + 전역 카운터 관리
  4. 웹 크롤링 노이즈 제거 → 앞부분만 사용, 도메인 지식 활용
  5. 외부 시스템 의존도 낮추기 → 시간 기반 Fallback 전략
  6. API 비용 절감 → 호출 전 LLM으로 가치 판단

 

반응형
저작자표시 비영리 (새창열림)
'일상다반사/개발' 카테고리의 다른 글
  • AI 자동매매 시스템 만들기 #5 - RAG로 AI에게 기억력을 주다(pgvector)
  • AI 자동매매 시스템 만들기 #4 - AI가 실제로 판단하는 방법
  • AI 자동매매 시스템 만들기 #3 - 키움증권 API 연동과 실전 거래
  • AI 자동매매 시스템 만들기 #2 - 채널 모니터링과 5단계 매칭 시스템
Kua
Kua
정보 공유, 개인 정리 공간 입니다.
  • Kua
    Kua's Miscellaneous
    Kua
  • 전체
    오늘
    어제
    • 분류 전체보기 (192) N
      • 대문 (2)
      • Tips (1)
        • Chrome (2)
        • Windows (4)
        • IDE (3)
        • 기타 (16)
      • CodingTest (44)
      • Language (20)
        • PHP (5)
        • C# (7)
        • Java (1)
        • Kotlin (7)
      • Framework & Runtime (16)
        • SpringBoot (12)
        • Node.js (2)
        • Vue.js (1)
        • Gradle (1)
      • DevOps (13)
        • Linux (1)
        • Docker (4)
        • Kubernetes (2)
        • Apache Kafka (1)
        • AWS (1)
      • 일상다반사 (59) N
        • 도서 (1)
        • 개발 (14) N
        • 후기 - IT (7)
        • 후기 - 일상 (13)
        • 차가리 (4)
        • 방송통신대학교 (4)
        • 음식 (2)
      • Games (12)
        • Minecraft (7)
        • VR (2)
        • 그외 (3)
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
Kua
AI 자동매매 시스템 만들기 #6 - 예외처리시간! (LLM 환각, WebSocket 재연결, API 비용 최적화)
상단으로

티스토리툴바