AI에게 투자정보를 말하게 하기까지
안녕하세요, 토스증권 Machine Learning Engineer 정현규입니다.
LLM으로 콘텐츠를 만드는 일은 확실히 쉬워졌어요. 뉴스를 요약하고, 공시를 풀어 쓰고, 실적 발표를 자연스러운 문장으로 옮기는 건 이제 몇 줄의 프롬프트로도 어느 정도 됩니다.
그런데 그 결과물을 고객이 보는 투자 정보로 내보내려고 하면 질문이 완전히 달라져요.
토스증권은 ML과 LLM 기술을 활용하여 금융투자 정보 서비스를 만들고 있어요. 종목·ETF·주요 시장의 움직임을 설명하는 AI 시그널, 지금 시장에서 벌어지는 이벤트가 어떤 산업·기업과 연결되는지 짚어주는 실시간 이슈, 기업 실적 발표를 실시간으로 번역하고 요약하는 어닝콜, 경제 지표와 주요 일정을 정리해주는 AI 증시 캘린더를 만들고 있죠.
이 서비스들을 만들면서 공통적으로 마주친 문제가 있었고, 그 문제를 풀다 보니, AI가 말하기 전에 통과해야 할 세 개의 관문을 세우게 됐어요. 이 글은 그 관문에 대한 이야기예요. 모델링 자체보다는, ‘모델이 입을 열기 전과 후에 무슨 일이 일어나야 하는지’에 대한 이야기입니다.

투자 정보는 일반적인 요약과 무엇이 다를까요
먼저 이 도메인이 왜 까다로운지부터 짚고 갈게요. 네 가지 특징으로 정리할 수 있어요.
적시성 (Timeliness). 시장 정보는 타이밍이 전부에 가까워요. 늦게 설명하면 가치가 떨어지는 정도가 아니라, 틀린 정보가 되기도 합니다. 변동성이 큰 국면에서는 오전의 설명과 오후의 설명이 정반대인 순간도 있어요. 지정학 이슈의 휴전 소식 하나로 하루 만에 시장의 해석이 뒤집히는 걸 여러 번 봤습니다.
정확성 (Accuracy). 뉴스 기사에 회사 이름이 등장한다고 해서 그 회사의 주가 움직임을 설명하는 근거가 되지는 않아요. 자회사 이야기일 수도 있고, 이름이 비슷한 다른 기업일 수도 있고, 단순 홍보성 기사일 수도 있죠. 이름이 비슷한 기업을 구별하지 못하면 엉뚱한 종목의 주가를 설명하게 됩니다.
검증 가능성 (Traceability). 투자 정보는 사용자가 아주 민감하게 받아들이는 정보예요. 그래서 모델이 말한 모든 결과에 대해 근거를 남기고, 평가하고, 문제가 생겼을 때 재현 가능하도록 추적할 수 있어야 해요.
비정상성(Non-stationarity). 금융 시장은 늘 같은 데이터 분포로 움직이지 않아요. 실적 시즌, 금리 이벤트, 지정학 이슈, 선거 시즌마다 데이터의 성격이 달라집니다. 똑같은 애널리스트 의견 변경 소식이라도 실적 시즌이냐 아니냐에 따라 주가에 미치는 영향이 다르죠. 그래서 특정 기간의 데이터로 튜닝한 프롬프트와 모델이 앞으로도 잘 동작하리라고 가정할 수 없어요.

