예제로 알아보는 Text-to-SQL과 이를 활용한 정보 검색 및 QA

crowdworks
크라우드웍스 Tech Blog
10 min readJan 13, 2025
Text-to-SQL (created by ChatGPT 4o)

Text-to-SQL이란?

SQL

SQL(Structured Query Language)은 관계형 데이터베이스의 데이터를 체계적으로 관리하고 효율적으로 조작하기 위해 사용되는 언어입니다. 데이터를 저장, 조회, 수정, 삭제하는 기본적인 기능을 제공할 뿐만 아니라, 복잡한 데이터 간의 관계를 처리할 수 있어 데이터 관리에 핵심적인 역할을 합니다.

SQL의 주요 목적은 데이터베이스에 저장된 정보를 정확하고 신속하게 처리함으로써 비즈니스 의사결정이나 시스템 운영에 필요한 유의미한 데이터를 제공하는 것입니다. 특히, 방대한 양의 데이터를 체계적으로 관리하고, 필요한 정보를 즉시 검색할 수 있도록 도와주기 때문에 데이터 기반의 의사결정에서 필수적인 도구로 활용됩니다. 또한, SQL은 데이터의 일관성과 무결성을 유지하면서 여러 사용자와 애플리케이션이 동시에 데이터에 접근하고 사용할 수 있도록 지원합니다.

하지만, SQL 문법을 익히는 과정은 학습이 필요하며, 복잡한 질의문을 작성하는 것은 비전문가에게 큰 어려움으로 작용할 수 있습니다.

이러한 문제를 해결하기 위해 Text-to-SQL 기술이 등장했습니다. 이 기술을 활용하면 사용자가 자연어로 질문을 입력하는 것만으로도 자동으로 적합한 SQL 쿼리를 생성할 수 있어, SQL에 대한 전문 지식이 없어도 원하는 데이터를 손쉽게 조회할 수 있습니다.

Text-to-SQL

Text-to-SQL은 사용자가 자연어로 작성한 문장을 이해한 후, 이를 데이터베이스에서 실행 가능한 SQL 쿼리로 자동 변환하는 기술입니다. 이를 통해 SQL 문법이나 데이터베이스 구조에 대한 전문 지식이 없는 사용자도 일상적인 언어나 비즈니스 용어로 질문을 입력하면, LLM이 이를 분석하여 적합한 SQL 쿼리를 생성하고 필요한 정보를 데이터베이스에서 추출할 수 있습니다.

이 기술은 자연어 처리(NLP, Natural Language Processing)의 한 분야에 속합니다. 먼저, 자연어 처리 기술을 활용해 사용자가 입력한 문장의 의미와 의도를 정확히 파악합니다. 이후, 데이터베이스의 구조를 기반으로 연관된 테이블, 필드, 조건 등을 분석하고 이를 SQL 문법에 맞게 변환하여 최적의 쿼리를 자동으로 생성합니다.

Text-to-SQL은 사용자의 질문을 자연어로 이해하고 이를 정형화된 SQL 쿼리로 변환하는 과정을 자동화함으로써 데이터 접근성을 높이고, 기술적 장벽을 크게 낮춰줍니다. 특히 비전문가나 비개발자도 데이터베이스를 쉽게 활용할 수 있도록 돕기 때문에 기업 내 데이터 활용도를 더 높일 수 있습니다.

이러한 Text-to-SQL 과정은 일반적으로 어떤 과정으로 이루어질까요?

Text-to-SQL이 진행되는 과정

Text-to-SQL의 첫 번째 단계질문 입력입니다. 사용자는 자연스러운 문장 형태로 LLM에게 질의합니다.

두 번째 단계에서는 LLM이 질문을 이해하고 질문의 의도를 파악합니다. 그런데, 질문만 보고서는 LLM이 데이터베이스에서 어떤 table을 선택해야 하는지, 어떤 column들을 선택해야 하는지에 대해서 알 수 없습니다. 이런 것들을 알려주지 않는다면, LLM은 당연하게도 본인이 생각하는 적절한 table명이나 column명을 생성해서 이야기할 것입니다. 그렇게 된다면, LLM은 DB에 존재하지 않는 table이나 column 이름을 포함한 SQL 쿼리를 작성하게 될 것이고, 이는 실행 시 오류를 발생시킬 것입니다.

때문에, 정확한 SQL 쿼리를 만들기 위해서 LLM은 이 과정에서 데이터베이스의 구조(table과 column 정보)를 추가적으로 입력으로 받아 데이터베이스에 대한 정보 속에서 어떤 table과 column이 필요한지 판단합니다.

