NL2SQL
NL2SQL(Natural Language to SQL)은 사용자가 일상적인 자연어(한국어, 영어 등)로 질문을 입력하면, 인공지능이 이를 분석하여 데이터베이스를 조회할 수 있는 SQL 쿼리로 자동 변환해 주는 기술입니다.
시스템 아키텍처
NL2SQL은 3계층 그래프 구조로 동작합니다. 상위 계층이 작업을 분해해 하위 계층으로 위임하는 방식입니다.
| 계층 | 이름 | 역할 |
|---|---|---|
| Tier 1 | Parent Graph | 사용자 질문을 분해해 N개의 Sub-Graph로 분배하고, 최종 결과를 통합 |
| Tier 2 | Sub-Graph | 분해된 단일 질문에 대해 IR → Generate → Correct → Execute 순으로 SQL 처리 |
| Tier 3 | Nested Graph (SQL Generator) | 테이블 단위로 SQL 생성 작업을 분할/검증/병합 |
운영 프로세스
NL2SQL 시스템 운영은 3단계 워크플로우로 진행됩니다.
DB 환경 설정 → 프로파일링 → Agent 배포(옵션)
agent-server-api에 docker exec -it로 도커 내부에서 CLI를 통해 1,2,3 단계를 수행할 수 있습니다.
docker 내부에 접속한 이후,
# 대화형 메뉴
python /app/graphs/nl2sql_agent/CLI_TOOL/nl2sql_cli.py
# 커맨드 직접 실행
python /app/graphs/nl2sql_agent/CLI_TOOL/nl2sql_cli.py <command> <subcommand> [options]
대화형 메뉴 화면
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Konan NL2SQL 관리 CLI
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
1. DB 환경 목록 (db list)
2. 활성 DB 설정 확인 (db active)
3. DB 환경 추가 (db add)
4. DB 환경 편집 (db edit <name>)
5. DB 환경 활성화 (db activate <name>)
6. DB 연결 테스트 (db test [name])
7. NL2SQL 직접 쿼리 (db query) 엔진 직접 호출
8. 프로파일링 초기화 (profiling init) ← 기존 파일 삭제 후 CSV 생성
9. 프로파일링 실행 (profiling run)
10. 프로파일링 로그 (profiling logs -f)
11. 프로파일링 중단 (profiling stop)
─── 테스트 ───────────────────────────────────────────
12. 모든 DB 연결 테스트 (test connections)
13. 모든 DB 프로파일링 테스트 (test profiling) ← init → run 순차 실행
14. NL2SQL 모두 쿼리 (test nl2sql) ← 공통 질문으로 전 환경 순차 쿼리
0. 종료
선택:
커맨드 직접 실행 도움말
root@0d868769e1ff:/app/graphs/nl2sql_agent/CLI_TOOL# python nl2sql_cli.py -h
usage: nl2sql_cli [-h] {db,profiling,test} ...
NL2SQL 관리 CLI — DB 환경 및 스키마 프로파일링 관리 도구.
positional arguments:
{db,profiling,test}
db DB 환경 관리
profiling 스키마 프로파일링
test 전체 환경 일괄 테스트
options:
-h, --help show this help message and exit
예시:
python CLI_TOOL/nl2sql_cli.py 대화형 메뉴
python CLI_TOOL/nl2sql_cli.py db list DB 환경 목록
python CLI_TOOL/nl2sql_cli.py db activate my_env 환경 활성화
python CLI_TOOL/nl2sql_cli.py db test 활성 환경 연결 테스트
python CLI_TOOL/nl2sql_cli.py db query "매출 상위 10개" 직접 쿼리
python CLI_TOOL/nl2sql_cli.py profiling init 초기화 (파일 삭제+CSV 생성)
python CLI_TOOL/nl2sql_cli.py profiling init --bg 초기화 백그라운드 실행
python CLI_TOOL/nl2sql_cli.py profiling run --step long long summary 생성
python CLI_TOOL/nl2sql_cli.py profiling run --step all --bg 전체 실행 백그라운드
python CLI_TOOL/nl2sql_cli.py profiling logs -f 프로파일링 로그 follow
python CLI_TOOL/nl2sql_cli.py profiling stop 프로파일링 중단
1) DB 환경 설정 (Database Configuration)
| 항목 | 내용 |
|---|---|
| DB 연결 등록 | dialect · host · port · MCP_DB_ID 정보 입력 |
| 연결 테스트 | SQLAlchemy 인증 / 호스트 검증 |
| 활성 환경 설정 | active_env 전환 및 스냅샷 원본 지정 |
2) 전처리 / 프로파일링
| 항목 | 내용 |
|---|---|
| 스키마 가져오기 | 활성화된 DB에서 Table/Column 조회 |
| CSV 편집 | CSV에 Table·Column description 작성 |
| Profiling 진행 | Foreign Key 탐색, NULL 여부 등 기본 정보 탐색 후, CSV를 참고해 summary.json 생성 |
📁 생성되는 파일 구조
{db_root}/{db_id}/
├── database_description/*.csv # 사용자 편집 가능 — 컬럼 메타
├── table_description.json # 사용자 편집 가능 — 테이블 설명
├── schema_join_info.json # 자동 생성 — FK / 조인 관계
└── {db_id}_summary.json # 최종 프로파일링 결과 (런타임 사용)
3) 배포
| 항목 | 내용 |
|---|---|
| DB env 설정 | env.json 작성 |
| 그래프 등록 | register.json을 Agent 서버에 POST하여 그래프 등록 |
curl -X POST http://{agent-server-url}/graphs \
-H 'Content-Type: application/json' \
-d @./register.json
환경 변수 설정
env.json에 정의하는 주요 환경 변수입니다.
기본 설정
| 키 | 설명 |
|---|---|
NL2SQL_BASE_URI |
LLM API 엔드포인트 (예: http://192.168.50.3:5555/v1) |
NL2SQL_LLM_MODEL |
사용할 모델명 (예: Konan-LLM-ENT-12) |
NL2SQL_DB_DIALECT |
sqlite | postgresql | mysql | oracle |
NL2SQL_ENV_MODE |
dev | aihub (DB 환경 모드) |
NL2SQL_DB_ID |
기본 조회 DB ID |
NL2SQL_DB_ROOT_PATH |
전처리 데이터 루트 경로 |
🔧 자동 계산되는 값
NL2SQL_DB_ROOT_DIRECTORY = {NL2SQL_DB_ROOT_PATH}/{NL2SQL_ENV_MODE}_databases
DB 접속 정보 (PostgreSQL / MySQL / Oracle)
| 키 | 설명 |
|---|---|
DB_HOST |
DB 호스트 (예: localhost) |
DB_PORT |
DB 포트 (예: 5432) |
DB_USER / DB_PASSWORD |
DB 인증 정보 |
DB_ADDITIONAL_ENDPOINT |
추가 접속 파라미터 (DSN 등) |
응답 제한 및 템플릿
| 키 | 설명 |
|---|---|
NL2SQL_SQL_RESULT_LIMIT |
DB 쿼리 최대 반환 행 수 (기본 200) — Execution 결과용 |
NL2SQL_SQL_REPORT_LIMIT |
응답 표시 최대 행 수 (기본 20) — 자연어 추론용 |
NL2SQL_TEMPLATES_ROOT_PATH |
프롬프트 템플릿 경로 |
프롬프트 템플릿 우선순위
템플릿은 다음 순서로 탐색합니다. (DB별 → 공통 → 내장 순)
| 순위 | 종류 | 경로 |
|---|---|---|
| 1️⃣ | 커스텀 · dialect별 | {TEMPLATES_ROOT}/{dialect}/template_{name}.txt |
| 2️⃣ | 커스텀 · 공통 | {TEMPLATES_ROOT}/template_{name}.txt |
| 3️⃣ | 내장 dict | Templates.get(name, dialect) |
성능 향상 팁
💡 핵심 원칙: LLM이 정답 SQL을 만들기 쉬운 환경을 만들어주는 것이 핵심입니다. 스키마 설계와 메타데이터 품질이 정확도를 결정합니다.
1) 자주 쓰는 JOIN은 View로 평탄화
- 복잡한 N-way 조인을 1개 테이블로 평탄화
- LLM은 단일 테이블
SELECT를 가장 잘 만듦
2) PK · FK 정보를 명시적으로 등록
- 스키마 그래프가 있어야 조인 추론이 가능
- 정확한 PK, FK 관계 정의 필수
3) 컬럼명을 의미와 일치시키기
- 이름 자체가 가장 강력한 LLM 힌트
- ✅ 권장:
user_email,order_total_krw처럼 명확하게 - ❌ 회피:
col1,val,data같은 모호한 이름 - 약어는 도메인 표준일 때만 사용 (예:
qty,amt)
4) CSV에 상세한 스키마 설명 입력
- Table·Column 설명이 곧 LLM 컨텍스트
- 용도를 명확히 명시
- 빈 description은 LLM이 추측에 의존하게 됨
부록
프로파일링
런타임이 의존하는 모든 스키마 메타데이터를 사전에 구축하는 오프라인 파이프라인입니다.
프로파일링 6단계
| 단계 | 작업 | 설명 |
|---|---|---|
| 1 | 컬럼 프로파일링 | distinct/NULL/예시값 수집. 컬럼 타입별 샘플링 (json/jsonb 별도 처리, VIEW는 통계 생략) |
| 2 | 유사도 분석 | TEXT 컬럼 간 유사도를 계산해 상위 쌍 반환 |
| 3 | Join 정보 구성 | PK · FK · referenced_by · joinable_with를 합쳐 schema_join_info.pickle로 저장 (VIEW 컬럼 제외) |
| 4 | Long Column Info (LLM) | extract_column_info_long 프롬프트로 컬럼 상세 설명 생성. JSON/JSONB은 키 구조까지 기술 |
| 5 | Short Column Info (LLM) | Long 설명을 한 줄로 압축 |
| 6 | Table Summary (LLM) | extract_table_summary 프롬프트로 테이블 전체를 자연어로 요약 (JSON 컬럼 키 구조 포함) |
프로파일링 결과물
최종적으로 다음 4가지 산출물이 생성됩니다.
| # | 산출물 | 내용 |
|---|---|---|
| 1 | Schema Join Info | PK · FK · referenced_by · joinable_with를 사전 구축한 결과 → schema_join_info.json |
| 2 | LLM · Long Column Info | 컬럼 의미 · 분포 · JSON 키 구조 · 조인 가능 대상까지 다문장으로 상세 기술 |
| 3 | LLM · Short Column Info | 한 줄 요약 (Context 절약용) |
| 4 | LLM · Table Summary | 테이블 단위로 압축된 설명 |
지원 DB
| Dialect | 값 |
|---|---|
| SQLite | sqlite |
| PostgreSQL | postgresql |
| MySQL | mysql |
| MariaDB | mariadb |
| Oracle | oracle_thin / oracle_thick |
| MS-SQL | mssql |