[고객 사례] Poly Inspiration 경영분석 AI Agent 구축 사례

데이터 웨어하우스의 나무를 자연어기반 BI Agent 숲으로 키우는 방법

DW의 나무를 자연어기반 BI Agent 숲으로 키우는 방법

들어가며 – 사례 소개

Pain Point에서 시작된 프로젝트

폴리 인스퍼레이션 (Poly Inspiration, 이하 PI)은 Poly와 CANB라는 두 브랜드의 전국 규모 교육 기관을 운영하는 기업으로서, 매월 방대한 양의 경영 데이터를 분석하여 의사결정에 활용하고 있습니다.

처음 우리에게 들어온 요청은 “데이터 웨어하우스(DW)를 구축해달라”는 것이었습니다. 흩어져 있는 데이터를 모아 분석할 수 있는 기반을 만들자는 자연스러운 출발이었습니다. 그런데 논의가 깊어질수록, 정작 풀어야 할 진짜 Pain Point는 DW 그 자체가 아니라는 사실이 분명해졌습니다. 가장 먼저 드러난 것은 DW 구축이라는 작업 자체에 따라오는 부담이었습니다.

  • 인력 부담 – 전사 데이터 모델링, 파이프라인 설계, 운영 거버넌스까지 책임질 데이터 엔지니어와 분석가가 지속적으로 필요합니다. 신규 채용도 쉽지 않고, 기존 인력을 빼면 본업이 흔들리는 구조였습니다.
  • 비용 부담 – DW 솔루션 라이선스, 인프라, 그리고 무엇보다 운영 인력 비용이 누적되는 구조입니다. 한 번 짓고 끝나는 것이 아니라 매년 운영비가 따라오기 때문에, 투자 대비 효용을 끊임없이 입증해야 합니다.
  • 시간 부담 – 요건 정의, 데이터 모델 설계, ETL 파이프라인 구축, 검증, 운영 안정화까지 통상 수개월에서 1년 이상이 걸립니다. 그 사이에도 경영진의 의사결정 수요는 계속되지만, DW가 답을 줄 수 있는 시점은 한참 뒤입니다.

그리고 이 부담을 모두 감수하고 DW를 구축한다 해도, 그것만으로 경영진의 의사결정이 빨라지지는 않습니다. 결국 누군가는 여전히 SQL을 작성하고, 결과를 엑셀로 옮기고, 피벗과 인사이트를 정리해 보고서로 다시 만들어야 합니다. 즉, DW는 분석을 위한 “기반”일 뿐, 경영진이 실제로 필요로 하는 “즉시성”은 별도의 레이어가 책임져야 한다는 뜻이었습니다.

  • 경영진 입장에서 필요한 것은 “언제든 묻고 즉시 답을 받는 경험”이지, 새로 만들어진 또 하나의 데이터 시스템이 아니었습니다.
  • 내부적으로도 “DW를 정말 해야 하는가, 한다면 무엇을 위해 하는가” 라는 근본 질문이 떠오른 시점이었습니다.

알파코드의 제안

이 지점에서 우리는 한발 물러서서 다른 길을 제안했습니다. “DW를 더 빠르게 만드는 것”이 아니라, “DW가 결국 풀고자 했던 문제(경영진의 판단을 돕는 일) 를 더 직접적으로 해결하는 방법” 으로 방향을 바꾸자는 것이었습니다. 그 답이 에이전틱 AI 기반 경영분석 플랫폼이었습니다.

현업 담당자나 경영진이 “지난달 신규생 현황 알려줘”처럼 일상 언어로 질문하면, AI Agent가 BigQuery를 직접 조회하고, 결과를 해석하고, 도메인 지식까지 결합해 즉시 답변합니다. 데이터를 모으는 것 자체가 아니라, 데이터로부터 답을 꺼내는 경험을 시스템이 책임지는 구조입니다.

결과적으로 이 프로젝트는 단순한 BI 도구 도입이 아니라, Poly가 가진 “왜 데이터를 모으는가”라는 근본 질문에 대한 답이자, 전사 AX(AI Transformation)의 출발점이 되었습니다.

