AI/Natural language processing

[NLP] Text-to-SQL 기반 Agentic AI 3-Tier 데이터 분석 에이전트 개발

hjjummy 2025. 11. 10. 17:14

이번 글에서는 약 3주간 Poc를 진행하며 Text-to-SQL 기반 데이터 분석 에이전트를 개발한 과정을 정리하고자 한다.


1. Text-to-SQL이란?

Text-To-SQL은 사용자가 입력한 자연어 질의를 데이터베이스가 이해할 수 있는 SQL 쿼리로 변환하는 기술이다. 

 

예를 들어 사용자가 "올해 입사한 20대 사원수 알려줘" 라고 입력하면 시스템은 자동으로 다음과 같은 SQL을 생성한다.

SELECT COUNT(*) 
FROM employee 
WHERE YEAR(join_date) = 2024 
AND age BETWEEN 20 AND 29;

 

즉, 사용자는 SQL 문법을 몰라도 자연어만으로 데이터베이스에 질의하고, 실시간으로 분석 결과를 받을 수 있다.
이 기술은 단순한 챗봇을 넘어 기업 내 데이터 접근성을 혁신적으로 개선할 수 있다는 점에서 의미가 크다.


2. Text-to-SQL이 필요한 이유

👉우선  첫 번째로

최근 기업 내에서는 대량의 데이터를 신속하게 분석해야 하는 상황이 늘고 있지만, 여전히 비개발 직군은 SQL을 직접 다루기 어렵다. 이로 인해 데이터 분석 요청이 개발자에게 집중되고, 의사결정 속도는 느려진다.

 

예를 들어, “지난달 신규 고객의 연령대별로 가장 잘 팔린 상품을 알려줘.” 이런 단순한 질문도 SQL로 변환하려면 여러 테이블을 조인하고, 집계 쿼리를 작성해야 한다.

 

만약 사내에 Text-to-SQL 기반 데이터 챗봇이 구축되어 있다면, 비개발자도 복잡한 SQL 없이 자연어 한 줄로 결과를 얻을 수 있다.
이처럼 데이터 접근성을 높이고 개발자 의존도를 줄이는 것이 프로젝트의 출발점이었다.

 

👉 두 번째로

기존 GPT 같은 LLM에게 데이터를 직접 업로드해 계산을 시키면, 종종 파일 구조나 수식을 잘못 해석해 계산 오류를 발생시키는 문제가 있었다. 특히 엑셀 파일의 셀 병합, 문자열 숫자, 결측값 등에서 정확도가 급격히 떨어졌다.

 

이러한 문제를 해결하기 위해 자연어 질의를 SQL로 자동 변환하여 실시간으로 데이터를 조회할 수 있는 시스템, 즉 Text-to-SQL 기반의 AI 분석 에이전트를 구현하게 되었다.


3. Text-to-SQL 수행 구조

Text-to-SQL은 다음과 같은 순서로 동작한다.

 

1️⃣ 자연어 질의 입력
: 사용자가 자연어로 질문을 입력한다.

2️⃣ 스키마 매핑
: 시스템은 입력된 문장에서 주요 명사를 추출하고, 데이터베이스의 테이블 및 컬럼 구조와 매칭한다.
예를 들어 “사용자 수를 알려줘”라는 문장에서 “사용자”는 DB의 user 테이블로 매핑된다.

3️⃣ SQL 생성
: LLM이 스키마 정보를 기반으로 SQL을 자동으로 생성한다.
이 과정에서 질의의 의도를 파악해 SELECT, WHERE, GROUP BY 등 필요한 절을 동적으로 구성한다.

4️⃣ SQL 검증 및 실행
: 생성된 SQL은 문법 검증(sqlglot)을 거쳐 DuckDB에서 실행되며, 결과가 Pandas DataFrame 형태로 반환된다.

5️⃣ 결과 출력
: Streamlit UI에서 표 형태로 시각화된다. 사용자는 SQL을 보지 않고도 결과만 확인할 수 있다.

[논문 : sLLM 기반의 경량화 Text-to-SQL 구현 방안]

