date
slug
author
status
tags(최대 3개)
summary
type
thumbnail
category
updatedAt
TL;DR
- 자연어로 질문하면 SQL을 짜서 실행하고 결과를 정리해 돌려주는 Slack AI 봇 쿼리곰을 만들었습니다.
- 첫 주는 반짝, 둘째 주는 조용했습니다. 범용 LLM 래퍼로는 쓸 만하다와 계속 쓴다 사이의 간극을 넘을 수 없었습니다.
- 세 가지 구조로 그 간극을 메웠습니다 — 멀티에이전트 검증, 조직의 지식 전체를 연결한 Hybrid RAG, 쓸수록 똑똑해지는 이중 메모리.
- 결과적으로 총 사용자 81명 중 70명이 재방문(86.4%)하고, 34.6%가 파워유저(10일 이상)가 됐습니다. 쿼리곰 단일 봇이 전체 요청의 93%를 차지하는 압도적 엔진이 됐고, 이 구조는 이제 6개 봇 플랫폼으로 확장되고 있습니다.
1. 데이터 좀 뽑아주세요라는 병목
어느 회사든 데이터팀에는 비슷한 풍경이 있습니다. PO는 지난달 팀별 매출을 뽑아 달라 하고, 마케터는 캠페인 유입 경로별 전환율을 보고 싶어 하고, 운영팀은 급하게 이 수치가 맞는지 확인만 해달라 합니다.
간단한 조회인데도 테이블 구조 파악 → SQL 작성 → 결과 검증까지 빨라야 수십 분입니다. 요청이 쌓이면 하루 이상 대기. 데이터팀은 병목이 되고, 요청자는 기다리고, 의사결정은 늦어집니다.
아임웹도 같았습니다. 그래서 자연어로 물어보면 SQL을 짜서 실행해 주는 봇을 만들었습니다. Slack에서
@쿼리곰을 멘션하고 질문하면 LLM이 SQL을 생성하고, Databricks에서 실행한 뒤, 결과를 정리해 답합니다. 프로토타입은 정말 하루 만에 나왔습니다.2. 1주일 만에 조용해진 이유
배포 첫 주는 기대가 컸습니다. 그런데 둘째 주부터 Slack이 조용해졌습니다. 왜일까요.
- 테이블명을 틀립니다. 데이터 레이크에 테이블이 수백 개인데 LLM은 그걸 모릅니다. 매출 보여달라고 하면 존재하지 않는 테이블을 자신 있게 만들어냅니다.
- 컬럼 매핑이 엉뚱합니다.
site_id와site_code를 혼동하고,order_time과created_at을 구분 못 합니다. 스키마를 모르니 당연합니다.
- 회사 용어를 모릅니다. GMV가 뭔지, 순매출과 어떻게 다른지, AM 고객이 무슨 뜻인지 모릅니다.
- 결과를 신뢰할 수 없습니다. 쿼리는 실행되는데, 숫자가 맞는지 확인하려면 결국 데이터팀에 물어봐야 합니다.
사용자 입장에서 결론은 하나였습니다. 그냥 데이터팀에 요청하는 게 빠르다는 것.
문제의 본질이 분명해졌습니다. 범용 LLM은 SQL을 생성하는 것은 잘합니다. 하지만 우리 회사의 데이터는 모릅니다.
더 중요한 건 모른다는 사실조차 모른다는 점입니다. 틀린 테이블을 자신 있게 쓰는 봇은, 아예 답을 못 하는 봇보다 더 나쁩니다. 신뢰를 깨뜨리니까요.
여기서 깨달았습니다. 사내 AI 봇의 진짜 제품은 답변이 아니라 신뢰입니다. 정확도 95%짜리 봇도 한 번 황당하게 틀리면 사용자는 떠납니다. 우리가 만들 것은 가끔 맞는 봇이 아니라 틀리지 않는 안전한 봇이었습니다.
3. 신뢰를 만드는 구조 ①: 멀티에이전트 검증
첫 선택은 LLM 하나가 아니라 전문 에이전트 팀으로 답을 만드는 것이었습니다. 단일 LLM에게 SQL을 짜고 검증도 하라고 시키면 구조적 문제가 생깁니다.
자기가 만든 쿼리를 자기가 검증하는 순간 확증 편향이 발생합니다. 사람도 그렇죠. 내 코드를 내가 리뷰하면 버그를 못 보지만, 동료가 리뷰하면 귀신같이 찾아냅니다.