이 프로젝트에서 풀어야 했던 요구사항은 아래와 같습니다.

  • 자연어 기반 데이터 분석 – SQL 지식 없이도 누구나 분석 가능해야 합니다.
  • 실시간 응답 – 사용자가 분석 과정을 투명하게 확인할 수 있어야 합니다.
  • 도메인 지식 체계화 – 현업의 비즈니스 노하우를 AI가 참조 가능한 조직 자산으로 정리해야 합니다.
  • 멀티 브랜드 지원 – Poly · CANB 등 여러 브랜드를 하나의 시스템에서 운영할 수 있어야 합니다.

이 글은 그 프젝트에서 내린 핵심 기술 결정들을 정리한 사례 소개입니다. 같은 문제를 마주한 다른 팀이 자기 맥락에 맞춰 재구성할 수 있도록 “왜 그렇게 했는가”를 중심에 두었습니다.

시스템 한눈에 보기

Poly Agent는 크게 세 덩어리로 구성됩니다. Next.js 15 기반의 웹 프론트엔드, Node.js/TypeScript로 구현한 Agent 백엔드, 그리고 GCP 위의 인프라 입니다.

사용자 메시지 한 건이 흐르는 경로는 다음과 같습니다.

▲ 사용자 요청이 Browser → Next.js → Poly Agent → Streaming Workflow로 흘러 SSE로 다시 Browser에 도달하는 경로

Agent Core 안에는 6개의 Manager가 있습니다. 각자 한 가지 관심사만 다룹니다 – 세션, 히스토리, 프롬프트, 지식, 툴, 토큰. Streaming Workflow는 LLM <-> Tool 루프를 최대 20회까지 돌리며 청크를 뽑아내고, 이 청크들이 SSE 이벤트 단위로 즉시 브라우저에 흘러갑니다.

이제 이 시스템을 만들면서 내린 핵심 결정 네 가지를 풀어보겠습니다. 각 결정은 같은 형식으로 정리했습니다 – 문제 -> 검토한 옵션 -> 최종 결정.

LangChain 없이, Manager 패턴으로

문제

Agent가 책임져야 하는 관심사는 한둘이 아닙니다. 세션 격리, 대화 히스토리, 브랜드별 프롬프트 주입, 도메인 지식 검색, 툴 실행, 토큰 추적. 그리고 에이전틱 AI 개발은 일반적인 백엔드 개발과 결이 다릅니다.

운영 로그를 보며 프롬프트를 매주 다듬고, 새로운 툴을 더하고, 브랜드별 도메인 지식을 보강하는 사이클이 끊임없이 돌아갑니다.

또한 “왜 이 응답이 나왔는가”를 추적할 수 있어야 하고, Poly · CANB 같은 브랜드별 특수 요구를 자유롭게 얹을 수 있어야 합니다.

따라서 각 관심사를 독립적으로 다룰 수 있고, 동작을 끝까지 들여다볼 수 있으며, 도메인 요구를 유연하게 수용하는 구조가 필요했습니다.

검토한 옵션

  • (a) LangChain · LlamaIndex 같은 풀스택 프레임워크
  • (b) 단일 Agent 클래스에 모든 책임 몰기
  • (c) 얇은 Agent 코어 + 책임별 Manager 분리

최종 결정

(c) Agent 클래스는 자체 비즈니스 로직을 거의 갖지 않습니다. 6개의 Manager를 조립하고, 워크플로우 실행을 위임할 뿐입니다.

Manager책임
SessionManagerchatId 격리, 세션별 응답 로깅, 종료 시 요약 리포트
ConversationManager메시지 히스토리 보관, 압축 트리거 감지
AgentPromptManager브랜드(Poly/CANB)별 시스템 프롬프트 주입, 지식 요약 포함
KnowledgeManager브랜드별 마크다운 지식 문서 프리로드 및 검색
ToolManager툴 등록·실행 (BigQuery / GCS / CSV / Knowledge)
TokenManager토큰 사용량·한도·압축 임계 추적, 비용 계산

의존성 조립은 AgentInitializer가 한 곳에 모아 처리합니다. 새로운 LLM Provider나 Tool을 끼워 넣을 때 수정 지점이 명확합니다 – 해당 Manager 한 곳과 Initializer 한 곳입니다.