3. Text-to-SQL 이 어려운 이유와 대응 전략

 GPT에게 SQL짜달라고 하면 잘 짜주는것 같은데 , " GPT API만 호출하고 연동하면 개발 끝 아닌가?!" 

라고 간단하게 생각할 수 있다. 나도 처음에는 그러했다..  기업에서 제공한 실제 DB와 샘플 쿼리 들을 보기전까진..ㅎㅎ

 

막상 DB와 샘플 질문을 가지고 개발을 진행하다보니 왜 text to sql이 까다롭고, 그만큼 요새 주목받는 기술인지를 느꼈다.

 아래는 실제 Text to SQL을 개발할 때 어려움에 대해서 잘 설명해준 블로그이고, 나 또한 매우 공감하기에 이를 다시한번 정리 해보았다.

참고: https://devocean.sk.com/blog/techBoardDetail.do?ID=167708&boardType=techBlog

 

1️⃣ 명시적 vs 암묵적 맥락 — “AI에게 DB는 그냥 텍스트 일 뿐이다”

Text-to-SQL의 첫 번째 어려움은 AI에게 ‘맥락’을 주는 일이다. 우리가 SQL을 쓸 때는 이미 머릿속에 데이터 구조가 그려져 있다.
“이 테이블은 주문 데이터고, 이 컬럼은 단가야” 같은 감각적인 이해가 전제되어 있다.

AI는 그런 걸 모른다. AI에게는 데이터베이스가 그저 텍스트 덩어리일 뿐이다. 따라서 우리가 AI사 이해 할 수 있도록 그 맥락을 설명해줘야 한다. 

 

AI에게 주어야할 맥락은 크게 2가지로 나눌 수 있다. 

  • 명시적 컨텍스트: 스키마, 테이블 관계, 컬럼 타입/별칭 등 구조화된 정보
  • 암묵적 컨텍스트: “이 회사에서 주문은 무엇을 의미하나?”, “반품 처리 로직은 어디에 반영되나?” 같은 해당 업계에서만 사용하는  용어 혹은 도메인 규칙관습적 의미임. 문서화가 부족하고, 스키마 개편에 따라 수시로 바뀌기 쉬움.

👉 대응 로직

  • 스키마 RAG: 최신 스키마/ERD/뷰 정의를 임베딩 색인하고, 쿼리 생성 전 LLM에 주입함.
  • 비즈니스 용어집 + 규칙 프롬프트: “베스트셀러 = ‘매출 합계 기준 상위 N’”처럼 정의 사전을 관리하고, 프롬프트에 강제 규칙으로 삽입함.
  • 골든 쿼리/리포트 카탈로그: 자주 쓰는 분석 쿼리를 메타데이터(의도·입력·출력 스키마)와 함께 저장해 few-shot 예시로 투입함.
  • 스키마 변화 추적: 사전 스캔으로 컬럼/뷰 변경 diff를 감지하여 프롬프트 컨텍스트를 자동 갱신함.

2️⃣ 사용자 의도 파악 — "사람의 말은 너무 모호하다"

두 번째 어려움은 질문 자체가 불명확하다는 점이다.

예를 들어 누군가 “가장 잘 팔린 신발은 뭐야?”라고 물었다고 하자.
이때 ‘잘 팔린’이라는 표현은 너무 모호하다.

 

  • 주문 수가 많은 건가?
  • 매출이 높은 건가?
  • 반품률은 제외해야 하나?
  • 브랜드별로 묶을까, 개별 상품으로 볼까?

사람이라면 이런 질문을 받으면 “정확히 어떤 기준으로요?”라고 되묻겠지만, AI는 일단 답을 하려고 든다.

그 결과, SQL은 만들어지지만 우리가 원하던 답은 아닐 수 있다.

👉 대응 로직

  • 리라이팅(Clarify) 으로 의도 명확화 : 질문을 측정 지표·집계 단위·기간·필터로 구조화하여 명시화함.
  • 템플릿/드롭다운 UX(선택형 하이브리드): 완전 자유 입력 대신 반정형 입력 UI를 병행하여 모호성을 줄임.
  • 의도 불확실성 임계치: 불확실성이 높으면 즉시 SQL 생성 대신 추가 질문을 유도하거나 대안 SQL 2~3안을 제시함.
  • 결과 근거 설명: “이 SQL은 ‘매출 합계 기준, 반품 미제외’로 해석함”처럼 가정·기준을 출력하여 신뢰성을 높임.