그래서 LLM 호출을 역할별로 쪼갰습니다. 복잡한 쿼리(JOIN 여러 개, 민감 데이터 포함)가 들어오면 생성 에이전트가 SQL을 만들고, 검증 에이전트 3개가 병렬로 각자의 관점에서 검토합니다.
하나라도 실패하면 피드백과 함께 재생성(최대 3회), 전부 통과해야 실행합니다. 간단한 쿼리(단일 테이블, JOIN 없음)는 이 과정을 건너뛰고 바로 실행해 속도를 지킵니다. 복잡도에 따라 검증 비용을 다르게 지불하는 거죠.
여기에 두 개의 안전망을 덧붙였습니다.
실행 전 자동 교정
- alias 기반으로 잘못된 컬럼을 올바른 컬럼으로 사전 변환
- 과거 교정 이력(뒤에 설명할 Correction Memory)에서 동일 패턴을 선제적으로 수정
- 사용자 입장에선 쿼리가 그냥 돌아가고, 내부에서 조용히 고쳐집니다
실행 후 검증
- Zero-row 감지: 결과가 0건이면 절대 통계를 만들어내지 않고, 조건을 확인해 달라고 솔직하게 답합니다
- NULL 컬럼 경고: 전체가 NULL인 컬럼이 나오면 스키마 확인을 제안
- 이상치 플래깅: 음수 금액, 비정상적 집계값 자동 감지
에이전트의 신뢰는 절대 안 틀리는 데서 오지 않습니다. 틀려도 안전하게 복구되는 데서 옵니다. Zero-row 감지 하나만 넣어도 사용자 신뢰가 눈에 띄게 올라갔습니다.
현재 쿼리곰의 에러율은 0.4%입니다.
총 3,378건을 처리하는 동안 실패로 분류된 건 14건 남짓. 이 숫자보다 중요한 건, 그 14건이 조용히 복구되거나 솔직하게 모른다고 답했지, 엉뚱한 숫자를 자신 있게 뱉지 않았다는 점입니다.
4. 신뢰를 만드는 구조 ②: 조직의 지식을 통째로 연결한 Hybrid RAG
LLM이 정확한 SQL을 짜려면 우리 회사에 어떤 테이블이 있고 각 컬럼이 뭘 의미하는지를 알려줘야 합니다. 여기까지는 많은 팀이 합니다. 우리는 한 발 더 나갔습니다. 쿼리곰이 참조하는 지식 소스는 데이터 웨어하우스 하나가 아닙니다. 데이터만 보는 봇에서 조직을 아는 봇으로 넘어간 지점입니다.

예를 들어 사용자가 ABC07 코드가 뭔지, 관련 매장 리스트를 뽑아 달라고 물으면 이렇게 동작합니다.
- 코드베이스 검색으로
ABC07이 소스코드에서 어떻게 정의됐는지 확인 — 결제 이탈 상태값
- Notion 검색으로 결제 이탈 관련 정책 문서 참조 — 집계 기준/제외 조건 파악
- Jira 검색으로 이 상태값이 언제 도입됐는지, 관련 티켓의 맥락 확인
- 메타 카탈로그에서 관련 테이블과 컬럼을 찾고
- 모든 컨텍스트를 합쳐 SQL 생성
정적 용어 사전으로는 담을 수 없는 조직의 동적인 지식을 매번 새로 엮어냅니다.
토큰이 터지지 않도록 — 3단계 검색 + RRF
물론 이 10개 소스를 매번 프롬프트에 다 넣으면 토큰이 터집니다. 그래서 검색을 3단계로 구성했습니다.
- 키워드 패턴 매칭 — 매출, 결제, 주문 같은 도메인 용어를 테이블 그룹과 매핑(57개+ 비즈니스 키워드)
- 전문 검색(Full-text Search) — 동의어 확장 포함. 매출로 검색하면 GMV, 거래액도 함께 잡힘
- 벡터 의미 검색 — 임베딩 유사도 검색으로, 위 두 방식으로 안 잡히는 애매한 질문도 커버
세 결과를 **RRF(Reciprocal Rank Fusion)**로 합산해 최종 순위를 뽑습니다. 단일 알고리즘으로는 놓치는 케이스를 앙상블이 덮어주는 구조입니다.

