RSS
데이터베이스

Text-to-SQL 정확도는 왜 실무 DB에서 떨어질까?

작성자
듀오랩스 대표·20분 읽기

「지난 분기 매출 상위 고객 10곳」을 물었더니 모델이 깔끔한 SQL을 돌려줍니다. JOIN도 맞고 GROUP BY도 맞고 실행도 됩니다. 그런데 그 숫자를 재무팀 보고서와 나란히 놓으면 맞지 않습니다. 환불이 빠지지 않았을 수도 있고, 부가세가 들어갔을 수도 있고, 회사의 회계 분기가 달력 분기와 다를 수도 있습니다. 쿼리는 문법적으로 완벽한데 답은 틀린 상태입니다.

Text-to-SQL을 두고 흔히 이렇게 생각합니다. LLM이 SQL을 잘 쓰니 DB만 연결해 주면 누구나 자연어로 데이터를 물을 수 있고, 남은 정확도 문제는 다음 모델이 풀어 줄 것이라고요. 저는 이 그림이 절반만 맞다고 봅니다. SQL 문법은 이미 거의 풀린 문제에 가깝습니다. 실무 스키마에서 정답률을 깎아 먹는 것은 「매출」이 어느 열인지, 어떤 경로로 조인해야 하는지, 회계 분기가 언제 시작하는지 같은 업무 문맥입니다. 이 글은 그 차이를 벤치마크 논문과 리더보드의 숫자로 따라가고, 문맥을 채우는 방법과 틀린 쿼리가 비싸지지 않게 막는 설정까지 이어 봅니다.

실무에 가까운 벤치마크일수록 떨어지는 정답률

Text-to-SQL 연구에는 세대를 나누는 벤치마크가 셋 있습니다. 2018년의 Spider 1.0은 200개 DB, 138개 도메인에서 질문 10,181개와 SQL 5,693개를 모았습니다. 학습과 평가에 서로 다른 DB를 쓰게 해서 처음 보는 스키마에 일반화하는 능력을 재려 했고, 당시 최고 모델의 정확 일치(exact match) 정답률은 12.4%였습니다.

2023년 NeurIPS에 나온 BIRD는 초점을 스키마에서 값으로 옮겼습니다. 95개 DB, 합계 33.4GB, 37개 전문 분야에 질문과 SQL 12,751쌍입니다. 논문이 강조하는 것은 지저분한 실제 값, 질문과 값 사이를 잇는 외부 지식, 그리고 큰 DB에서의 쿼리 효율입니다.

2024년 11월에 공개되고 ICLR 2025에 실린 Spider 2.0은 한 단계 더 나갑니다. 기업 환경에서 가져온 632개 작업이고 DB는 BigQuery, Snowflake 같은 클라우드 웨어하우스에 있습니다. 논문 본문 기준으로 DB 하나에 평균 812개 열이 있고, 정답 SQL 하나가 평균 144토큰입니다.

같은 모델을 세 벤치마크에 올리면 차이가 뚜렷합니다. Spider 2.0 논문(2025년 3월 개정판) 초록은 o1-preview 기반 에이전트가 Spider 2.0 작업의 21.3%만 풀었다고 보고하면서, 같은 방식이 Spider 1.0에서 91.2%, BIRD에서 73.0%를 낸 것과 나란히 놓습니다. 프로젝트 사이트의 소개 문구에는 o1-preview 17.1%, GPT-4o는 Spider 2.0 10.1% 대 Spider 1.0 86.6%로 적혀 있는데, 논문 개정 전의 수치로 보입니다. 어느 쪽을 보든 같은 모델이 연구용 스키마에서 90점 안팎을 내다가 기업 스키마에서 10~20점대로 내려앉았다는 결론은 같습니다.

벤치마크 발표 무엇을 재나 논문이 보고한 대표 수치
Spider 1.0 2018 처음 보는 스키마로의 일반화 당시 최고 모델 12.4% (exact match)
BIRD NeurIPS 2023 지저분한 값, 외부 지식, 효율 GPT-4 54.89%, 사람 92.96% (테스트, 힌트 제공 시)
Spider 2.0 ICLR 2025 기업 웨어하우스 작업 흐름 o1-preview 21.3% (같은 방식 Spider 1.0 91.2%, BIRD 73.0%)

힌트 한 줄에 20점이 움직이는 BIRD의 결과