3️⃣ SQL 방언(Dialect) — “DB마다 말이 다르다”

  • EXTRACT vs MONTH, LIMIT/OFFSET 차이, 날짜함수/캐스팅 규칙 등 DB마다 다름.
  • LLM은 미묘한 차이에 취약함.

👉 대응 로직

  • 표준화 추출기(sqlglot): 생성 SQL을 파싱·정규화하여 타깃 엔진용 방언으로 변환함.
  • DB 기능 프로파일: 엔진별 함수 지원/제약을 JSON으로 관리해, 프롬프트와 검증기가 참고하도록 함.
  • 회귀 테스트: 주요 질의에 대해 엔진별 기대 결과를 스냅샷으로 보관하고 자동 비교함.

4. Agentic AI 3-Tier 시스템 설계 

이번 프로젝트의 핵심은 단순한 질문 → SQL” 자동화를 넘어서, AI가 스스로 사고하고, 과거 대화 문맥을 이어받아 자율적으로 질의를 수행하는 에이전트 구조로 확장하는 것이었다.

 

이를 위해 시스템을 Prompt Layer → Logic Layer → Execution Layer의 3-Tier 구조로 설계하였다.


단계 역할 구성 요소
1️⃣ Prompt Layer 자연어 이해, 질의 의도 파악 GPT-5 기반 프롬프트 엔진, 리라이팅 모듈
2️⃣ Logic Layer SQL 생성 및 검증, 컬럼 선택 DuckDB 스키마, SQL 파서(sqlglot), Column Selector
3️⃣ Execution Layer SQL 실행 및 결과 반환 DuckDB, Pandas, Streamlit

이 구조 덕분에 모델은 단순한 챗봇이 아닌,
사용자의 질의를 단계적으로 해석하고 실행하는 Agentic AI로 작동한다.

 

예를 들어,

“AC25 공장의 평균 효율은?”
“그보다 높은 라인은?”

 

이 두 질문이 연속되면, AI는 첫 번째 결과를 기억한 뒤 “그보다 높은” 조건을 자동으로 반영한 SQL을 생성한다.
즉, 문맥을 이해하고 스스로 확장하는 대화형 분석 루프가 완성된다.

 

DuckDB 선택 이유

PoC에서는 경량형 분석 DB인 DuckDB를 사용했다.
서버 설치 없이 로컬 파일로 동작하며, SQL-92 표준을 준수하고
Pandas와의 연동성이 탁월하다.

DuckDB의 주요 장점은 다음과 같다.

  • 복잡한 JOIN, GROUP BY 연산을 빠르게 처리
  • 인덱스 없이도 컬럼 압축 기반으로 고속 질의
  • Streamlit 환경에서 바로 시각화 가능

이를 통해 “엑셀 업로드 → 내부 DB화 → SQL 질의 → 결과 시각화”의
하이브리드형 데이터 분석 구조를 구현할 수 있었다.


5. Text-to-SQL 성능평가

Test Dataset — Spider / WikiSQL

Text-to-SQL 모델의 성능은 일차적으로 기업이 제공한 샘플 쿼리로 테스트를 하고, 일반화 성능을 체크하기 위해 공개 데이터셋으로 평가했다.
대표적으로 SpiderWikiSQL이 있다.

데이터셋 특징
Spider 예일대 학생들이 주석을 단 SQL 데이터셋으로, 다중 테이블·복잡 쿼리 지원. HAVING, GROUP BY, JOIN 등 다양한 SQL 구조 포함.
WikiSQL 위키피디아의 테이블 기반으로 구성된 단일 테이블 SQL 데이터셋. 구조는 단순하지만 대규모(8만 개 샘플).

이 프로젝트에서는 Spider의 다중 테이블 질의 구조를 참고하여,
복잡한 공정 데이터를 처리할 수 있는 스키마 매핑 로직을 구현하였다.


정리 

