
데이터팀/BI팀이 아니더라도 “지난달 결제 전환율이 뭐야?” 같은 질문을 자연어로 던지면, 시스템이 알아서 SQL을 만들고 DB에서 조회해 결과를 보여주는 흐름이 Text-to-SQL입니다. 핵심은 단순히 SQL을 생성하는 게 아니라, 스키마를 정확히 이해하고(정확도), 실행 가능한 쿼리만 만들고(신뢰성), 권한/보안까지 지키는 것(안전성)입니다.
Text-to-SQL은 사용자의 자연어 질문(NL Query)을 데이터베이스가 이해할 수 있는 SQL로 변환하는 기술/시스템입니다. (최근엔 LLM + RAG + 검증 루프 형태가 사실상 표준 패턴이 되어가고 있어요.)
1) 스키마 인지 부족: 테이블/컬럼이 수백~수천 개면 LLM이 “어떤 컬럼이 실제로 존재하는지”부터 헷갈립니다. 그래서 스키마 인코딩/링킹이 중요해졌고, 이 축을 강하게 다룬 연구가 RAT-SQL 입니다. 이 논문은 “보지 못한 스키마(새 DB)에 일반화”가 핵심 난점임을 명시합니다. Source
2) 문법적으로 깨진 SQL: LLM은 종종 괄호, JOIN, GROUP BY 조건 등을 틀려서 실행 불가 SQL을 내놓습니다. 이를 “디코딩 단계에서” 강제 제약으로 막는 접근이 PICARD 입니다(토큰을 한 글자/조각씩 뽑을 때, 불가능한 토큰을 거부). Source
3) 보안/권한 문제(특히 SQL Injection + 데이터 유출): Text-to-SQL은 “사용자 입력 → SQL” 경로가 생기기 때문에, 검증/권한/파라미터 바인딩 같은 전통 보안 원칙을 그대로 적용해야 합니다. OWASP는 Prepared Statement(파라미터 쿼리), Stored Procedure(안전 구성), Allow-list 검증 등을 핵심 방어로 권고합니다. Source
Text-to-SQL 성능 비교에서 가장 유명한 벤치마크 중 하나가 Spider 입니다. 단순 문자열 비교가 아니라 SQL을 절(clause) 단위로 분해해 set 비교를 하는 등 구조적 정확도를 보려는 평가 체계를 제공합니다. Source
이미지 출처: Yale LILY Lab Spider
아래는 “그냥 LLM에 물어보기”를 넘어, 실제 제품에서 안정적으로 굴리는 권장 아키텍처입니다.
flowchart LR
U[User Question] --> G[Guardrails: intent/permission check]
G --> R[Schema & Context Retrieval (RAG)]
R --> P[Prompt Builder: schema + examples + constraints]
P --> L[LLM SQL Generation]
L --> V[Validator: parse / lint / dry-run]
V -->|OK| X[Execute (read-only) + postprocess]
V -->|Error| F[Feedback: error message + retry loop]
F --> L
Google Cloud는 Text-to-SQL 정확도를 올리기 위해 (1) 관련 테이블/컬럼의 지능형 검색(벡터 검색 등), (2) 비즈니스 예시를 ICL로 제공, (3) 데이터 샘플링/시맨틱 레이어, (4) self-consistency(여러 후보 생성 후 선택), (5) dry-run/파싱 기반 검증 후 재작성 같은 기법을 조합한다고 정리합니다. Source

이미지 출처: Google Cloud Blog
AWS는 견고한 Text-to-SQL을 위해 (1) DB 메타데이터 기반 RAG, (2) 멀티스텝 self-correction loop, (3) SQL 엔진(Athena)에서 에러를 받아 재프롬프트를 핵심 구성요소로 설명합니다. 즉 “LLM이 SQL을 만들고 → 엔진이 문법/실행 오류를 주고 → 그 오류를 다시 LLM에 먹여 고치게 하는” 반복 구조입니다. Source

이미지 출처: AWS Machine Learning Blog
sql, reason, tables_used 등)예시(개념):
You are a data assistant. Generate a single SQL query.
Rules:
- Read-only SELECT only. No INSERT/UPDATE/DELETE/DDL.
- Must include LIMIT 100 unless user asks otherwise.
- Use only the provided schema. Do not hallucinate columns.
Schema:
- orders(order_id, user_id, created_at, total_amount, status)
- users(user_id, signup_date, country)
Question:
"지난 30일간 국가별 매출 합계를 보여줘"
권장 검증 체크리스트:
Google Cloud도 dry-run/파싱으로 결정적 신호를 얻고, 이를 재작성 프롬프트로 넣는 방식을 강조합니다. Source
Text-to-SQL은 “LLM이 SQL을 만든다”는 특수성이 있어도, 보안 원칙은 바뀌지 않습니다.
실무 팁(자주 먹히는 조합):
SELECT * 금지, 특정 테이블 접근 금지)1) 스키마/메타데이터 RAG부터 붙이기 (정확도 체감이 큼)
2) 검증(dry-run) + 에러 피드백 루프로 “실행 가능 SQL” 만들기
3) 권한/보안(OWASP + 최소권한)을 제품 요구사항으로 고정
4) 이후 self-consistency, 예시 학습(ICL), 시맨틱 레이어로 고도화 Source
원하시면, 사용 중인 환경에 맞춰서(예: BigQuery / Postgres / MySQL, 또는 dbt/semantic layer 유무) 프롬프트 템플릿 + RAG에 넣을 “스키마 요약 포맷” + 검증/재시도 정책까지 한 번에 블로그용 예제로 다듬어드릴게요. 어떤 DB와 SQL 방언을 쓰시나요?