여기에 LLM과 에이전트의 특성이 겹치면
LLM은 비정형 정보를 이해하고 자연어로 재구성하는 데 강해요. 뉴스·공시·실적 발표처럼 형식이 제각각인 텍스트를 다룰 때 이만한 도구가 없죠.
하지만 LLM은 결국 주어진 맥락을 바탕으로 통계적으로 그럴듯한 응답을 생성하는 모델이에요. 정보가 부족하거나, 불분명한 근거가 섞여 있거나, 질문이 애매하면 유창하지만 틀린 답을 만들어냅니다. 같은 정보라도 어떤 순서로 배치했는지, 어떤 예시를 넣었는지, 어떤 출력 형식을 요구했는지에 따라 판단이 달라지고요.
자율성이 큰 에이전트 구조로 가면 이 불확실성의 표면적이 더 넓어져요. 에이전트는 목표를 하위 작업으로 나누고, 도구를 고르고, 실행 결과를 보고 다음 행동을 정합니다. 탐색형 업무나 사람이 곁에서 확인할 수 있는 내부 생산성 도구에는 아주 강력한 구조예요. 하지만 고객에게 곧바로 전달되는 투자 정보에서는 이야기가 다릅니다.
- 검색 단계에서 잘못된 근거를 가져오거나
- 툴 콜(Tool-Call) 결과를 잘못 해석하거나
- 이전 단계의 잘못된 상태가 다음 판단의 근거로 쓰이는
오류가 그대로 전파돼요. 그것도 매번 다른 경로로요. 물론 이런 경로(Trajectory)를 검증하고 최적화할 순 있지만, 실 서비스에서는 운영에서의 비용도 고려해야했어요.
그래서 문제를 다시 정의했어요.
금융 AI 서비스의 핵심은 생성 전에 어떤 근거를 선별하고, 어떻게 검증하며, 운영 중에 어떻게 관찰하고 개선할 것인가가 더 중요하다.
LLM과 에이전트의 능력은 쓰되, 어떤 자율성을 열어두고 어떤 자율성을 닫을지를 설계해야 한다는 뜻이에요. 그 설계가 세 개의 관문이 됐습니다.
첫 번째 관문. 무엇을 말할지 고르기
특정 기업의 주가가 움직였을 때 그 이유를 찾는 태스크를 예로 들어볼게요. 원천 데이터에서 시작해 LLM의 최종 입력값이 되기까지의 과정이에요.

입수 시점에 이미 분류를 끝내둬요
뉴스·공시·재무 같은 원천 데이터는 데이터를 입수하는 시점에 BERT 기반 분류 모델로 자체 설계한 분류 체계에 맞춰 메타데이터를 붙여둡니다. 검색할 때 분류하는 게 아니라, 들어올 때 이미 분류된 상태로 쌓아두는 거예요.
뉴스 데이터라면 제목과 본문 외에 이런 것들이 함께 붙어요.

NewsItem
├─ title
├─ content
├─ taxonomy_tags # 한국 주식 / 애널리스트 분석 / 기술 트렌드 ...
├─ related_entities # 이 기사와 연결된 기업
└─ embedding # 벡터 서치용기사 내용을 보고 이게 한국 주식에 관련된 건지, 애널리스트 분석인지, 기술 트렌드를 말하는 건지 분류하고, 어떤 기업과 관련되어 있는지를 붙이고, 이후 벡터 서치를 위한 임베딩까지 만들어 둡니다.
넓게 가져온 다음, 좁혀요
그 다음은 하이브리드 리트리버(Hybrid Retriever)로 후보를 넓게 가져와요. 리트리브 단계의 목표는 Recall이거든요. 대신 이 시점의 후보에는 중복된 정보, 오래된 기사, 지금의 등락과 반대되는 설명이 섞여 있습니다.
그래서 세 단계로 좁혀요.
중복 제거. 의미 기반 유사도로 클러스터링해서 같은 이벤트를 하나로 묶고, 클러스터마다 대표 원천만 남깁니다. 같은 뉴스가 열 군데에 실렸다고 해서 그 이벤트가 열 배 중요한 건 아니니까요.
리랭킹과 필터링. 특정 기업의 움직임을 설명하는 데 얼마나 직접적인 근거인지를 기준으로 후보를 재정렬해요. 이때 단순히 순위만 매기지 않고, 주요 설명 패턴 택소노미 중 어디에 해당하는지를 함께 분류합니다. 실적인지, 가이던스인지, 기업 행동인지 같은 것들이죠. 동시에 실패 사유 택소노미도 붙여요. 광고·홍보성인지, 근거가 부족한지 같은 라벨입니다. 이 라벨이 그대로 필터 역할을 해요. 그리고 어떤 근거가 더 중요한지는 루브릭(Rubric)으로 정의해서 관련도 순으로 정렬합니다.