이번 PoC를 통해 Text-to-SQL 기술을 중심으로 한 3-Tier 아키텍처 기반의 Agentic AI를 구현할 수 있었다.
각 역할이 분화되어 있더라도, 아직 결과를 평가하고 다시 Planner에게 피드백을 주는 형태의 에이전트 간 상호작용 루프가 존재하지 않기 때문에 완전한 Multi-Agent 시스템이라고 부르기에는 이르다.

 

현재는 하나의 에이전트가 프롬프트 해석부터 SQL 생성, 검증, 실행까지의 전 과정을 스스로 수행하고 있으며, 이는 AI가 reasoning → planning → action → reflection 단계를 거쳐 스스로 목표를 설정하고 문제를 해결하는 자율형 구조로 발전했음을 의미한다.

 

이러한 Agentic 구조는 단순한 기능 분할을 넘어, Text-to-SQL의 본질적인 가치를 더욱 명확하게 보여준다.
Text-to-SQL은 단순히 SQL을 자동으로 생성하는 기술이 아니라, 비즈니스 언어를 데이터 언어로 정확히 번역하는 과정이며, 그 번역의 정밀도는 AI가 사용자의 문맥과 의도를 얼마나 깊이 이해하고 계획적으로 사고하느냐에 달려 있다.


향후 계획

현재 시스템은 단일 테이블 기반의 DB 구조를 사용하고 있어 스키마 선택 과정이 단순하고 명시적이다.
하지만 향후에는 다중 테이블 환경으로 확장하여, RAG 기법을 도입함으로써 AI가 스스로 관련 스키마 정보를 검색하고 선택할 수 있는 구조로 발전시킬 계획이다.

 

또한, 생성된 SQL 코드의 품질을 평가하고 그 결과를 다시 Planner에게 피드백하는Self-Reflection Loop를 추가하여
각 에이전트가 독립적인 역할을 수행하며 협력하는 Multi-Agent 시스템으로 확장할 예정이다.

 

 

느낀점

이번 프로젝트를 하면서 제일 크게 느낀 건, “단순 프로젝트성 개발할 때랑, 고객이 있는 PoC는 진짜 다르다”는 거였다.

혼자  만들 땐 편하다. AI가 모호한 질문을 던져도 내가 바로 판단해서 “아, 이건 이런 식으로 리라이팅해야겠다” 하면서 규칙을 고치면 끝이다.

 

결국 내 머릿속에 기준이 다 있으니까 빠르게 수정하고, 바로 테스트하고, 마음대로 바꿔볼 수도 있다.

근데 PoC는 다르다. 고객이 있고, 그 고객의 실제 데이터가 얽혀 있기 때문에 조금이라도 표현이 모호하면 바로 해석 차이가 생긴다.

 

게다가 내가 세운 규칙이라도, 그걸 세일즈팀이나 고객 담당자에게 명확히 공유하지 않으면 나중에 서로 “이 부분은 원래 이렇게 작동하는 거 아니었나요?” 같은 오해가 생긴다.


이 과정에서 진짜 “소통이 반이다”라는 걸 체감했다.

 

예를 들어 이런 일이 있었다.
고객이 “이 수치와 가장 비슷한 상품을 찾아줘.”라고 쿼리를 작성했는데, 나는 단순히 기술 검증 수준으로 생각해서 UI를 간결하게 만들고 “최신 N개만 반환”하는 로직으로 처리했다.

 

그런데 피드백 미팅에서 고객이 하신 말 —

“저희는 비슷한 상품 전부 다 보고 싶었어요.”
그 한마디에 머리를 한 대 맞은 기분이었다.

 

이건 단순히 기능 차이의 문제가 아니라, 결국 “무엇을 비슷하다고 보는가”라는 기준부터 다르게 생각하고 있었던 거다.
물론 추후 간단히 해결 할 수 있는 문제지만, 이런 사소한 차이 하나가 결과 해석은 물론, 그에 따른 사용자 경험까지 완전히 바꿔버린다는 걸 그때 알았다.

 

그래서 내린 결론은,,~~

PoC에서는 기술구현 이전에 명확하고 구체적인 고객 요구사항 정의가 매우 중요하니 잘 정리하자!