여기에 데이터 계층 우선순위를 곱합니다. 정돈된 마트에 같은 데이터가 있으면 그걸 우선 쓰되, 마트에 없는 케이스는 raw 레이어까지 내려가 답을 찾습니다.
마트 정비가 완벽하지 않아도 동작하는 현실적인 구조입니다. (마트가 만들어지는 속도가 raw 데이터가 쌓이는 속도를 따라잡기 어려웠습니다.)
5. 신뢰를 만드는 구조 ③: 쓸수록 똑똑해지는 이중 메모리
이 구조가 쿼리곰의 진짜 retention 장치입니다. 사용자가 봇의 결과를 교정하면 봇이 그걸 기억하고, 다음엔 같은 실수를 반복하지 않습니다. 그것도 내 팀원이 교정한 내용을 다른 팀원의 질문에서도 활용합니다. 두 개의 레이어로 분리했습니다.
Correction Memory — 스키마 교정
- LLM이
a_id를 썼는데 실제론a_code여야 할 때, 교정 내역을 JSONL로 자동 저장
- 다음에 같은 테이블을 쓸 때 교정 이력이 자동으로 프롬프트에 주입되어 같은 실수를 반복하지 않음
- 사용 빈도(
hit_count)를 추적해 자주 쓰이는 교정을 우선순위 높게
- 대표 사례를 꼽자면
a_id → a_code가 5회 이상 자동 교정된 흔적이 남아 있습니다. 5명이 같은 함정에 빠지지 않게 된 셈이죠.
Learning Memory — 비즈니스 룰
- 매출은 GMV가 아니라 순매출이라는 규칙을 영구 저장
position컬럼은 TEXT 타입이라'1'로 비교해야 한다는 규칙을 영구 저장
- 월간 활성 매장은 결제 발생 기준이지 설치 완료 기준이 아니라는 규칙을 영구 저장
- 벡터에 임베딩으로 저장되어, 관련 질문이 들어오면 의미 검색으로 자동 주입됩니다
- 봇별로 컬렉션이 분리돼 있어, 쿼리곰의 학습이 다른 봇의 컨텍스트를 오염시키지 않습니다
한 명이 교정하면 전 직원이 혜택을 받습니다. 쿼리곰은 개인 도구가 아니라 팀이 함께 키우는 도구가 됩니다.
이 구조가 누적될수록 사용자는 봇을 떠나기 어려워집니다. 내가 가르친 게 다 들어 있는데 다른 도구로 갈 이유가 없으니까요. 수치로도 확인됩니다. 1기 코호트의 리텐션 커브가 단순 하락형이 아니라 smile curve를 그립니다.
W2에 54.2%로 떨어졌다 W3에 79.2%로 반등하고, W7까지 70.8%를 유지하다 W8에 66.7%. 한 번 가치를 체감한 사용자는 오히려 더 강하게 정착합니다. 학습 메모리가 이 곡선의 바닥을 떠받치고 있다고 믿습니다.
6. 채팅 UX를 과소평가하지 마세요
기술 구조만큼 중요한 게 대화 경험이었습니다. 데이터 분석은 한 번에 끝나지 않습니다. 지난달 매출을 보여달라 → 팀별로 나눠달라 → 전월 대비 증감도 → CSV로 뽑아달라처럼 이어집니다.
쿼리곰은 Slack 스레드 안에서 이 대화를 자연스럽게 이어갑니다. 메시지마다 이전 대화 맥락과 실행한 쿼리 이력이 자동 주입됩니다. UX를 매끄럽게 만든 디테일은 이렇습니다.
- 세션 유지 — 스레드 단위로 대화가 이어집니다. 아까 그 테이블에서라고만 해도 맥락을 압니다
- 실행 버튼 — SQL을 먼저 보여준 뒤 ▶️ 한 번으로 즉시 실행. 신뢰가 쌓이기 전까지는 사용자가 확인하고 실행할 수 있게
- 스트리밍 상태 — 오래 걸리는 쿼리는 진행률을 실시간으로 표시
- 대용량 데이터 — 결과가 크면 다운로드 링크를 자동 생성
- 피드백 버튼 — 응답마다 👍 / 🤔 / 👎 세 버튼. 부정 피드백은 자동으로 학습 메모리의 개선 신호로 연결
결과적으로 사용자 경험은 동료 데이터 분석가와 Slack에서 대화하는 것과 거의 같아졌습니다. 한 사용자는 이렇게 말했습니다.
외근 중에 필요한 지표를 바로 확인할 수 있어서 좋아요. 숫자만 주는 게 아니라 해석까지 같이 주니까요.
인당 요청 수가 5.6건에서 17건으로 3배 증가한 데에는 이런 사소해 보이는 UX가 결정적이었다고 봅니다.
7. 하나의 봇이 플랫폼이 되다 — 게이트웨이 패턴
쿼리곰이 자리를 잡자 다른 팀에서 요청이 들어왔습니다. QA 검토도 AI로 해달라, 총무 업무도 봇으로 처리할 수 없냐, 인프라 모니터링·에스컬레이션도 해달라는 식이었죠. 그래서 봇을 하나씩 늘렸습니다.
총무 봇(서포트곰), 인프라 봇(곰프라), 관리자 봇(곰추장), QA 봇(qagom). 그런데 새 문제가 생겼습니다. 이 질문을 누구에게 해야 하는지 — 쿼리곰? 곰변? 서포트곰? — 봇이 3개를 넘자 사용자들이 혼란스러워했습니다. 기술 문제가 아니라 제품 문제였습니다.
해결책은 뭐든물어봐곰이라는 게이트웨이 봇이었습니다. 사용자는 이 봇 하나만 기억하면 됩니다. 설계할 때 반드시 지킨 원칙은 이렇습니다.