BIRD에서 가장 눈여겨볼 표는 모델 순위가 아니라 「외부 지식 증거(evidence)」를 줬을 때와 안 줬을 때의 차이입니다. BIRD는 질문마다 사람이 쓴 힌트 문장을 하나씩 붙여 두었습니다. 논문은 이 힌트를 넷으로 나눕니다. 비율이나 차이를 구하는 수식 지식, 은행의 투자수익률처럼 업계에서만 통하는 도메인 지식, 같은 뜻의 다른 표현을 잇는 동의어 지식, 그리고 값 설명입니다. 값 설명의 예로 논문은 농구 DB에서 「센터」가 pos = 'C'로 저장되어 있다는 사실을 듭니다. 전체 질문의 70.1%가 이런 값 설명을 필요로 했습니다.

논문의 표 2를 보면 GPT-4는 테스트셋에서 힌트 없이 34.88%, 힌트를 주면 54.89%입니다. 20점이 힌트 한 줄로 움직였습니다. 사람의 점수도 같이 봐야 합니다. 데이터 엔지니어와 DB 전공 학생으로 꾸린 사람 평가도 힌트 없이 72.37%, 힌트를 주면 92.96%였습니다. 사람도 「센터가 C로 저장된다」는 걸 모르면 틀립니다.

저는 이 표가 Text-to-SQL에 대한 오해를 가장 짧게 바로잡는다고 봅니다. 문맥 없이 사람이 72점인 과제에서 모델이 90점을 내길 기대하는 것은 모델에게 독심술을 요구하는 일입니다. 정확도 문제의 상당 부분은 모델 성능이 아니라 질문과 DB 사이에 빠져 있는 정보의 문제입니다.

2026년 리더보드 상위 점수가 전제하는 조건

논문이 나온 뒤 숫자는 많이 올랐습니다. 2026년 10월 9일에 연 BIRD 리더보드의 테스트셋 실행 정확도 1위는 2026년 9월 26일자로 올라온 GrainSQL의 82.95%이고, 사람 기준선은 여전히 92.96%입니다. 다만 상위 항목에는 「Oracle Knowledge」 표시가 붙어 있습니다. 사람이 써 준 힌트 문장을 받고 낸 점수라는 뜻입니다. 운영진도 같은 문제를 의식하고 있습니다. 2025년 11월 13일 공지에서 모호함을 다루는 대화형 트랙을 열고 그 대신 Oracle Evidence를 없애겠다고 밝혔습니다.

Spider 2.0 리더보드는 설정이 셋으로 나뉩니다. Snowflake 하나에 547문제를 올린 Spider 2.0-Snow의 1위는 Genloop의 Sentinel Agent v2 Pro로 96.70점(2026년 3월 1일 등록)입니다. BigQuery, Snowflake, SQLite에 걸친 547문제의 Spider 2.0-Lite 1위는 Tencent의 Tianqiong Data Agent + GLM 5.2로 76.23점(2026년 7월 28일 등록), dbt 프로젝트를 다루는 68문제짜리 Spider 2.0-DBT 1위는 SignalPilot Agent로 65.6점(2026년 5월 29일 등록)입니다. 페이지는 평가 지표를 계속 점검하고 있어 점수가 조금씩 바뀔 수 있다고 적어 둡니다.

21.3%가 2년이 안 돼 96.70%가 된 것을 「모델이 좋아져서」로만 읽으면 다시 같은 오해로 돌아갑니다. 리더보드는 Spider 2.0-Snow를 「잘 준비된 DB 메타데이터와 문서를 포함한」 설정이라고 소개합니다. 상위 제출물의 이름에는 대부분 「Agent」가 붙어 있고, 소속은 Genloop, Tencent, Paytm 같은 기업 팀입니다. 모델 하나에 질문을 던진 결과가 아니라 여러 단계를 엮은 시스템의 점수라는 뜻입니다. 세 방언에 걸친 Lite 설정에서는 1위가 70점대에 머뭅니다. 저는 리더보드 점수를 이만큼 준비했을 때 닿는 상한으로 읽고, 사내 웨어하우스에 범용 모델을 그냥 붙였을 때의 기대치로 옮겨 오지 않습니다. 개별 제출물이 정확히 무엇을 했는지는 팀마다 공개 수준이 달라 확인할 수 없는 부분이 많습니다.

SQL 문법보다 업무 용어와 조인에서 나오는 오답