컨텍스트 정렬. 마지막은 살아남은 근거를 LLM이 읽기 좋은 순서로 배치하는 일이에요. 저희는 모델이 다음 순서로 점검하게 만들고 싶었어요.

그래서 식별 대상에 대한 설명, 필터링된 근거 맥락, 주가 움직임의 방향성과 시점 같은 메타 정보를 이 점검 순서대로 배치합니다. 리즈닝 친화적인 컨텍스트(Reasoning-Friendly Context)를 만드는 게 목적이에요.
정리하면 첫 번째 관문은 LLM에게 보여줄 정보를 압축하고, 비즈니스 요구사항이 반영되도록 배치하는 컨텍스트 엔지니어링(Context Engineering) 단계입니다.
두 번째 관문. 어떻게 생성할지 통제하기
LLM과 에이전트의 능력이 커질수록 관리해야 할 지점도 함께 늘어난다고 말씀드렸죠. 두 번째 관문은 그 지점을 제품 요건에 맞게 통제하는 일이에요.


멀티 에이전트 구조는 툴 콜링(Tool Calling)과 플래닝(Planning)이 붙으면서 확장성이 커집니다. 대신 실행 경로와 실패 지점도 같이 늘어나요. 투자 정보 서비스에서 이 넓은 액션 스페이스를 그대로 열어두기에는 비용과 리스크가 큽니다. 근거를 남겨야 하고, 재현 가능해야 하고, 레이턴시(Latency)와 비용을 예측해야 하고, 문제가 생겼을 때 어느 단계에서 실패했는지 바로 찾을 수 있어야 하거든요.
그래서 서비스 요건에 따라 태스크 그래프를 설계해요. 후보 검색 → 관련성 판단 → 중복 제거 → 근거 구성 → 최종 응답 생성처럼 단계마다 역할을 나누고, 각 단계의 입력과 출력 스키마를 정의합니다. 이렇게 하면 각 단계가 디버깅 포인트이자 평가 포인트가 되고, 운영에서 비용·속도·폴백(Fallback)을 설계하기도 쉬워져요.
판단 기준은 "요건이 얼마나 명확한가"였어요
에이전트 구조를 어떻게 가져갈지 정하려면, 먼저 서비스 요건이 얼마나 명확한지를 정의해야 했어요.
자율형 에이전트가 잘 맞는 경우는 문제 정의가 열려 있고 탐색 과정 자체에 가치가 있을 때예요. 투자 아이디어를 발굴하거나, 특정 이벤트가 시장에 미칠 잠재 시나리오를 탐색할 때는 에이전트가 스스로 계획을 세우고 툴을 고르는 능력이 유용합니다. 정답이 하나로 정해져 있지 않고, 여러 관점에서 넓게 보는 게 중요한 문제니까요.
절차형 오케스트레이션이 유리한 경우는 응답 요건이 명확할 때입니다. 특정 기업의 주가 등락을 설명하는 태스크는 후보를 제한하고, 관련도를 판단하고, 방향성과 연결성을 확인하고, 중복을 제거하고, 근거를 정렬한 뒤, 정해진 형식으로 설명해야 해요. 여기서 필요한 건 넓은 탐색 능력이 아니라 반복 가능한 실행 경로입니다.
ReAct 루프를 길게 돌리면 툴 콜, 토큰 사용량, 레이턴시(Latency)가 늘어나고 실행 경로가 매번 달라져서 관리할 트레이스(Trace)도 많아져요. 제품이 요구하는 판단 경로가 이미 정해져 있다면, 필요한 노드만 남긴 절차형 그래프가 오버엔지니어링을 피하는 선택이었습니다.
그래서 응답 요건이 구체적인 제품에서는 LLM이 직접 툴 콜을 하기보다, 검색·분류·검증·평가 같은 기능을 정해진 절차로 조합하고 LLM은 요약, 재작성, 근거 기반 설명에 집중시키는 방식이 훨씬 현실적이었어요.
그런데 여기서 배운 게 하나 있어요
절차형 오케스트레이션은 자율형 에이전트의 반대편에 있는 구조가 아니었어요.
비용과 운영 안정성 때문에 절차형으로 고정했지만, 잘 정의된 절차형 그래프는 나중에 다른 에이전트가 호출할 수 있는 기능 인터페이스가 됩니다.
예를 들어 "특정 기업의 움직임 이유를 설명한다"는 그래프는 이런 호출 단위가 돼요.