이 구조는 처음 던졌던 세 가지 요건에 곧바로 응답합니다. 각 Manager가 독립적으로 단위 테스트되고 수정되기 때문에 매주 도는 개선 사이클을 빠르게 돌릴 수 있고, 브랜드별 격리·한국어 동의어·비즈니스 룰 검증 같은 도메인 특수 요구를 다른 영역에 영향을 주지 않고 얹을 수 있습니다.

그리고 호출 흐름이 추상화 레이어 뒤에 숨지 않고 명시적으로 드러나 있기 때문에, “왜 이 응답이 나왔는가”를 끝까지 추적할 수 있습니다.

이터레이션 속도, 도메인 적합성, 제어 가능성 – Manager 패턴이 풀어주는 것은 결국 이 셋입니다.

LLM을 갈아끼울 수 있게

문제

Vertex AI Claude로 시작했지만, 비용·지연·품질을 비교하려면 Gemini도 붙여보고 싶었고, 일부 환경에서는 Anthropic 직결도 시험해보고 싶었습니다. SDK를 워크플로우 곳곳에 직접 박아 두면 교체 비용이 폭발합니다.

검토한 옵션

  • (a) SDK를 곳곳에서 직접 호출
  • (b) 공통 인터페이스로 Provider 추상화
  • (c) 외부 게이트웨이(LiteLLM 등) 도입

최종 결정

 (b)ILLMProvider라는 공통 인터페이스를 정의하고, 모든 LLM 호출을 이 한 가지 통로로만 다루도록 했습니다. 인터페이스가 노출하는 메서드는 두 개로 한정했습니다.

  • 일반 호출 – 메시지를 보내고 완성된 응답 한 덩어리를 받습니다. 짧은 분류·요약처럼 스트리밍이 필요 없는 작업에 사용합니다.
  • 스트리밍 호출 – 응답을 청크 단위로 흘려받습니다. 사용자에게 실시간으로 분석 과정을 보여주는 메인 채팅 흐름에 사용합니다.

두 메서드는 입력 형식(메시지 배열 + 옵션)이 동일하고, 반환 형태만 다릅니다. 이 단순한 계약 덕분에 새로운 LLM Provider를 추가하는 일이 “인터페이스 두 개를 채우는 작업”으로 정리됩니다. 모델별 SDK 차이, 인증 방식, 재시도 정책은 모두 구현체 내부에 가둡니다.

구현체는 세 가지로 나뉩니다.

  • VertexClaudeProvider – 메인. Claude 4.5 Sonnet on Vertex AI
  • VertexGeminiProvider – 비교 실험용
  • AnthropicClaudeProvider – 외부 호출 / 경량 Haiku 작업용

워크플로우 코드는 인터페이스에만 의존합니다. 따라서 “지금 메인은 Claude로 돌리고, A/B 테스트는 Gemini로” 같은 결정도 워크플로우 한 줄을 고치지 않고 처리할 수 있습니다.

실시간 응답을 흐르게

문제

AI 응답은 길이가 깁니다. BigQuery 쿼리와 결과 해석까지 합치면 한 요청이 수십 초가 걸리는 일이 흔합니다.

그 동안 사용자에게 빈 화면을 보여줄 수는 없습니다. 더구나 Agent는 LLM 한 번 호출이 아니라 LLM <-> Tool 다중 왕복이어서, “지금 생각 중”, “툴 실행 중”, “최종 답변” 같은 여러 채널을 흘려야 합니다.

검토한 옵션

(a) WebSocket

(b) HTTP + 클라이언트 폴링

(c) Server-Sent Events (SSE)

최종 결정

(c) Agent → Browser는 단방향 push로 충분합니다. SSE는 그냥 HTTP라서 인프라(프록시·인증·로깅)를 그대로 활용할 수 있고, 클라이언트 코드도 가볍습니다.