마지막으로, 필요하다고 판단되어 선택된 table과 column 정보를 바탕으로 SQL 쿼리가 생성됩니다. LLM은 입력된 질문의 의미를 반영하여 적절한 SQL 쿼리를 작성하고, 이를 데이터베이스에 실행해 결과를 반환합니다.

위의 세 단계를 간단한 예시를 통해 다시 한 번 설명 드리겠습니다. 우선, 사용자가 “지난해 가장 높은 매출을 기록한 제품은?”과 같은 질문을 입력한다고 생각해봅시다.

첫 번째 단계에서, LLM은 이 문장을 분석할 준비를 합니다.

두 번째 단계에서, LLM은 사용자의 질문을 분석한 후, 질문에서 ‘지난해’, ‘매출’, ‘제품’ 등의 핵심 키워드를 파악하고, 질문을 해결하기 위해 데이터베이스에서 어떤 table을 선택할지, 선택한 table에서 어떤 column을 참고할지를 결정하게 됩니다. 이 예시에서는 상품과 관련된 table과 연도, 매출에 관련된 column을 선택하게 될 것입니다.

마지막 단계에서, LLM은 이전 단계에서 얻은 정보들을 토대로 질문을 아래와 같은 SQL 쿼리로 변환하여 데이터베이스에 질의합니다.

SELECT product_name  
FROM sales
WHERE year = 2023
ORDER BY revenue DESC
LIMIT 1;

위의 쿼리를 실행하게 되면, 상품 테이블(sales)에서 2023년(year)인 데이터만 가져온 후, 매출(revenue)를 기준으로 내림차순 정렬(DESC)하여 가장 맨 위에 가장 높은 매출을 기록한 제품(product_name)을 가져오게 되는데, 이는 사용자가 질문에서 의도한 바와 일치합니다.

다음으로는 저희가 Text-to-SQL을 사용했던 부분의 예제를 통해 Text-to-SQL의 진행과정에 대해 더 자세히 알아보며, 그 속에서 저희가 Text-to-SQL 기술을 활용한 방법에 대해 설명드리겠습니다.

Text-to-SQL를 활용한 예제

접근 방법

저희는 문제를 해결하기 위해 우선, 사용자의 질문을 두 개의 분기로 나누었습니다. 각 분기에 대한 설명은 아래와 같습니다.

분기 A: 사용자들이 자주 사용하는 주제에 대한 것들을 처리하는 분기입니다. 정보를 알고 싶어 하는 대상이 명확하게 특정되어 있는 것이 포함됩니다.
ex) XXX의 나이가 어떻게 돼? / YYY의 거주지 알려줘.

분기 B: 분기 A 이외의 복잡한 주제에 대한 질문들을 처리하는 분기입니다. 정보를 알고 싶어 하는 대상이 명확하게 특정되어 있지 않고, 조건들로 정보를 찾는 질문들이 주로 포함됩니다.
ex) XXX와 나이가 비슷한 사람들 알려줘 / 50대들 중 서울에 사는 사람 알려줘.

분기 설명 이미지

저희는 기존 Text-to-SQL에서 진행하는 다양한 부수적인 작업들(메타데이터 테이블 정의, 카테고리 정의 등)이 속도 면에서 영향을 끼칠 수도 있다고 생각했습니다.

때문에, 질문이 들어왔을 때 사용자들이 자주 사용하는 주제들을 처리하는 분기 A와 이외의 복잡한 질문들을 처리하는 분기 B, 두 갈래로 분기를 나누어 질문을 처리하고자 했습니다.

분기 A에 대해서는 세부적인 케이스들로 질문을 나눈 뒤 각 케이스마다의 SQL 쿼리 템플릿을 만들어 SQL 쿼리를 생성하는 방식을, 분기 B에 대해서는 일반적인 Text-to-SQL 과정을 사용하는 방식을 택했습니다.

분기 A는 활용 빈도가 높기 때문에 속도와 정확성이 매우 중요하다고 볼 수 있습니다. 그렇기 때문에, 예상되는 케이스들을 선정하여 각 케이스마다의 SQL 쿼리 템플릿을 사용하는 것이 속도와 정확성 면에서 더 좋은 성능을 가질 것이라 판단했습니다.