input: { ticker, direction, time_window }
process: 검색 → 관련성·방향성 판단 → 중복 제거 → 근거 정렬 → 설명 생성
output: { explanation, evidences[], reasoning_type, ... }상위 에이전트나 다른 서비스는 이 복잡한 과정을 매번 직접 계획할 필요가 없어요. 이미 구비된 절차형 에이전트를 호출하고, 그 결과를 다음 추론이나 사용자 응답에 쓰면 됩니다. 이런 단위가 쌓이면 팀 전체가 쓸 수 있는 툴(Tools)·서브 에이전트·MCP 서버 목록이 늘어나고요.
절차형 오케스트레이션은 단기적으로는 운영 안정성을 위한 선택이고, 장기적으로는 에이전트 확장성을 위한 호출 인터페이스입니다. 그래서 저희에게는 절차형 그래프를 만드는 것만큼, 그걸 다른 에이전트가 호출 가능한 형태로 잘 설계하는 일이 중요했어요.
세 번째 관문. 평가 가능한 구조로 만들기
"어쩐지 답이 좀 별로다."
이런 주관적인 평가로는 개선할 수 있는 게 없어요. 개선하려면 산출물이 평가 가능한 형태여야 합니다.
여기서 핵심은 자연어 생성 태스크라고 해서 자연어만 생성할 이유는 없다는 점이에요.
범주형 루브릭을 함께 생성하게 했어요
저희는 태스크마다 범주형 루브릭(Rubric)을 설계하고, LLM이 답변과 함께 그 분류값을 내놓게 했어요. 리즈닝 타입 같은 주요 이벤트 분류 체계를 정의해 분류하게 하고, 반대로 필터링 대상이 되는 실패 사유 분류 체계도 함께 분류하게 합니다.

이렇게 하면 "요약이 좋아 보인다"로 끝나지 않고, 생성 결과 안에 평가 가능한 구조화 필드가 남아요. 그러면 질문이 바뀝니다.
정밀도, 재현율, F1-Score 등 으로 어느 방향으로 개선할 수 있을지 측정할 수 있게 되죠.
그리고 앞서 말한 비정상성 때문에, 이 분류 체계는 한 번 정하면 끝이 아니에요. 실적 시즌, 지정학 이벤트, 정책 변화처럼 국면이 바뀌면 주요하게 봐야 할 실패 유형과 이벤트 유형도 달라집니다. 국면마다 분류 체계가 추가될 수 있어야, 운영에서 새로 발견한 실패 유형이 다음 평가셋과 프롬프트 예제(Few-shot prompt)로 연결돼요.
운영에서 발견된 문제, 평가셋, 프롬프트 버전, 모델 버전이 함께 연결되어야 같은 문제를 반복해서 겪지 않고 개선 효과를 수치로 확인할 수 있습니다.
고정 Few-Shot 대신, 맥락에 맞는 Few-Shot Retrieval
이 피드백 루프를 실제 제품에 적용한 방법을 하나 소개할게요.
퓨샷은 보통 프롬프트에 고정으로 넣습니다. 그런데 투자 정보 태스크에서는 설명 가능한 이벤트 유형도(실적 발표, 애널리스트 의견, R&D 이슈…) 실패 유형도 너무 다양해요. 고정된 몇 개로는 전체 분포를 대표할 수 없었습니다. 시장 국면이 바뀌면 과거에 잘 동작하던 예시가 덜 유효해지고, 지금 태스크와 관련 없는 예시가 들어가 컨텍스트만 낭비하기도 하고요.
그래서 지금 들어온 판단 문제와 가장 비슷한 과거 사례를 맥락에 맞춰서 가져오는 방식으로 바꿨어요.
잘된 예시와 잘못된 예시를 나란히 넣으면, 모델이 판단의 경계면을 볼 수 있어요. 운영에서 발견된 실패 사례가 다음 판단의 기준으로 재사용되는 구조이기도 하고요.
고정 퓨샷이 시험 전에 정답지 몇 개를 외워 가는 것이라면, 퓨샷 리트리빙은 지금 풀 문제와 가장 비슷한 오답 노트를 옆에 펼쳐 놓고 문제를 푸는 것에 가깝습니다.
결과
특정 종목의 움직임을 잘 설명하는지 연관성을 검증하는 태스크에 적용해봤어요. 재현율은 유지하면서 정확도와 정밀도가 크게 개선됐습니다.