실제 데이터는 다음과 같이 흐릅니다. Agent의 워크플로우는 응답을 한꺼번에 만드는 대신, 청크 단위로 하나씩 흘려보내는 비동기 생성기 형태로 구현했습니다. SSE Handler는 이 청크들을 받자마자 SSE 이벤트 형식으로 클라이언트에 송신하고, 브라우저는 스트리밍으로 받은 청크의 타입을 보고 화면의 어느 영역에 어떻게 표시할지 결정합니다.

청크 타입은 일곱 가지로 나뉩니다.

  • thinking – AI가 도구를 실행하거나 결과를 분석하는 동안의 사고 과정. 프론트엔드에서는 “생각 과정” 접힘 영역에 표시합니다.
  • answer – 사용자에게 보여줄 최종 응답 본문. 메시지 영역에 토큰 단위로 흘러갑니다.
  • progress – “BigQuery 조회 중”, “결과 정리 중” 같은 진행 상태. 상단 토스트로 표시합니다.
  • status – 세션 시작·종료, 모델 전환 같은 메타 상태 변경 알림. 프론트엔드는 디버깅 로그나 분석 도구로 활용합니다.
  • error – 오류 메시지. 사용자에게 친화적인 형태로 안내합니다.
  • keep-alive – 프록시·로드밸런서가 유휴 연결을 끊지 않도록 보내는 핑 신호. 프론트엔드는 무시합니다.
  • done – 스트림 종료 신호. 프론트엔드는 이 시점에 입력창을 다시 활성화합니다.

청크에 타입을 명시한 덕분에 프론트엔드는 받은 데이터를 어떻게 처리할지 한눈에 알 수 있고, 사용자 입장에서는 AI가 무엇을 하고 있는지 그 과정이 투명하게 보입니다.

한 가지 더 짚어둘 것은 루프 제어입니다. LLM이 “툴을 더 호출해야 한다”고 응답하는 한 워크플로우는 반복되기 때문에, 무한루프 방지를 위해 최대 반복 횟수를 20으로 두었습니다. 이 한도에 도달하면 “더 이상 툴을 호출하지 말고 지금까지 모은 데이터로 최종 분석을 내라”는 가드 메시지를 주입해서 안전하게 마무리합니다.

컨텍스트 윈도우를 효율적으로 관리하기

문제

Claude의 200K 토큰 윈도우도 긴 분석 대화에서는 금방 차오릅니다. 그렇다고 매 요청마다 처음부터 다시 시작하면 직전 BigQuery 결과·탐색 의도·결정 내역이 통째로 사라집니다 – 사용자 입장에서는 “방금 보여준 데이터 다시 설명해줘”가 안 통하게 됩니다.

검토한 옵션

(a) Sliding window – 오래된 메시지부터 단순 절삭

(b) 요약 압축 – 한도 근접 시 LLM으로 요약·병합

(c) 외부 벡터 DB로 RAG화 – 모든 히스토리를 검색 가능한 형태로 저장

최종 결정

(b)를 주축, (c)는 지식 영역에만 컨텍스트 윈도우 관리의 기본 설정은 다음과 같이 잡았습니다.

  • 전체 한도 – Claude의 컨텍스트 윈도우 200K 토큰을 기준으로 운영합니다.
  • 응답 예약 토큰 – 응답 생성용으로 항상 4,096 토큰을 비워둡니다. 이걸 빼고 남는 영역이 실제 대화에 쓸 수 있는 공간입니다.
  • 압축 트리거 시점 – 가용 토큰의 80%에 도달하면 자동 요약·병합을 발동합니다. 한계에 부딪히고 나서가 아니라, 여유가 남아 있을 때 미리 정리합니다.
  • 최소 보존 메시지 수 – 압축이 일어나도 최근 10개 메시지는 원문 그대로 유지합니다. 직전 맥락이 잘려서 “방금 그게 뭐였지?”가 안 통하는 상황을 방지합니다.