케이스를 선정하는 방식은 LLM을 사용하여 진행했는데요, 각 케이스에 대한 간단한 설명들을 담은 프롬프트를 통해 사용자의 질문이 어떤 케이스들에 맞는지를 확인한 후, 각 케이스들에 대한 SQL 쿼리 템플릿을 선정했습니다.

세부 케이스를 선택하여 SQL 쿼리 템플릿을 사용하는 프로세스가 어떻게 보면 Function call과 비슷한 느낌이라고도 볼 수 있는데요, Function call도 LLM이 미리 정의된 함수와 해당 함수의 설명을 보고 어떤 task가 들어왔을 때 이 task를 해결할 수 있는 가장 최적의 function을 찾는 방식이기 때문입니다.

Function call

Function call과 같이, 분기 A에서는 사용자의 질문이 들어오면 해당 질문을 가장 잘 처리할 수 있는 case를 LLM을 통해 찾고, 해당 case와 매칭되는 SQL 템플릿을 찾아 적용해 SQL 쿼리를 만듭니다.

분기 B는 분기 A 이외의 복잡한 주제에 대한 질문들을 처리하는 분기입니다. 이 분기에서는 템플릿을 정의하지 않고 LLM이 처음부터 끝까지 SQL 쿼리를 작성하도록 했습니다.

우선, 질문이 들어오면 LLM이 이 질문에 대해 답변하기 위해 DB에서 어떤 table을 써야하고, 해당 table들에서 어떤 column들을 조회해야하는 지 판단하는 과정을 거칩니다.

이후, 해당하는 table과 column에 대한 메타데이터 테이블을 정의하게 되는데요, 이 메타데이터 테이블에는 table명, column 한글/영문명, column에 대한 한글/영문 설명 등이 포함되어 있습니다.

그리고, 이 메타데이터 테이블과 질문을 토대로 LLM이 어떤 table을 선정해야 하는지, 각 table에서 어떤 column을 선정해야 질문에 답할 수 있을지에 대한 판단을 한 후, 선정된 요소들을 JSON 형태로 추출합니다.

이후, 추출된 JSON과 질문을 토대로 SQL 쿼리를 생성하게 됩니다.

저희는 이 SQL 쿼리를 만드는 과정에서 추가적으로, SQL 쿼리가 오류가 나지 않는 유효한 SQL 쿼리인지 체크하는 로직을 추가하여 Text-to-SQL의 안정성을 높였습니다. 생성된 SQL 쿼리를 DB에 사용했을 때, 오류가 난다면 SQL 생성 프롬프트에 검증 프롬프트를 추가하는 방식입니다.

결과

결과적으로, 저희는 질문에 대해 두 가지 분기를 만들어서 분리함으로써 정확도와 속도를 더욱 향상시킬 수 있었습니다. 이러한 접근은 보다 효율적이고 신뢰성 있는 결과를 도출하는 데 큰 도움이 되었습니다.

마치며

Text-to-SQL 기술은 자연어를 사용해 데이터베이스에서 필요한 정보를 쉽게 추출할 수 있도록 도와줍니다. SQL 문법을 몰라도 원하는 질문을 던지기만 하면 자동으로 쿼리를 생성해 주기 때문에, 일반인들의 데이터 분석 진입 장벽을 낮추고 상당수 개발자에 의존할 수 밖에 없었던 기업내 업무의 효율성을 극대화할 수 있습니다. Text-to-SQL 기술의 등장이 데이터베이스가 DBA(Database Administrator, 데이터베이스 관리자)나 개발자의 전유물이 아닌 모든 회사내 인원들이 언제나 접근하고 편하게 원하는 데이터를 추출할 수 있게 되는 전환점이 되는 것입니다.

이를 통해서 현업 업무 인원들은 원하는 데이터에 대한 접근성을 개선하고 원하는 데이터에 대한 리드타임을 현격하게 줄일수 있게 되고, 개발자나 DBA는 어떻게 보면 그때 그때 한번 필요한 Ad-hoc SQL을 작성하는 업무에서 해방되어 좀더 서비스나 코어 로직 개발에 집중할 수 있게 되는거죠.

아직 Text-to-SQL 기술은 연구개발해야 할 부분이 많고 이제 조금씩 다양한 분야에 적용되고 있습니다. 하지만, 더 발전하고 보편화된다면 많은 사람들이 데이터의 힘을 보다 쉽게 활용할 수 있을 것으로 기대됩니다. 이를 통해 더 많은 가능성이 열리고, 생산적인 결과를 만들어내는 데 큰 도움이 될 것입니다.

--

--

No responses yet