Spider 2.0 논문은 오답 300건을 직접 분류했습니다. 가장 큰 덩어리는 잘못된 데이터 분석(35.5%)으로, 방언 함수를 잘못 쓰거나(10.3%) 여러 단계의 CTE와 중첩 쿼리를 제대로 계획하지 못한 경우(17.7%)입니다. 그다음이 잘못된 스키마 연결(27.6%)입니다. 엉뚱한 열을 고른 경우가 16.6%, 엉뚱한 테이블이 10.1%였습니다. 논문은 Spider 2.0-Lite의 DB당 평균 열 수가 755개를 넘는데 BIRD는 약 54개라는 점을 원인으로 듭니다. 조인 오류도 8.3%였고, 이유가 눈에 띕니다. BigQuery의 DB에는 외래 키가 명시되지 않은 경우가 많아서 모델이 열 이름과 설명만 보고 조인 키를 추측해야 했다는 것입니다.

반대로 문법 지식을 채워 주는 효과는 작았습니다. 논문은 문제마다 필요한 SQL 함수 문서를 사람이 골라 넣어 주는 실험을 했는데 성능이 「약간」 올랐을 뿐이라고 적습니다. 모델은 함수 쓰는 법을 이미 알고 있고, 막히는 곳은 요구사항을 그 함수로 옮기는 단계라는 해석입니다.

사내 DB로 옮겨 오면 이 목록은 더 익숙해집니다. amount, total, net_amount가 나란히 있으면 어느 것이 매출인지는 스키마가 알려 주지 않습니다. status = 3이 취소인지 환불인지도 코드표를 봐야 압니다. 회계연도가 4월에 시작하는 회사라면 「1분기」라는 말 자체가 번역이 필요합니다. 삭제 표시가 된 행을 빼야 하는지, 테스트 계정을 걸러야 하는지 같은 규칙은 대개 누군가의 머릿속이나 대시보드 SQL 안에만 있습니다. 모델이 이것을 틀리는 것은 SQL을 몰라서가 아니라 정보를 받은 적이 없어서입니다.

모델 밖에서 채우는 문맥: 열 설명, 검증된 쿼리, 시맨틱 레이어

정확도를 올리는 손잡이는 대부분 모델 바깥에 있습니다. 가장 먼저 손댈 곳은 스키마 연결입니다. 수백 개 테이블을 통째로 프롬프트에 넣으면 문맥 창이 차기 전에 모델의 주의가 먼저 흩어집니다. 질문과 관련 있는 테이블과 열만 먼저 골라 넣는 단계를 두는 이유입니다. Spider 2.0 리더보드는 정답 테이블을 미리 받은 제출물을 따로 표시하고 순위에서 빼는데, 저는 이것을 어느 테이블을 볼지 아는 것만으로도 점수가 크게 달라진다는 신호로 읽습니다. BIRD 원 논문이 당시 최고 기록으로 소개한 DIN-SQL도 값 샘플링, 예시 쿼리, 자기 수정을 묶은 프롬프트 기법이었습니다.

열과 값에 설명을 붙이는 일은 BIRD가 직접 보여 줍니다. BIRD는 DB마다 「설명 파일」을 따로 두었습니다. 논문은 테이블과 열 이름이 줄임말이라 알아보기 어렵고, 질문의 낱말이 DB 값과 직접 맞지 않을 때 값 설명이 특히 쓸모 있다고 적습니다. 사내 DB라면 Postgres의 COMMENT ON COLUMN이든 데이터 카탈로그든, 모델이 읽을 수 있는 곳에 「이 열은 환불 차감 후 금액」이라고 한 줄 적어 두는 것이 가장 싼 개선입니다.

사람이 검증한 질문과 SQL 쌍도 좋은 문맥입니다. 매출, 활성 사용자, 이탈률처럼 자주 묻는 질문에 대해 데이터팀이 맞다고 확인한 쿼리를 몇 개 보여 주면, 모델은 조인 경로와 필터 규칙을 그 예시에서 베낍니다. 질문이 늘수록 이 예시 묶음이 사실상 회사의 지표 정의서가 됩니다.

그 정의를 아예 코드로 고정하는 방법이 시맨틱 레이어입니다. dbt Semantic Layer 문서는 MetricFlow로 매출 같은 핵심 지표를 모델링 계층에 한 번 정의하고, 정의가 바뀌면 그것을 부르는 모든 곳에 반영된다고 설명합니다. 같은 문서는 AI 도구가 dbt MCP 서버로 Semantic Layer에 붙으면 날것의 테이블을 추측하는 대신 관리되는 지표를 쓰게 된다고 적습니다. 이 방식에서 모델은 SQL을 처음부터 쓰지 않고 「어떤 지표를 어떤 차원으로 자를지」만 고릅니다. 자유도가 줄어드는 만큼 틀릴 여지도 줄어듭니다. 저는 비개발자에게 자연어 질의를 열어 줘야 한다면 이쪽이 출발점이라고 봅니다.

