OpenAI API 기반 자연어 SQL 쿼리 생성 시스템
사용자의 자연어 질문을 SQL로 변환하고 데이터베이스 조회까지 연결한 자연어 기반 데이터 분석 프로토타입
프로젝트 개요
이 프로젝트는 SQL을 모르는 사용자도 일상적인 문장으로 데이터에 질문할 수 있도록 만든 Natural Language to SQL 프로토타입입니다. 사용자가 “각 주(State)별 총매출의 합을 보여줘”라고 입력하면, OpenAI API가 데이터베이스 스키마를 바탕으로 SQLite 쿼리를 생성하고 애플리케이션이 해당 쿼리를 실행해 결과를 반환합니다.
실험 데이터로 Adidas US Sales Dataset을 사용했습니다. Excel 파일을 Pandas로 전처리하고 SQLAlchemy를 통해 메모리 기반 SQLite 데이터베이스로 옮긴 뒤, 자연어 입력부터 쿼리 생성과 조회 결과 확인까지 하나의 파이프라인으로 연결했습니다. 목표는 반복적인 SQL 작성을 줄이는 데 그치지 않고, 비개발자가 데이터에서 필요한 정보를 직접 찾고 이해할 수 있는 데이터 리터러시 도구의 가능성을 확인하는 것이었습니다.
처리 흐름
Excel 데이터 → Pandas 전처리 → SQLite 적재 → 스키마 기반 프롬프트 → OpenAI API → SQL 추출 → 데이터베이스 실행 → 결과 반환
- 데이터 준비: Excel 매출 데이터를 Pandas DataFrame으로 불러오고, 공백이 포함된 열 이름을 SQL에서 다루기 쉬운 형태로 정규화했습니다.
- 데이터베이스 구성: DataFrame을 SQLAlchemy로 메모리 기반 SQLite의
Sales테이블에 적재했습니다. - 스키마 전달: 테이블 이름과 전체 열 목록을 사용자의 질문과 결합해 모델이 실제 데이터 구조 안에서 쿼리를 작성하도록 했습니다.
- SQL 생성: 시스템 메시지에서 SQLite용 쿼리,
SELECT시작, 세미콜론 종료 등의 출력 조건을 지정했습니다. - 응답 처리 및 실행: 모델 응답에서 SQL 문장을 추출하고 SQLAlchemy의
text()로 실행한 뒤 조회 결과를 확인했습니다.
프롬프트 설계와 쿼리 생성
테이블 구조를 알 수 없는 모델은 존재하지 않는 열을 사용하거나 다른 SQL 방언을 섞을 수 있습니다. 이를 줄이기 위해 사용자 질문만 전달하지 않고 다음과 같이 스키마 정보를 함께 제공했습니다.
### SQLite table and its columns
Sales(
Retailer, Retailer_ID, Invoice_Date, Region, State, City,
Product, Price_per_Unit, Units_Sold, Total_Sales,
Operating_Profit, Operating_Margin, Sales_Method
)
Request: 각 State별 총매출의 합
모델은 이 요청에 대해 다음 SQL을 생성했습니다.
SELECT State, SUM(Total_Sales) AS Total_Sales_Sum
FROM Sales
GROUP BY State;
이 쿼리를 Sales 테이블에 실행해 Alabama, California, Florida 등 각 주의 매출 합계를 반환받았고, 자연어 입력부터 실제 데이터 조회까지 전체 흐름이 동작함을 확인했습니다.
구현 과정에서 해결한 문제
- Excel 로딩 의존성: Pandas가
.xlsx파일을 읽는 데 필요한openpyxl을 개발 환경에 추가했습니다. - 날짜 열 집계 오류:
groupby().sum()이datetime64열까지 집계하면서 발생한 오류를numeric_only=True로 숫자형 열에 한정해 해결했습니다. - SQL 실행 환경: 별도의 데이터베이스 서버 없이 흐름을 빠르게 검증할 수 있도록 SQLAlchemy와 메모리 기반 SQLite를 사용했습니다.
- API 호출 실패: 초기
429 insufficient_quota응답을 통해 API 키뿐 아니라 프로젝트의 결제 및 사용 한도 설정도 함께 관리해야 한다는 점을 확인했습니다. - 응답 형식 처리: 모델이 반환한 메시지 전체가 아니라 실행 가능한 SQL 부분만 분리하는 응답 처리 함수를 두었습니다.
결과와 배운 점
이 프로토타입을 통해 자연어 인터페이스가 SQL 작성의 진입 장벽을 낮출 수 있다는 점을 확인했습니다. 동시에 모델이 생성한 문자열을 곧바로 데이터베이스에서 실행하는 구조에는 프롬프트만으로 해결할 수 없는 위험이 있다는 것도 배웠습니다. 스키마를 구체적으로 제공하면 쿼리 정확도가 좋아지지만, 출력의 문법적·권한적 안전성은 애플리케이션이 별도로 검증해야 합니다.
실서비스로 확장한다면 읽기 전용 데이터베이스 계정, SELECT 단일 문장 허용, 대상 테이블과 열의 allowlist, SQL 파서 기반 검증, 실행 전 사용자 확인, 쿼리 시간 및 결과 행 수 제한을 추가할 계획입니다. 현재 OpenAI API가 제공하는 구조화·제약 출력 기능을 활용하더라도, 생성 결과는 서버에서 다시 검증해야 한다는 원칙은 동일합니다.
기술 스택
Python · Pandas · SQLAlchemy · SQLite · OpenAI API · Jupyter Notebook · openpyxl