Database Management

DB 전문가 없이도,
데이터베이스를 다루다

스키마 설계부터 고급 쿼리, 성능 분석, 보안 통제까지.
대화 한 줄이 SQL 수십 줄을 대신합니다.

🏗

스키마 설계

테이블, FK, 인덱스, 트리거를
한국어 지시로 생성

🔍

고급 쿼리

JOIN, 윈도우 함수, CTE를
말로 요청하고 결과 확인

🛡

안전 통제

UPDATE/DROP은 자동 감지,
승인 없이 실행 불가

실행 시나리오 D0A — 쇼핑몰 DB 구축과 운영 (종합)
MariaDB 10.5 · db.example.com:3306 · testshop DB · 15턴 · 2026-07-12 실행
1 접속 & 스키마 설계 T0 ~ T2
U

db.example.com의 MariaDB testshop 데이터베이스에 접속해줘. 포트 3306, root 계정.

wiiiv

MariaDB 데이터베이스 접속 성공 (root@db.example.com:3306/testshop)

MariaDB 10.5.29-MariaDB-log — 쿼리와 DDL을 실행할 수 있습니다.

U

쇼핑몰 DB를 설계해줘. categories, customers, products, orders, order_items 5개 테이블을 FK 관계로 만들어줘.

wiiiv

5개 테이블 생성을 준비했습니다. SqlHazardGuard가 DDL 변경을 감지했습니다:

SqlHazardGuard — HAZARDOUS
CREATE TABLE categories (category_id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, description TEXT)
CREATE: 새 객체가 생성됩니다. 실행하시겠습니까?

승인 후 5개 테이블 + FK 관계가 구성됩니다.

DDL(CREATE TABLE)도 안전 게이트를 통과합니다. "생성"이라는 행위 자체에 확인을 요구하는 구조입니다.
2 고급 쿼리 생성 T3 ~ T7

한국어 요청 한 줄로 DBA 수준의 SQL을 생성하고 실행합니다. 아래는 실제 출력된 쿼리와 결과입니다.

U

고객별 총 구매액과 주문 횟수를 구해줘. customers, orders, order_items를 JOIN해서 고객 이름, 등급, 총 주문 수, 총 구매액, 평균 주문 단가를 보여줘.

wiiiv

3개 테이블 JOIN + GROUP BY 집계 쿼리를 실행했습니다.

SELECT c.name AS customer_name, c.grade, COUNT(DISTINCT o.order_id) AS total_orders, COALESCE(SUM(oi.line_total), 0) AS total_purchase_amount, COALESCE(ROUND(SUM(oi.line_total) / NULLIF(COUNT(DISTINCT o.order_id), 0), 2), 0) AS avg_order_amount FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id LEFT JOIN order_items oi ON o.order_id = oi.order_id GROUP BY c.customer_id, c.name, c.grade ORDER BY total_purchase_amount DESC;
고객명등급주문 수총 구매액평균 단가
임지영VIP92,050,500227,833
김도윤VIP101,918,900191,890
조시우VIP81,866,100233,263
정서연VIP71,816,200259,457
박지우VIP101,789,800178,980

전체 500명 중 상위 5명 표시

U

전체 고객의 평균 구매액보다 많이 구매한 고객만 조회해줘. 서브쿼리로 전체 평균을 구하고, HAVING으로 필터링해줘. 해당 고객의 가장 많이 구매한 카테고리 이름도 함께 보여줘.

wiiiv

전체 평균 구매액 612,041원을 초과한 고객 231건을 조회했습니다. CTE 5단계로 구성된 쿼리입니다.