되묻기와 실행 후 수정이 각각 잡는 오류

문맥을 다 채워도 남는 오류가 있고, 이것을 잡는 장치는 두 가지입니다. 하나는 쿼리를 실제로 실행해 보고 오류 메시지를 읽어 다시 쓰게 하는 자기 수정입니다. 없는 열을 참조했거나 방언에 없는 함수를 썼다면 DB가 바로 오류를 돌려주므로, 모델은 그 메시지를 근거로 고칩니다. 실행 전에 EXPLAIN으로 계획만 받아 보면 데이터를 읽지 않고도 참조 오류를 걸러 냅니다.

이 고리가 잡지 못하는 오류가 더 위험합니다. 실행은 되는데 뜻이 틀린 쿼리입니다. 환불을 빼지 않은 매출 합계는 오류 없이 숫자를 돌려주고, 모델은 그 숫자가 틀렸다는 신호를 받지 못합니다. 결과가 0행이거나 터무니없이 크면 다시 보게 하는 규칙은 둘 만하지만, 그럴듯한 오답은 그 그물에도 걸리지 않습니다.

그 빈틈을 메우는 것이 되묻기입니다. 「매출」이 순매출인지 총매출인지, 「지난 분기」가 회계 분기인지 묻고 나서 쿼리를 쓰면 뜻이 틀릴 여지가 줄어듭니다. 문제는 모델이 아직 이것을 잘하지 못한다는 점입니다. BIRD 운영진이 만든 대화형 벤치마크 BIRD-Interact에 대해 BIRD 리더보드 공지(2025년 10월 9일)는 GPT-5(Med)가 전체 과제에서 c-Interact 8.67%, a-Interact 17.00%의 성공률에 그쳤다고 적었습니다. 같은 공지는 상호작용과 소통이 모델을 믿을 만한 조수로 만드는 데 결정적이라는 것을 핵심 발견으로 꼽습니다. 모호한 요청을 받았을 때 무엇을 물어야 하는지 아는 능력이 Text-to-SQL에서 가장 덜 풀린 부분이라고 저는 봅니다.

틀린 쿼리가 비싸지지 않게 DB가 막는 설정

정확도를 아무리 올려도 틀린 쿼리는 나옵니다. 그래서 모델이 만든 SQL은 처음부터 「틀릴 수 있는 입력」으로 보고, 틀렸을 때의 피해를 DB 설정으로 묶어 둡니다. 모델에게 「SELECT만 써라」, 「LIMIT을 붙여라」라고 이르는 것은 가장 약한 장치입니다. 모델이 지시를 어길 수도 있고, 지시를 지킨 쿼리가 여전히 비쌀 수도 있습니다.

-- 자연어 질의 전용 역할: 아무 권한도 없는 상태에서 필요한 것만 연다
CREATE ROLE nlq_reader LOGIN;
GRANT USAGE ON SCHEMA analytics TO nlq_reader;
GRANT SELECT ON analytics.orders, analytics.customers TO nlq_reader;

-- 세션 기본값: 읽기 전용, 문장당 30초, 잠금 대기 5초
ALTER ROLE nlq_reader SET default_transaction_read_only = on;
ALTER ROLE nlq_reader SET statement_timeout = '30s';
ALTER ROLE nlq_reader SET lock_timeout = '5s';

이 예시에서 쓰기를 실제로 막는 것은 GRANT SELECT입니다. ALTER ROLE ... SET으로 건 값은 세션의 기본값이라 세션 안에서 SET으로 다시 바꿀 수 있으므로 보조 장치로 봅니다. 그래도 기본값은 꼭 걸어 둡니다. Postgres 18 문서에 따르면 statement_timeout의 기본값은 0, 즉 제한 없음이고, default_transaction_read_only의 기본값은 off입니다. 아무것도 설정하지 않은 역할로 질의를 받으면 시간 제한 없는 읽기·쓰기 계정이 됩니다. 읽기 전용 트랜잭션에 대해서도 문서는 「높은 수준의 읽기 전용 개념」이라 디스크 쓰기를 모두 막지는 않는다고 적습니다. 무거운 분석 쿼리가 서비스 트래픽과 다투지 않게 하려면 운영 DB 대신 읽기 복제본에 연결합니다.