ConversationManager가 대화 히스토리를 보관하고, ContextWindowManager가 사용률을 감시하다가 임계를 넘으면 자동 요약·병합을 트리거합니다. 이때 모든 메시지를 똑같이 다루지 않습니다 – 메시지마다 중요도 점수를 계산해서, 낮은 것부터 정리합니다. 점수는 “역할에 따른 기본 점수”에 “내용에 따른 가산점”을 더하는 방식으로 계산합니다.

  • 역할 기준 기본 점수 – 시스템 메시지가 가장 높고(1.0), 사용자 메시지(0.7), AI 응답(0.5) 순으로 점수를 부여합니다. 시스템 메시지는 Agent의 동작 규칙이라 어떤 상황에서도 살려둬야 하기 때문입니다.
  • 내용 기준 가산점 – 툴을 호출했거나(+0.2), 비즈니스 엔티티(브랜드명·지표명 등)를 언급했거나(+0.1), 에러 메시지(+0.15), SQL 쿼리 내용(+0.1)이 포함되어 있으면 추가 점수를 더합니다. 분석 흐름의 핵심 단서들이라 우선 보존해야 하기 때문입니다.
  • 최종 분류 – 합산 점수에 따라 메시지를 세 등급으로 나눕니다. CRITICAL(0.8 이상)은 절대 삭제하지 않고, CONTEXT(0.6 이상)는 최대한 유지하며, REFERENCE(0.4 이상)는 공간이 부족할 때 우선 정리 대상이 됩니다.

이 정책 덕분에 BigQuery 쿼리 결과나 의사결정 메시지처럼 “나중에 다시 참조될 가능성이 큰” 항목은 보존되고, 잡담성·중복 토큰부터 먼저 정리됩니다.

한편 브랜드별 도메인 지식은 대화 컨텍스트와 분리해서 다룹니다. 브랜드별 마크다운 지식 문서는 KnowledgeManager가 별도로 로드·검색하기 때문에, 대화 토큰을 잡아먹지 않으면서도 필요한 시점에 참조할 수 있습니다. 이 분리가 (c) RAG 방식이 들어간 유일한 자리입니다 – 그것도 외부 벡터 DB가 아니라, 인메모리 스코어링 검색으로 구현했습니다.

완성된 결과물

3개월간의 Phase 1을 통해 완성된 폴리 인스퍼레이션 경영분석 AI 에이전트의 메인 화면입니다.

사용자는 브랜드(Poly · CANB)를 선택하고, 자연어로 질문을 던지면 됩니다. 분석할 데이터 소스를 미리 골라둘 수도 있고, 자주 쓰는 분석은 프로젝트로 묶어 관리할 수 있습니다.

▲ 폴리 인스퍼레이션 경영 분석 플랫폼 메인 화면 – 브랜드 선택, 자연어 질의, 최근 프로젝트

앞서 풀어본 네 가지 결정이 모두 이 한 화면 뒤에서 동작합니다.

브랜드 토글 한 번에 시스템 프롬프트와 지식 문서가 통째로 갈아끼워지고(AgentPromptManager · KnowledgeManager), 데이터 소스 선택은 BigQuery 뷰 ID로 변환되어 ToolManager에 전달됩니다. 사용자가 메시지를 보내면 SSE 스트림으로 “thinking -> answer -> done” 청크가 흘러 들어옵니다.

운영하면서 본 것들 – Phase 1의 숫자

Phase 1은 3개월 만에 마무리되었습니다. 단순 개발이 아니라 “매주 분석 -> 개발 -> 배포 -> 피드백” 사이클을 도는 에이전틱 개발 방법론으로 진행했습니다.

Week 1부터 동작하는 시스템을 고객(Poly 도메인 전문가)과 함께 다듬는 방식입니다. 그 결과로 정량적으로 남은 숫자들은 다음과 같습니다.

지표의미
토큰 사용량 절감34.5%프롬프트 리팩터링·압축 정책으로 비용 최적화
동시 지원 브랜드2개Poly · CANB – 같은 코어, 격리된 프롬프트·지식
공동 작성된 지식 문서30+도메인 전문가 + 개발자가 함께 마크다운으로 작성
동의어 사전400+“신규/신입/입학/등록” 같은 한국어 동의어 매칭
일일 피드백 → 당일 반영350+ commits3개월간 매일 도는 사이클의 산물

숫자로 잡히지 않는 변화도 적지 않았습니다. 토큰 절감 34.5%는 중요한 숫자이지만, 그것 자체보다 그 숫자에 도달한 방법이 자산이 되었습니다.