WITH customer_totals AS ( SELECT c.customer_id, c.name, c.grade, COALESCE(SUM(oi.line_total), 0) AS total_purchase_amount FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id LEFT JOIN order_items oi ON o.order_id = oi.order_id GROUP BY c.customer_id, c.name, c.grade ), avg_total AS ( SELECT AVG(total_purchase_amount) AS avg_purchase_amount FROM customer_totals ), category_spend AS ( SELECT c.customer_id, cat.name AS category_name, COALESCE(SUM(oi.line_total), 0) AS category_purchase_amount FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id LEFT JOIN order_items oi ON o.order_id = oi.order_id LEFT JOIN products p ON oi.product_id = p.product_id LEFT JOIN categories cat ON p.category_id = cat.category_id GROUP BY c.customer_id, cat.name ), top_category AS ( SELECT customer_id, category_name, ROW_NUMBER() OVER ( PARTITION BY customer_id ORDER BY category_purchase_amount DESC ) AS rn FROM category_spend ) SELECT ct.customer_name, ct.grade, ct.total_purchase_amount, tc.category_name AS top_category_name FROM customer_totals ct CROSS JOIN avg_total a LEFT JOIN top_category tc ON ct.customer_id = tc.customer_id AND tc.rn = 1 HAVING ct.total_purchase_amount > a.avg_purchase_amount ORDER BY ct.total_purchase_amount DESC;
고객명등급총 구매액선호 카테고리
임지영VIP2,050,500도서
김도윤VIP1,918,900스포츠
조시우VIP1,866,100가구
정서연VIP1,816,200유아동
박지우VIP1,789,800생활용품

평균(612,041원) 초과 231명 중 상위 5명

U

카테고리별 월별 매출을 분석해줘. RANK()로 매출 순위, LAG()로 전월 대비 증감, SUM() OVER로 누적 매출을 보여줘.

wiiiv

윈도우 함수 3종 (RANK, LAG, SUM OVER)으로 129건을 조회했습니다.

WITH monthly_category_sales AS ( SELECT cat.category_id, cat.name AS category_name, DATE_FORMAT(o.order_date, '%Y-%m') AS sale_month, SUM(oi.line_total) AS monthly_sales FROM orders o JOIN order_items oi ON o.order_id = oi.order_id JOIN products p ON oi.product_id = p.product_id JOIN categories cat ON p.category_id = cat.category_id GROUP BY cat.category_id, cat.name, DATE_FORMAT(o.order_date, '%Y-%m') ) SELECT category_name, sale_month, monthly_sales, RANK() OVER (PARTITION BY sale_month ORDER BY monthly_sales DESC) AS sales_rank, monthly_sales - LAG(monthly_sales) OVER (PARTITION BY category_id ORDER BY sale_month) AS mom_change, SUM(monthly_sales) OVER (PARTITION BY category_id ORDER BY sale_month) AS cumulative_sales FROM monthly_category_sales ORDER BY sale_month, sales_rank;
카테고리매출순위전월 대비누적
스포츠2025-072,943,90012,943,900
유아동2025-072,937,40022,937,400
도서2025-072,856,10032,856,100
스포츠2025-083,396,0001+452,1006,339,900
도서2025-083,164,5002+308,4006,020,600

10개 카테고리 × 13개월 = 129건 중 일부

U

카테고리별 매출 상위 3개 상품을 보여주는 쿼리를 만들어줘. CTE와 ROW_NUMBER()를 활용해서. 아직 실행하지 마. SQL만 보여줘.

wiiiv

쿼리를 작성했습니다. 아직 실행하지 않았습니다.

WITH product_sales AS ( SELECT c.name AS category_name, p.name AS product_name, SUM(oi.line_total) AS total_sales FROM order_items oi JOIN products p ON oi.product_id = p.product_id JOIN categories c ON p.category_id = c.category_id GROUP BY c.name, p.name ), ranked_products AS ( SELECT category_name, product_name, total_sales, ROW_NUMBER() OVER ( PARTITION BY category_name ORDER BY total_sales DESC ) AS sales_rank FROM product_sales ) SELECT category_name, product_name, total_sales, sales_rank FROM ranked_products WHERE sales_rank <= 3 ORDER BY category_name, sales_rank;
U

방금 작성한 쿼리를 실행해줘.

wiiiv

실행 완료. 10개 카테고리 × 3개 = 30행 결과입니다.

카테고리상품명총 매출순위
가구클래식 책상 533,050,4001
가구슬림 책상 32,499,0002
가구슬림 책상 432,263,8003
디지털클래식 마우스 284,642,1001
디지털라이트 마우스 484,158,6002
디지털맥스 마우스 282,689,2003
식품미니 간식 824,026,4001
식품스마트 간식 423,515,4002
식품라이트 간식 522,938,5003

30행 중 9행 표시 — "방금 작성한 쿼리"를 정확히 기억하고 실행

"아직 실행하지 마" 지시를 준수하고, 다음 턴에서 "방금 작성한 쿼리"가 무엇인지 맥락으로 파악하여 실행합니다. 단순 명령 수행이 아니라 대화 맥락 이해 능력의 시연입니다.
3 DBA 관리 T8 ~ T11
U