행 수 제한은 두 가지를 나눠서 봐야 합니다. 돌려줄 행을 줄이는 것과 DB가 읽는 양을 줄이는 것입니다. 앞의 것은 애플리케이션이 결과를 받아 올 때 상한을 걸면 됩니다. 뒤의 것은 LIMIT으로 해결되지 않는 경우가 많습니다. BigQuery 비용 모범 사례 문서는 클러스터링되지 않은 테이블에서는 LIMIT을 붙여도 계산 비용이 줄지 않는다고 적고, 대신 「maximum bytes billed」 설정을 권합니다. 실행 전에 읽을 바이트를 추정해 한도를 넘으면 요금 없이 실패시키는 장치입니다. 종량제 웨어하우스에서는 이 한도가 사실상 질의 하나의 예산입니다.

질문하는 사람마다 볼 수 있는 행이 다르다면 행 수준 보안을 겁니다. 다만 문서는 슈퍼유저와 BYPASSRLS 속성을 가진 역할은 항상 RLS를 건너뛰고, 테이블 소유자도 FORCE ROW LEVEL SECURITY를 걸지 않으면 대개 건너뛴다고 적습니다. 질의용 역할이 테이블 소유자도 관리자도 아니어야 RLS가 의미를 가집니다. 질문 원문, 생성된 SQL, 실행한 사람을 함께 기록해 두면 틀린 숫자가 보고서에 올라갔을 때 어느 단계에서 어긋났는지 되짚을 수 있습니다.

분석가의 도구로는 쓸 만하고 셀프서비스로는 이른 단계

여기서부터는 제 판단입니다. 지금 Text-to-SQL이 확실히 값을 하는 곳은 SQL을 읽을 줄 아는 사람이 결과를 검증하는 환경입니다. 분석가나 개발자가 초안 쿼리를 받아 조인과 필터를 눈으로 확인하고 고쳐 쓰는 용도라면, 모델이 틀려도 사람이 잡고 맞으면 시간을 아낍니다. 테이블이 수십 개 이하이고 열 설명과 검증된 예시 쿼리가 갖춰진 좁은 도메인, 예를 들어 한 팀이 소유한 운영 지표 DB나 사내 도구의 조회 화면도 무리가 없는 범위로 봅니다.

위험한 쪽도 분명합니다. 첫째는 SQL을 읽지 못하는 사람에게 날것의 기업 스키마를 열어 주는 셀프서비스입니다. 문법적으로 완벽한데 뜻이 틀린 쿼리는 오류를 내지 않고 그럴듯한 숫자를 돌려주고, 질문한 사람은 그 숫자가 틀렸다는 것을 알아챌 방법이 없습니다. BIRD에서 힌트 없는 사람이 72점이었다는 사실을 떠올리면, 문맥 정비 없이 이 문을 여는 것은 이릅니다. 이 경우라면 저는 SQL 생성보다 시맨틱 레이어 위에서 지표와 차원만 고르게 하는 쪽을 택하겠습니다. 둘째는 생성된 SQL이 쓰기 권한을 가진 계정으로 실행되는 모든 구성입니다. 조회 질문에 쓰기 권한은 필요 없고, 필요 없는 권한은 사고가 났을 때 피해만 키웁니다.

확신이 끝나는 지점도 적어 둡니다. 리더보드 상위 시스템들의 점수가 실제 사내 웨어하우스에서 얼마나 재현되는지는 공개된 자료로 판단하기 어렵습니다. 벤치마크는 질문이 모호하지 않도록 다듬어져 있고, Spider 2.0 논문도 주석자 최소 세 명이 지시문의 정확성과 모호하지 않음을 검토했다고 적습니다. 현실의 질문은 그렇게 다듬어져 오지 않습니다. 되묻는 능력이 얼마나 빨리 좋아질지도 저는 아직 판단하지 못하겠습니다. AI 기능이 결국 관계형 DB 안으로 흡수되는 흐름은 그래프 DB가 RDB를 대체할까? 숫자로 본 2026년 데이터베이스 흐름에서 다뤘는데, 자연어 질의도 같은 길을 걷는다면 그때 DB가 함께 내놓아야 할 것은 SQL 생성기보다 열 설명과 지표 정의, 그리고 질의 전용 역할일 것이라고 봅니다.

마지막 수정:

공유하실 때는 출처(Duolabs)와 원문 주소를 표시해 주세요.