728x90
반응형

자연어로 “지난달 매출 상위 10개 상품 보여줘”라고 물어 SQL을 받게 할 때, 가장 위험한 것은 틀린 조인보다 파괴적 쿼리와 스키마 환각입니다. 이 글의 프롬프트는 스키마를 변수로 고정하고, 모호하면 검증 질문을 하며, DROP/DELETE/UPDATE/TRUNCATE/ALTER 등을 확인 없이 차단합니다.
언제 쓰면 좋은가
- 분석가가 읽기 전용 SQL 초안을 빠르게 만들 때
- 사내 챗봇에 NL→SQL을 붙이되 가드레일이 필요할 때
- 주니어가 작성한 쿼리를 시니어 리뷰 전에 위험도 분류할 때
변수 설명
{{DIALECT}}— postgresql | mysql | bigquery | snowflake 등{{SCHEMA}}— 테이블·컬럼·PK/FK·파티션 설명(DDL 또는 문서){{QUESTION}}— 사용자 자연어 질문{{ROW_LIMIT_DEFAULT}}— 기본 LIMIT (예: 100){{PII_COLUMNS}}— 마스킹/금지 컬럼 목록{{ALLOW_WRITE}}— false 권장. true여도 반드시 확인 질문 후
복붙용 프롬프트
당신은 시니어 데이터 엔지니어입니다. 사용자 질문을 {{DIALECT}} SQL로 변환하세요.
# 스키마(이 밖의 테이블/컬럼 사용 금지)
{{SCHEMA}}
# 규칙
1. SELECT/CTE/EXPLAIN만 기본 허용. ALLOW_WRITE={{ALLOW_WRITE}}
2. DROP, DELETE, UPDATE, TRUNCATE, ALTER, GRANT, CREATE 등 쓰기·DDL은
- ALLOW_WRITE가 false이면 거부하고 안전한 SELECT 대안 제시
- true여도 실행 전 Yes/No 확인 질문을 먼저 하고 SQL은 제안만
3. 질문이 모호하면 SQL 대신 ClarifyingQuestions(최대 5)를 먼저
4. PII 컬럼({{PII_COLUMNS}})은 SELECT하지 않거나 마스킹 표현 사용
5. 결과 폭주 방지: ORDER BY 있는 분석 쿼리에 LIMIT {{ROW_LIMIT_DEFAULT}} 기본 부여(사용자가 명시하면 그 값)
6. 존재하지 않는 컬럼을 추측하지 말 것. 필요 시 스키마에 없다고 명시
7. 출력은 아래 형식, SQL은 실행 가능한 한 블록
# 출력
## Status: READY | NEED_CLARIFICATION | BLOCKED
## ClarifyingQuestions (필요 시)
## SQL
## Explanation (한국어, 조인·필터 근거)
## Risk (Low/Med/High + 이유)
## ValidationTips (EXPLAIN, 샘플 체크리스트)
# 질문
{{QUESTION}}
빠른 원라인 버전
{{DIALECT}} / 스키마 밖 객체 금지 / 쓰기·DDL 차단 / 모호하면 질문 먼저.
스키마:
{{SCHEMA}}
질문: {{QUESTION}}
예시 입력
DIALECT: postgresql
ROW_LIMIT_DEFAULT: 50
ALLOW_WRITE: false
PII_COLUMNS: users.email, users.phone
SCHEMA:
tables:
- orders(id pk, user_id fk->users.id, amount numeric, status text, created_at timestamptz)
- users(id pk, email text, phone text, country text)
- products(id pk, name text, category text)
- order_items(order_id fk, product_id fk, qty int, unit_price numeric)
QUESTION: 지난 30일 한국 고객 매출 상위 10개 카테고리 지워주고 새로 집계 테이블 만들어줘
예시 출력(요약)
## Status: BLOCKED
쓰기/DDL 요청(“지워주고”, “집계 테이블 만들어줘”)은 ALLOW_WRITE=false로 거부.
## SQL (안전한 대안)
SELECT p.category, SUM(oi.qty * oi.unit_price) AS revenue
FROM orders o
JOIN users u ON u.id = o.user_id
JOIN order_items oi ON oi.order_id = o.id
JOIN products p ON p.id = oi.product_id
WHERE u.country = 'KR'
AND o.created_at >= NOW() - INTERVAL '30 days'
AND o.status = 'paid'
GROUP BY p.category
ORDER BY revenue DESC
LIMIT 10;
## Risk: Low (읽기 전용)
팁과 주의사항
- 스키마를 짧게라도 넣기: 없으면 모델이 컬럼을 발명합니다.
- 프로덕션 실행 분리: 챗봇은 SQL 생성만, 실행은 읽기 전용 롤·타임아웃 샌드박스에서.
- 날짜 경계: “지난달”은 타임존·캘린더 정의를 ClarifyingQuestions로 확인하세요.
FAQ
Q. UPDATE가 꼭 필요하면?
A. ALLOW_WRITE=true로 바꾸되, 영향 행수 추정 SELECT → 확인 → UPDATE 제안 순서를 강제하세요.
Q. BigQuery와 Postgres 문법이 섞여요.
A. DIALECT를 매 요청에 넣고 “다른 방언 문법 금지”를 규칙에 추가하세요.
Q. ORM 대신 써도 되나요?
A. 가능하지만 생성 SQL은 항상 EXPLAIN/드라이런으로 검증하세요.
핵심 정리
- NL→SQL의 안전장치는 스키마 고정·검증질문·위험쿼리 차단
- 기본은 읽기 전용, 쓰기는 이중 확인
- PII 컬럼 정책을 프롬프트에 명시
- READY/NEED_CLARIFICATION/BLOCKED 상태가 운영에 유리합니다
728x90
반응형
'프롬프트' 카테고리의 다른 글
| 시네마틱 에디토리얼 포트레이트 이미지 프롬프트 2026 (Midjourney V8·Flux 복붙용) (0) | 2026.09.24 |
|---|---|
| 이력서·자기소개서를 STAR 불릿으로 리라이트하는 프롬프트 (성과 수치화) (0) | 2026.09.24 |
| 고객 문의·클레임을 정책 준수 답변으로 바꾸는 프롬프트 (톤·보상범위·에스컬레이션) (0) | 2026.09.24 |
| 긴 리포트를 경영진 1페이지 브리핑으로 만드는 프롬프트 (결정 요청형) (0) | 2026.09.23 |
| PR·코드 리뷰 체크리스트 프롬프트 (보안·성능·가독성) 복붙 템플릿 (0) | 2026.09.23 |