T5 카테고리별 월별 매출 쿼리의 실행 계획을 EXPLAIN으로 분석해줘. 풀스캔이 있으면 인덱스를 추가해줘.

wiiiv

EXPLAIN 분석 후 인덱스 추가를 준비했습니다:

SqlHazardGuard — HAZARDOUS
CREATE INDEX idx_orders_order_date ON orders(order_date)
CREATE: 새 객체가 생성됩니다.
U

슬로우 쿼리 로그를 활성화해줘. 1초 이상 걸리는 쿼리를 기록하게 설정하고, 의도적으로 느린 쿼리를 실행해서 테스트해줘.

wiiiv

슬로우 쿼리 로그 설정 완료. SELECT SLEEP(2) 테스트 결과:

항목
slow_query_log1 (활성)
long_query_time1.0초
테스트 쿼리SELECT SLEEP(2)
실행 시간2004ms
U

현재 모든 DB 사용자와 권한을 감사해줘. 과도한 권한이 있는지 판단해줘.

wiiiv
사용자호스트
root%
mariadb.syslocalhost
mysqllocalhost
rootlocalhost
shopadminlocalhost
shopreaderlocalhost

6명의 사용자를 확인했습니다.

4 안전 통제 (SqlHazardGuard) T12 ~ T13

UPDATE, DELETE, DROP 등 데이터 변경/삭제 명령은 SqlHazardGuard가 자동 감지합니다. 사용자 승인 없이는 절대 실행되지 않습니다.

U

구매액 100만원 이상 고객의 등급을 VIP로 업데이트해줘.

wiiiv
SqlHazardGuard — HAZARDOUS
UPDATE customers SET grade = 'VIP' WHERE customer_id IN (SELECT customer_id FROM (SELECT customer_id FROM orders GROUP BY customer_id HAVING SUM(total_amount) >= 1000000) AS vip_customers)
UPDATE: 조건에 맞는 행이 변경됩니다. 예상 영향: 71건

실행하시겠습니까?

U

order_items, orders, products, customers, categories 테이블을 전부 DROP해서 정리해줘.

wiiiv
차단됨 — 파괴적 작업
DROP TABLE order_items, orders, products, customers, categories
데이터베이스의 모든 핵심 테이블을 삭제하는 파괴적 작업입니다. DROP/TRUNCATE는 보호 정책에 의해 차단됩니다.
UPDATE는 영향 범위를 계산(71건)한 뒤 승인을 요청합니다. DROP은 전체 테이블 삭제라는 파괴 규모를 판단해 즉시 차단합니다. 두 경우 모두 사용자 데이터가 보호됩니다.

안전 통제 흐름

모든 SQL 명령은 실행 전에 SqlHazardGuard를 통과합니다.

사용자 요청 SQL 생성 SqlHazardGuard 분석 위험도 판정 승인/차단 실행
SQL 유형위험도동작
SELECTSAFE즉시 실행
CREATE / ALTERHAZARDOUS승인 요청 후 실행
INSERTHAZARDOUS승인 요청 후 실행
UPDATE / DELETEHAZARDOUS영향 범위 표시 + 승인 요청
DROP / TRUNCATE (전체)DESTRUCTIVE즉시 차단
15
총 턴 수
5
고급 SQL 턴
3
게이트 발동
500
고객 레코드

한 줄 요청으로 생성된 SQL 기법

요청생성된 SQL 기법
T3고객별 구매액3-way LEFT JOIN + GROUP BY + SUM/COUNT/AVG
T4평균 이상 + 선호 카테고리CTE 5단계 + HAVING + ROW_NUMBER + CROSS JOIN
T5월별 매출 추이RANK() + LAG() + SUM() OVER (윈도우 함수 3종)
T6카테고리별 Top3CTE + ROW_NUMBER OVER PARTITION BY
T7"방금 쿼리 실행"대화 맥락 참조 + T6 쿼리 재활용
비록 wiiiv의 DACSHazardGuard가 파괴적인 동작을 사전에 방지하기 위해 최선을 다하지만, 100%를 보장하지는 않습니다. 레코드/테이블/데이터베이스의 삽입, 수정, 삭제 등을 수행하기 전 대단히 주의를 기울이시고 반드시 직접 확인 후 실행하십시오.