- 키워드 매칭 금지 — 자연어는 키워드로 분류할 수 없습니다. 매출 통계 보여줘는 데이터, 매출 통계 관련 정책은 큐곰입니다. LLM 분류만이 답입니다
- 역방향 핸드오프 — 전문 봇이 이건 내 영역이 아니라고 판단하면 게이트웨이로 반려하고, 게이트웨이가 다시 올바른 봇에 전달
- 스레드 고정 — 한번 라우팅된 스레드의 후속 메시지는 자동으로 같은 봇이 받습니다. 스레드 중간에 봇이 바뀌면 맥락이 무너지니까요
- 크로스봇 멘션 — 쿼리곰 스레드에서
@큐곰을 직접 호출하면 큐곰이 1회성으로 답하고, 스레드 소유권은 쿼리곰에 유지
봇이 2개 이상 될 예정이면 게이트웨이를 먼저 만드세요. 나중에 도입하려면 사용자 습관을 바꿔야 해서 훨씬 어렵습니다.
현재 곰타운 사용자의 34.6%가 멀티봇 사용자이고, 한 명이 평균 1.5개 봇을 씁니다. 쿼리곰 단일 제품이 아니라 곰타운이라는 업무 인터페이스로 인식되기 시작한 증거입니다.
8. 결과 — 수치가 말하는 것
출시 7.5주, 곰타운 전체 지표를 요약하면 이렇습니다.

