AI 데이터베이스 보호 (4중 안전망)
Multi-SaaS Kit 은 AI 협업 워크플로우 를 핵심 가치로 하는 플랫폼입니다. AI 에 의한 우발적인 데이터 손실을 막기 위해 4중 안전망 + 1 옵션 을 기본 탑재합니다.
왜 필요한가?
AI 코딩 도구 (Claude Code, Codex, Cursor, …) 가 보편화되면서 다음과 같은 위험이 실재화되었습니다:
| 위험 시나리오 | 결과 |
|---|---|
AI 가 php artisan migrate:fresh 자율 실행 | 전 테이블 drop → 운영 데이터 전체 손실 |
AI 가 Model::truncate() 호출 | 단일 테이블 전체 삭제 |
AI 가 psql -c "TRUNCATE …" Bash 실행 | application 우회 → 직접 SQL 파괴 |
AI 가 WHERE 빠진 DELETE FROM users | 의도와 다른 전체 삭제 |
일반 백업만으로는 부족합니다 — 손실 발생부터 인지까지 시간 차가 있고, 부분 손실 후 데이터 부정합 복구는 매우 어렵습니다.
→ 사후 복구보다 사전 차단 이 비용/리스크 모두 우월합니다.
4중 안전망 한눈에 보기
AI 의 destructive 작업 시도
│
┌─────────────────────────┼─────────────────────────┐
│ │ │
Bash 실행 PHP 코드 Artisan 명령
│ │ │
┌───────▼──────┐ ┌────────▼────────┐ ┌──────▼──────┐
│ Phase E │ │ Phase A │ │ Phase 0 │
│ AI Bash hook│ │ Query Listener │ │ Cmd Guard │
│ (Claude Code)│ │ (DB::listen) │ │ (Artisan) │
└───────┬──────┘ └────────┬────────┘ └──────┬──────┘
│ │ │
└─────────────┬─── ────────┴───────────┬─────────────┘
│ │
차단 + audit 통과
│ │
┌──────▼──────┐ ▼
│ Phase F │ 정상 실행
│ Audit log │
└──────┬──────┘
│
⚠️ AI→SQL→User 워크플로
(사용자가 admin 도구로 직접 실행)
| Phase | 레이어 | 막는 대상 | 기본 활성 |
|---|---|---|---|
| 0 | Artisan 명령 차단 | migrate:fresh|refresh|reset, db:wipe, schema:dump --prune | ✅ |
| A | 런타임 Query 차단 | Model::truncate(), raw TRUNCATE/DROP/DELETE FROM(WHERE 없음) | ✅ |
| C | DB Role 분리 (PostgreSQL) | application connection 의 권한 자체를 제한 | ⏸️ 옵션 |
| E | AI Bash hook 차단 | AI 가 Bash 로 실행하는 destructive shell SQL | ✅ |
| F | Audit log 기록 | 차단/허용 이력 영구 추적 | ✅ |
일반 개발 워크플로 (테스트, RefreshDatabase, 정상 마이그레이션) 는 자동 허용 됩니다 — false positive 가 거의 없습니다.
Phase 0 — Artisan 명령 차단
php artisan migrate:fresh 같은 명령을 Laravel 부트 시점에 가로챕니다.
차단 대상
| 명령 | 위험 |
|---|---|
migrate:fresh | 전 테이블 drop 후 재생성 |
migrate:refresh | 전체 rollback 후 재실행 |
migrate:reset | 전체 rollback |
db:wipe | 전 테이블 drop |
schema:dump --prune | 마이그레이션 파일 일괄 삭제 |
자동 허용
- PHPUnit 실행 +
APP_ENV=testing+migrate:fresh만 허용 (LaravelRefreshDatabase정상 경로)
운영자 1회성 우회 (필요한 경우)
# 명령별로 토큰 발급 — .env 에 상시 저장 금지
MSK_ALLOW_DESTRUCTIVE_ARTISAN="MSK-ALLOW-DB-DESTRUCTIVE:migrate:fresh" \
php artisan migrate:fresh
Phase A — 런타임 Query 차단
PHP 코드에서 발생하는 destructive query 를 DB::listen() 으로 가로채 차단합니다.
Phase 0 가 막지 못하는 런타임 우회 경로 를 차단합니다.
차단 패턴
TRUNCATE [TABLE] {name} -- ⛔ 차단
DROP TABLE {name} -- ⛔ 차단
DROP DATABASE {name} -- ⛔ 차단
DELETE FROM {name} -- ⛔ 차단 (WHERE 없음)
DELETE FROM {name} WHERE … -- ✅ 통과
UPDATE {name} SET … WHERE … -- ✅ 통과
SELECT … / INSERT … -- ✅ 통과
차단 시 동작
RuntimeException: ⛔ DB destructive query blocked: TRUNCATE TABLE users
사용자 명시 필요 (MSK_ALLOW_DESTRUCTIVE_QUERY=1) 또는 admin role 에서 실행하세요.
→ 호출 stack 까지 예외 전파, 트랜잭션이 있다면 자동 롤백.
자동 허용
APP_ENV=testing+runningUnitTests()(RefreshDatabase 호환)MSK_ALLOW_DESTRUCTIVE_QUERY=1환경변수 (운영자 1회성 우회)
Phase E — AI Bash hook 차단
AI 코딩 도구 (Claude Code) 가 Bash 로 실행하는 destructive 명령을 실행 직전 에 가로챕니다.
검사 대상 (Bash 만 — Edit/Write 제외)
| 패턴 예시 | 차단 |
|---|---|
psql -c "TRUNCATE TABLE users" | ⛔ |
mysql -e "DROP TABLE foo" | ⛔ |
php artisan migrate:fresh | ⛔ |
docker exec mydb psql -c "DROP DATABASE x" | ⛔ |
php artisan tinker --execute "User::truncate()" | ⛔ |
grep -r 'truncate' src/ | ✅ (정상 검색) |
git log --oneline | grep truncate | ✅ (정상 검색) |
왜 Bash 만? Edit/Write 의 텍스트에
truncate,delete from단어가 등장하는 정상 케이스(주석, 문서, 검색 결과)가 너무 많습니다. SQL 실행 컨텍스트(Bash) 만 검사하여 false positive 를 거의 0 으로 만들었습니다.
차단 시 AI 의 동작 (AI→SQL→User 워크플로)
AI 응답:
⛔ 이 작업은 admin 권한이 필요합니다.
다음 SQL 을 사용자가 직접 실행해주세요:
TRUNCATE TABLE foo CASCADE;
실행 위치 (택 1):
- pgadmin (admin role 연결)
- 운영 DBA 에게 요청
실행 후 결과를 알려주시면 후속 작업을 진행하겠습니다.
→ AI 는 SQL 을 작성만 하고, 실제 실행은 사용자가 admin 권한 도구로 직접 수행.
Phase F — Audit Log 기록
차단/허용 이력은 모두 audit_logs 테이블에 영구 기록됩니다.
SELECT action, message, meta->>'sql', created_at
FROM audit_logs
WHERE action LIKE 'db_destructive_%'
ORDER BY created_at DESC
LIMIT 20;
action | 의미 |
|---|---|
db_destructive_blocked | 차단됨 (RuntimeException 발생) |
db_destructive_allowed | unlock 토큰 / RefreshDatabase 로 통과됨 |
→ 운영자가 주기적으로 검토하여 의심 패턴을 탐지할 수 있습니다.
Phase C — PostgreSQL Role 분리 (옵션)
가장 강력한 안전망. application connection 자체에 destructive 권한이 없도록 PostgreSQL Role 을 2단으로 분리합니다.
┌────────────────────────┐ ┌────────────────────────┐
│ app_user (서비스용) │ │ admin_user (관리용) │
│ │ │ │
│ ✅ SELECT │ │ ✅ SELECT │
│ ✅ INSERT │ │ ✅ INSERT │
│ ✅ UPDATE WHERE │ │ ✅ UPDATE │
│ ✅ DELETE WHERE │ │ ✅ DELETE │
│ ⛔ TRUNCATE │ │ ✅ TRUNCATE │
│ ⛔ DROP │ │ ✅ DROP │
│ ⛔ migrate / DDL │ │ ✅ migrate / DDL │
│ │ │ │
│ Laravel 앱이 사용 │ │ pgadmin / DBA 가 사용 │
└────────────────────────┘ └────────────────────────┘
장점: AI 가 Phase 0/A/E 를 모두 우회해도 PostgreSQL 레벨에서 거부됩니다.
단점: 인프라 변경이 큼 — 22+ 프로젝트 마이그레이션 필요. 따라서 옵션 으로 제공.
보안 강도 요구가 높은 운영 환경 (금융, 의료, 정부) 에서 권장. 일반 SaaS 는 Phase 0+A+E+F 만으로 충분.
활성화 가이드는 별도 문서 (예정) 에서 다룹니다.