투자 정보 서비스에서는 False-Positive가 특히 중요해요. 설명할 수 없는 정보를 설명 가능한 것처럼 통과시키면, 뒷단에서 아무리 문장을 잘 만들어도 전체 품질이 흔들리니까요.
여기서 얻은 인사이트는 단순했어요. 유사한 내용의 퓨샷을 가져오면 검증 성능이 올라간다.
프롬프트와 학습 바깥의 일
LLM 서비스라고 하면 프롬프트나 모델 학습을 먼저 떠올리기 쉬워요. 물론 중요합니다. 그런데 투자 정보 제공으로써 운영까지 고려하게 되면 프롬프트와 학습 바깥의 일이 훨씬 많았어요.
특히 운영에서 발견된 문제를 평가와 개선으로 되돌리는 장치가 없으면, 서비스 품질은 결국 사람의 감에 의존하게 됩니다.
그래서 ML, LLM, 리트리버, 데이터, 서빙, 운영 시스템을 함께 설계하고 오케스트레이션(Orchestration)하는 일이 AI 서비스 엔지니어링의 핵심이었어요.
정리하며
지속 가능한 AI 서비스는 좋은 문장이 아니라 분해 가능한 판단을 남깁니다. 생성 결과만 남기지 않고 관련도, 방향성, 이벤트 타입, 실패 유형처럼 다시 평가할 수 있는 필드를 함께 남길 때 개선이 가능했어요.
에이전트의 자율성은 기능이 아니라 비용·지연 시간·책임 범위를 함께 갖는 설계 변수입니다. 자율형이 잘 맞는 문제도 분명히 있지만, 절차가 명확하고 고객에게 바로 노출되는 투자 정보에서는 액션 스페이스를 줄이는 편이 운영과 품질 모두에 이로웠습니다.
실패 사례는 비용이 아니라 도메인 데이터입니다. 운영에서 나온 실패 케이스를 그냥 이슈로 닫지 않고 평가셋과 하드 샘플 퓨샷(Hard-Sample Few-shot)으로 되돌리면, 그 자체가 개선을 위한 자산이 돼요.
좋은 답변은 생성 단계가 아니라, 말할 수 있는 후보를 만드는 단계에서 절반 이상 결정됩니다. 모델이 아무리 좋아도 입력으로 들어간 근거가 부정확하거나 방향성이 맞지 않으면 좋은 투자 정보가 되기 어려워요.
결국 AI에게 투자 정보를 말하게 한다는 것은, AI가 말해도 되는 상태를 계속 운영하는 일이었습니다.
✅ 이번 아티클은 아래 토스증권 Tech Talk Talk의 세션을 바탕으로 재구성되었습니다.