매일 운영 로그를 들여다보면서 “이 프롬프트의 이 줄이 정말 필요한가”를 묻는 습관, 압축이 일어난 시점의 대화를 거꾸로 추적해서 어떤 메시지가 살아남고 어떤 게 잘렸는지 검증하는 절차 등 이런 것들이 코드와 별개로 팀에 쌓였습니다.

그리고 가장 큰 수확은 도메인 지식의 체계화입니다. Poly 현업 담당자들이 보유한 풍부한 비즈니스 노하우 “신규유입율은 어떻게 계산하는가”, “이탈은 어떤 상태값을 봐야 하는가” 가 30+ 개의 마크다운 문서로 정리되어, AI Agent가 곧바로 참조할 수 있는 형태로 자산화되었습니다. 담당자가 바뀌어도 업무 연속성이 유지되는 조직 자산입니다.

마치며

처음으로 돌아가 봅니다. Poly Inspiration이 우리에게 가져온 첫 질문은 “DW를 어떻게 빨리, 잘 만들 것인가”였습니다. 하지만 그 질문 아래에는 더 깊은 갈증이 있었습니다. 데이터를 모으는 것 자체가 목적이 아니라, 경영진이 궁금한 것을 그 자리에서 묻고 답을 얻고 싶었던 것입니다. 인력·비용·시간이 무겁게 따라오는 DW 구축의 길은, 결국 그 갈증을 해소하기까지 너무 멀고 너무 비쌌습니다.

그래서 우리는 질문을 바꿔 던졌습니다. “DW를 짓지 않고도 그 갈증을 풀 수 있을까?” 그 답을 찾는 과정이 이 프로젝트였고, 도착한 자리가 지금의 폴리 인스퍼레이션 경영분석 AI Agent였습니다. 자연어로 묻고, AI가 BigQuery를 직접 조회하고, 결과를 도메인 지식과 결합해 즉시 답해주는 시스템 – 처음의 질문이 정말 묻고자 했던 답을, 다른 길로 돌려준 셈입니다.

Manager 패턴으로 관심사를 쪼개고, ILLMProvider로 LLM을 갈아끼울 수 있게 하고, SSE 스트리밍으로 응답을 흐르게 하고, 컨텍스트 윈도우를 효율적으로 관리한 네 가지 결정은 모두 이 한 문장을 떠받치기 위해 내려진 것들입니다. 그리고 이 프로젝트의 가장 큰 수확은 코드 자체가 아니라 그 과정에서 함께 정리된 30+ 개의 도메인 지식 문서일지도 모릅니다. “우리 비즈니스는 어떻게 돌아가는가”를 처음으로 명문화한 조직 자산이기 때문입니다. AI Agent는 그 지식을 실행하는 엔진일 뿐입니다.

물론, 끝난 것은 아닙니다. Phase 1을 마치고 보니 다음 질문들이 보입니다 – 더 많은 브랜드와 데이터 소스를 어떻게 더 빠르게 온보딩할 것인가, AI의 답변 품질을 어떻게 더 정량적으로 측정하고 개선할 것인가, 경영진이 묻기 전에 AI가 먼저 이상 징후를 짚어주는 단계로는 어떻게 갈 것인가. 처음의 질문에 답하면서 새로운 질문들이 떠올랐고, Phase 2는 그 질문들과 함께 시작될 것입니다.

“프레임워크 없이 만든다”는 결정은 자랑이 아닙니다. 우리 맥락에 맞는 도구가 마침 그 자리에 없었을 뿐이고, 그래서 우리가 그 도구가 되었습니다. 같은 자리에 다른 팀은 다른 결론을 내려도 좋습니다 – 이 글이 그 의사결정을 조금 더 빠르게 만드는 데 보탬이 되면 좋겠습니다.

좋은 시스템은 처음 던진 질문에 답하는 데서 끝나지 않습니다. 그 답이 다음 질문을 불러올 때, 비로소 시스템은 살아 있는 것입니다. Poly Inspiration과 함께한 1년은 우리에게 그 사실을 다시 가르쳐주었습니다.

✍️ AlphaCode · AI Group

게시물 주소가 복사되었습니다.

이런 콘텐츠도 있어요!