- 누적 요청 3,629건, 그중 쿼리곰 단독 3,378건(93%)
- 총 사용자 81명 중 70명 재방문(86.4%)
- 인당 요청 수 5.6건 → 17건(약 3배)
- 1기 코호트 리텐션 커브가 smile curve — W2 54.2% → W3 79.2% → W7 70.8% → W8 66.7%
하지만 진짜 의미 있는 건 사용자 피드백입니다.
데이터 분석가분들 리소스를 뺏는 것 같아 사소한 질문은 망설였는데, 이제는 부담 없이 물어볼 수 있어요.
데이터 요청이 조심스러운 일에서 Slack에서 바로 물어보는 자연스러운 행동으로 바뀌었습니다. 데이터팀은 그 시간을 더 깊은 분석에 쓰고 있습니다. 병목이 해소됐다는 건 이런 모양입니다.
흥미로운 관찰도 있었습니다. 개발 직군의 사용량이 예상보다 훨씬 높았습니다. SQL을 직접 짤 수 있는 사람들인데 왜 쿼리곰을 쓸까요? 답은 간단했습니다.
테이블 구조를 매번 찾는 것보다 물어보는 게 빠르니까요. 조직의 지식 전체를 엮어 둔 구조가 만든 예상 밖의 채택이었습니다.
9. 우리가 배운 것
쿼리곰을 만들고 운영하며 배운 걸 한 문장으로 줄이면 이렇습니다.
범용 LLM 래퍼는 장난감입니다. 조직의 지식을 엮는 구조 + 틀려도 안전한 검증 + 쓸수록 똑똑해지는 학습 루프가 그 장난감을 필수 도구로 바꿉니다.
좀 더 구체적으로 정리하면 이렇습니다.
- 사내 AI 봇의 제품은 답변이 아니라 신뢰입니다. 한 번 황당하게 틀린 봇은 두 번째 기회를 얻기 어렵습니다. 틀려도 안전한 구조를 맨 먼저 설계하세요.
- 단일 LLM이 혼자 검증하면 확증 편향에 빠집니다. 생성자와 검증자를 분리하세요. 간단한 케이스까지 오버엔지니어링할 필요는 없지만, 복잡한 케이스에선 반드시 필요합니다.
- 모델을 바꾸기 전에 컨텍스트를 바꾸세요. 더 비싼 모델로 갈아타는 것보다, 조직의 지식(Notion, Jira, Slack, 코드, 대시보드)을 엮는 게 정확도에 더 큰 영향을 줍니다.
- 학습 루프가 retention을 만듭니다. 사용자가 내가 키운 봇이라고 느끼는 순간 다른 도구로 이탈하지 않습니다. smile curve는 우연히 생기지 않습니다.
- 채팅 UX를 과소평가하지 마세요. 세션 유지, 실행 버튼, 스트리밍 상태, 피드백 버튼 같은 사소한 UX가 실제 채택률을 결정합니다.
- 관찰성 없이는 개선도 없습니다. 요청 ID와 피드백 버튼, 이 두 가지가 없으면 뭘 고쳐야 하는지 모릅니다.
- 봇이 2개 이상 될 예정이면 게이트웨이를 먼저. 사용자 습관은 한번 들면 바꾸기 어렵습니다.
10. 앞으로
쿼리곰은 여전히 성장 중입니다. 지금 작업 중인 것은 이렇습니다.
- 더 많은 조직 지식의 자동 연결 — 현재는 10개 소스를 수동으로 연결했지만, 새 지식 소스가 생길 때마다 플러그인 방식으로 추가되는 구조로 정리 중
- 복잡한 다단계 분석 자동화 — 단순 SQL 생성을 넘어, 분기별 코호트 분석처럼 여러 쿼리를 엮어야 하는 케이스까지 자동화
- 다른 봇들의 성장 — 현재 쿼리곰이 93%를 차지하지만, 곰변·서포트곰·곰프라가 각자의 도메인에서 두각을 나타내기 시작했습니다. 데이터를 묻는 곳에서 사내 업무 전반을 다루는 인터페이스로
사내 AI 봇을 만들고 있다면, 만드는 것보다 사람들이 계속 쓰게 만드는 것에 더 많은 시간을 쓰길 권합니다.
LLM을 호출하는 코드는 하루면 씁니다. 하지만 누군가가 1주일 뒤에도, 한 달 뒤에도, 여섯 달 뒤에도 계속 돌아오게 만드는 건 다른 이야기입니다. 곰타운은 그 여정의 한가운데에 있습니다.

