Files
sam-docs/dev/dev_plans/db-backup-system-plan.md
권혁성 db63fcff85 refactor: [docs] 팀별 폴더 구조 재편 (공유/개발/프론트/기획)
- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동)
- 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/)
- 기획팀 폴더 requests/ 생성
- plans/ → dev/dev_plans/ 이름 변경
- README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용)
- resources.md 신규 (노션 링크용, assets/brochure 이관 예정)
- CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동
- 전체 참조 경로 업데이트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:46:03 +09:00

29 KiB

DB 백업 시스템 계획

작성일: 2026-01-30 목적: OS 레벨 백업(쉘 스크립트) + Laravel 모니터링 절충안으로 DB 백업 시스템 구축 기준 문서: docs/architecture/system-overview.md, docs/specs/database-schema.md 상태: 🔄 진행중


📍 현재 진행 상태

항목 내용
마지막 완료 작업 Phase 5.4: 시스템 알림 Blade 페이지 + 라우트 등록
다음 작업 Phase 1.3: 개발서버 스크립트 테스트 / Phase 3: 서버 배포
진행률 11/14 (79%) — 서버 작업 3건 잔여
마지막 업데이트 2026-01-31

1. 개요

1.1 배경

SAM 프로젝트의 개발서버(114.203.209.83)를 당분간 운영 환경처럼 사용할 예정이므로, 데이터 손실 방지를 위한 DB 백업 시스템이 필요하다. 운영서버에도 동일 구조로 적용할 수 있도록 설계한다.

대상 데이터베이스:

  • sam — 메인 비즈니스 데이터 (개발서버), samdb (로컬 Docker)
  • sam_stat — 통계 데이터 (재집계 가능하나 함께 백업)

1.2 기준 원칙

┌─────────────────────────────────────────────────────────────────┐
│  🎯 핵심 원칙                                                    │
├─────────────────────────────────────────────────────────────────┤
│  1. 백업은 OS 레벨(crontab)에서 실행 — 앱 장애와 무관하게 동작   │
│  2. 모니터링은 Laravel에서 — 기존 stat_alerts 인프라 활용        │
│  3. 환경 이식성 — backup.conf만 수정하면 운영서버에서도 동작     │
└─────────────────────────────────────────────────────────────────┘

1.3 변경 승인 정책

분류 예시 승인
즉시 가능 스크립트 파일 생성, .conf 파일 생성, 문서 수정 불필요
⚠️ 컨펌 필요 StatMonitorService 수정, 스케줄러 등록, crontab 등록 필수
🔴 금지 기존 테이블 구조 변경, 기존 스케줄 시간 변경 별도 협의

1.4 준수 규칙

  • docs/quickstart/quick-start.md - 빠른 시작 가이드
  • docs/standards/quality-checklist.md - 품질 체크리스트
  • docs/standards/api-rules.md - API 개발 규칙 (Service-First)

1.5 환경 정보

개발서버 (배포 대상)

SSH: hskwon@114.203.209.83
API 경로: /home/webservice/api
MNG 경로: /home/webservice/mng
MySQL: 8.0.44
DB 사용자: codebridge / code**bridge
DB명: sam (메인), sam_stat (통계)
  ※ 로컬 Docker에서는 samdb (메인)
Git remote: /data/GIT/samproject/sam-api (bare repo, post-receive hook으로 auto-deploy)
MNG remote: /data/GIT/samproject/sam-mng

로컬 (코드 작업)

프로젝트 루트: /Users/kent/Works/@KD_SAM/SAM/
API: api/ (Laravel 12, PHP 8.4)
MNG: mng/ (Laravel 12, Plain Blade + HTMX + Tailwind)
Docker: docker/ (docker-compose.yml)
로컬 DB: samdb (메인), sam_stat (통계), samuser/sampass

배포 프로세스

로컬에서 코드 작성
  → git add + git commit
  → git push origin develop (api)
  → 개발서버 post-receive hook이 자동 pull + migrate
  → MNG도 동일 (git push → auto-deploy)

1.6 기존 코드 참조 (필수 읽기)

새 세션에서 작업 시작 전 반드시 읽어야 할 기존 코드:

파일 이유 Phase
api/app/Services/Stats/StatMonitorService.php recordBackupFailure() 추가 대상 2, 4
api/app/Models/Stats/BaseStatModel.php sam_stat 연결 패턴 ($connection = 'sam_stat') 5
api/app/Models/Stats/StatAlert.php 알림 모델 구조 (MNG용 모델 생성 참조) 5
api/routes/console.php 기존 스케줄러 패턴 (Schedule::command 형식) 2
mng/app/Http/Controllers/AuditLogController.php MNG 컨트롤러 패턴 (필터+페이지네이션) 5
mng/routes/web.php MNG 라우트 등록 패턴 5

stat_alerts 테이블 스키마

-- sam_stat 데이터베이스
CREATE TABLE stat_alerts (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tenant_id       INT UNSIGNED NOT NULL,
    alert_type      VARCHAR(50) NOT NULL,         -- aggregation_failure, missing_data, data_mismatch, backup_failure
    domain          VARCHAR(50) NOT NULL,         -- sales, finance, production, backup, system 등
    severity        ENUM('info','warning','critical') NOT NULL,
    title           VARCHAR(200) NOT NULL,
    message         TEXT,
    current_value   DECIMAL(15,2) NULL,
    threshold_value DECIMAL(15,2) NULL,
    is_read         TINYINT(1) DEFAULT 0,
    is_resolved     TINYINT(1) DEFAULT 0,
    resolved_at     TIMESTAMP NULL,
    created_at      TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

BaseStatModel 패턴 (API)

// api/app/Models/Stats/BaseStatModel.php
abstract class BaseStatModel extends Model {
    protected $connection = 'sam_stat';
    protected $guarded = ['id'];
}

// api/app/Models/Stats/StatAlert.php
class StatAlert extends BaseStatModel {
    protected $table = 'stat_alerts';
    public $timestamps = false;
    protected $casts = [
        'current_value' => 'decimal:2',
        'threshold_value' => 'decimal:2',
        'is_read' => 'boolean',
        'is_resolved' => 'boolean',
        'resolved_at' => 'datetime',
        'created_at' => 'datetime',
    ];
}

StatMonitorService 현재 메서드

// api/app/Services/Stats/StatMonitorService.php
class StatMonitorService {
    public function recordAggregationFailure(int $tenantId, string $domain, string $jobType, string $errorMessage): void
    public function recordMissingData(int $tenantId, string $domain, string $date): void
    public function recordMismatch(int $tenantId, string $domain, string $label, float|int $expected, float|int $actual): void
    public function resolveAlerts(int $tenantId, string $domain, string $alertType): int
}
// 모든 메서드는 try/catch로 감싸져 있음 (실패해도 비즈니스 로직 차단 안 함)

routes/console.php 스케줄 등록 패턴

// 기존 패턴 — 이 형식을 따라야 함
Schedule::command('db:backup-check')
    ->dailyAt('05:00')
    ->appendOutputTo(storage_path('logs/scheduler.log'))
    ->onSuccess(function () {
        \Illuminate\Support\Facades\Log::info('✅ db:backup-check 스케줄러 실행 성공', ['time' => now()]);
    })
    ->onFailure(function () {
        \Illuminate\Support\Facades\Log::error('❌ db:backup-check 스케줄러 실행 실패', ['time' => now()]);
    });

MNG 컨트롤러 패턴

// mng/app/Http/Controllers/AuditLogController.php (참조 패턴)
class AuditLogController extends Controller {
    public function index(Request $request): View {
        $query = Model::query()->orderByDesc('created_at');
        // 필터 적용 (if $request->filled('xxx'))
        // 페이지네이션: $query->paginate(50)->withQueryString()
        return view('...', compact(...));
    }
}

MNG 라우트 등록 패턴

// mng/routes/web.php (기존 패턴)
Route::prefix('audit-logs')->name('audit-logs.')->group(function () {
    Route::get('/', [AuditLogController::class, 'index'])->name('index');
    Route::get('/{id}', [AuditLogController::class, 'show'])->name('show');
});

// 새로 추가할 패턴
Route::prefix('system/alerts')->name('system.alerts.')->group(function () {
    Route::get('/', [SystemAlertController::class, 'index'])->name('index');
    Route::post('/{id}/read', [SystemAlertController::class, 'markAsRead'])->name('read');
    Route::post('/{id}/resolve', [SystemAlertController::class, 'resolve'])->name('resolve');
    Route::post('/read-all', [SystemAlertController::class, 'markAllAsRead'])->name('read-all');
});

MNG 주의사항 (CLAUDE.md 기반)

- MNG에서 마이그레이션 파일 생성 금지 (API에서만 관리)
- MNG에서 모델 작성은 허용 (API의 테이블 사용)
- HTMX 사용: 읽음/해결 버튼은 hx-post로 처리
- 사이드바 메뉴 추가 시: MngMenuSeeder 수정 + db:seed 실행 필요

2. 대상 범위

2.1 Phase 1: 백업 스크립트 (A안 — OS 레벨)

# 작업 항목 상태 비고
1.1 backup.conf 설정 파일 생성 DB 접속정보, 경로, 보관기간
1.2 sam-db-backup.sh 스크립트 생성 mysqldump + gzip + 보관관리
1.3 개발서버에서 스크립트 테스트 수동 실행 후 백업 파일 확인 (서버 접속 필요)

2.2 Phase 2: Laravel 모니터링 (B안 — 앱 레벨)

# 작업 항목 상태 비고
2.1 StatMonitorService에 recordBackupFailure() 추가 기존 서비스 확장
2.2 BackupCheckCommand 생성 db:backup-check 커맨드
2.3 routes/console.php에 스케줄 등록 매일 05:00 실행

2.3 Phase 3: 서버 배포 & 테스트

# 작업 항목 상태 비고
3.1 개발서버 crontab 등록 백업 스크립트 + schedule:run 확인 (서버 접속 필요)
3.2 통합 테스트 (백업→모니터링) 전체 플로우 검증 (서버 접속 필요)

2.4 Phase 4: Slack 알림

# 작업 항목 상태 비고
4.1 SlackNotificationService 생성 웹훅 기반 알림 발송 서비스
4.2 BackupCheckCommand에 Slack 알림 연동 백업 실패 시 Slack 즉시 통보
4.3 StatMonitorService에 Slack 알림 연동 집계 실패/정합성 불일치 시 통보 (critical만)
4.4 개발서버 테스트 실제 Slack 채널에 테스트 메시지 전송 (Phase 3과 함께)

2.5 Phase 5: MNG 관리자 패널 — 시스템 알림 페이지

# 작업 항목 상태 비고
5.1 MNG에 sam_stat DB 연결 추가 config/database.php + .env
5.2 StatAlert 모델 생성 (MNG용) sam_stat 연결, 읽기 전용
5.3 SystemAlertController 생성 목록 조회, 읽음 처리, 해결 처리
5.4 시스템 알림 Blade 페이지 생성 필터링, 페이지네이션, 상태관리 + 라우트 등록

3. 작업 절차

3.1 아키텍처 개요

[OS 레벨 — crontab]                    [앱 레벨 — Laravel API]

04:30  sam-db-backup.sh                 05:00  db:backup-check
  ├── mysqldump sam → gzip               ├── 오늘 백업 파일 존재?
  ├── mysqldump sam_stat → gzip           ├── 파일 크기 최소값 충족?
  ├── 오래된 백업 삭제 (보관정책)           ├── 마지막 백업 25시간 이내?
  └── 상태 파일 기록                       ├── 실패 시 stat_alerts 기록
       (.backup_status)                   │    (domain=backup, severity=critical)
                                          └── 실패 시 Slack 웹훅 전송
                                               ↓
                                          SlackNotificationService
                                            ├── 백업 실패 알림
                                            ├── 집계 실패 알림
                                            └── 정합성 불일치 알림

[MNG 관리자 패널]
  mng.sam.kr/system/alerts
  ├── stat_alerts 목록 조회 (sam_stat DB)
  ├── 필터: 도메인, 심각도, 읽음/미읽음
  ├── 읽음 처리
  └── 해결 처리

3.2 스케줄 시간표 (최종)

02:00  stat:aggregate-daily          (Laravel)
03:00  stat:aggregate-monthly        (Laravel, 월 1일만)
03:00  api-log:prune                 (Laravel)
03:10  audit:prune                   (Laravel)
03:20  sanctum:prune-expired         (Laravel)
03:30  storage:cleanup-temp          (Laravel)
03:40  storage:cleanup-trash         (Laravel)
03:50  storage:cleanup-links         (Laravel)
04:00  storage:record-usage          (Laravel)
04:30  sam-db-backup.sh              (crontab — OS 레벨)
05:00  db:backup-check               (Laravel)
09:00  stat:check-kpi-alerts         (Laravel)

3.3 디렉토리 구조

/data/backup/mysql/
├── daily/
│   ├── 2026-01-30/
│   │   ├── sam_20260130_0430.sql.gz
│   │   └── sam_stat_20260130_0430.sql.gz
│   ├── 2026-01-29/
│   └── ... (7일 보관)
├── weekly/
│   ├── sam_20260126_week.sql.gz
│   └── ... (4주 보관)
└── logs/
    └── backup.log

3.4 프로젝트 내 파일 구조

api/
├── scripts/
│   └── backup/
│       ├── sam-db-backup.sh              # 백업 스크립트
│       └── backup.conf.example           # 설정 파일 예시 (Git 추적)
├── app/
│   ├── Console/Commands/
│   │   └── BackupCheckCommand.php        # 모니터링 커맨드
│   └── Services/
│       ├── Stats/
│       │   └── StatMonitorService.php    # recordBackupFailure() 추가
│       └── SlackNotificationService.php  # Slack 웹훅 알림 서비스
└── routes/
    └── console.php                       # 스케줄 등록 추가

mng/
├── app/
│   ├── Http/Controllers/
│   │   └── System/
│   │       └── SystemAlertController.php # 시스템 알림 컨트롤러
│   └── Models/
│       └── Stats/
│           └── StatAlert.php             # 알림 모델 (sam_stat 연결)
├── config/
│   └── database.php                      # sam_stat 연결 추가
├── resources/views/
│   └── system/
│       └── alerts/
│           └── index.blade.php           # 시스템 알림 목록 페이지
└── routes/
    └── web.php                           # /system/alerts 라우트 추가

4. 상세 작업 내용

4.1 Phase 1: 백업 스크립트

1.1 backup.conf.example

설정 파일 (서버에 backup.conf로 복사 후 수정):

# DB 접속 정보
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=codebridge
DB_PASS="code**bridge"

# 백업 대상 DB (공백 구분)
DATABASES="sam sam_stat"

# 백업 저장 경로
BACKUP_BASE_DIR=/data/backup/mysql

# 보관 정책
DAILY_RETENTION_DAYS=7
WEEKLY_RETENTION_DAYS=28

# 로그
LOG_FILE=/data/backup/mysql/logs/backup.log

# 상태 파일 (Laravel 모니터링용)
STATUS_FILE=/data/backup/mysql/.backup_status

1.2 sam-db-backup.sh 주요 로직

1. backup.conf 로드
2. 날짜 디렉토리 생성 (daily/YYYY-MM-DD/)
3. 각 DB별 mysqldump 실행
   - --single-transaction (InnoDB 무중단)
   - --routines --triggers (프로시저/트리거 포함)
   - | gzip 압축
4. 일요일이면 weekly/ 디렉토리에도 복사
5. 오래된 백업 삭제
   - daily: DAILY_RETENTION_DAYS일 초과 삭제
   - weekly: WEEKLY_RETENTION_DAYS일 초과 삭제
6. 상태 파일 기록 (성공/실패, 파일 크기, 시간)
7. 로그 기록

1.3 상태 파일 형식 (.backup_status)

{
  "last_run": "2026-01-30T04:30:00+09:00",
  "status": "success",
  "databases": {
    "sam": {"file": "sam_20260130_0430.sql.gz", "size_bytes": 52428800},
    "sam_stat": {"file": "sam_stat_20260130_0430.sql.gz", "size_bytes": 1048576}
  },
  "errors": []
}

4.2 Phase 2: Laravel 모니터링

2.1 StatMonitorService 확장

// 추가 메서드
public function recordBackupFailure(int $tenantId, string $title, string $message): void
// domain: 'backup', alert_type: 'backup_failure', severity: 'critical'

참고: 백업은 테넌트 무관(시스템 레벨)이므로 tenantId=0 사용

2.2 BackupCheckCommand

시그니처: db:backup-check
옵션: --path= (백업 경로 오버라이드)

체크 항목:
1. .backup_status 파일 존재 여부
2. last_run이 25시간 이내인지
3. status가 "success"인지
4. 각 DB 백업 파일 크기가 최소값 이상인지
   - sam: 1MB 이상
   - sam_stat: 100KB 이상

결과:
- 모든 체크 통과: "✅ 백업 상태 정상" 출력
- 하나라도 실패: stat_alerts에 기록 + "❌ 백업 이상 감지" 출력

2.3 환경 설정

# .env 추가
BACKUP_PATH=/data/backup/mysql
BACKUP_STATUS_FILE=/data/backup/mysql/.backup_status
BACKUP_MIN_SIZE_SAM=1048576
BACKUP_MIN_SIZE_STAT=102400

4.3 Phase 4: Slack 알림

4.1 SlackNotificationService

위치: api/app/Services/SlackNotificationService.php

기능:
- Slack Incoming Webhook을 통한 메시지 전송
- 기존 LOG_SLACK_WEBHOOK_URL 환경변수 활용
- 별도 SLACK_ALERT_WEBHOOK_URL 추가 (알림 전용 채널 분리 가능)

메서드:
- sendAlert(string $title, string $message, string $severity): void
  └── severity에 따른 색상: critical=red, warning=orange, info=blue
- sendBackupAlert(string $title, string $message): void
- sendStatAlert(string $title, string $message, string $domain): void

메시지 포맷 (Slack Block Kit):
┌──────────────────────────────────────┐
│ 🚨 [SAM 백업 실패]                    │
│                                       │
│ 서버: 개발서버 (114.203.209.83)       │
│ 시간: 2026-01-30 05:00:00            │
│ 상세: sam DB 백업 파일 미발견          │
│                                       │
│ 환경: development                     │
└──────────────────────────────────────┘

4.2 BackupCheckCommand Slack 연동

기존 흐름:
  체크 실패 → stat_alerts 기록 → 로그 출력

변경 후:
  체크 실패 → stat_alerts 기록 → Slack 알림 전송 → 로그 출력

4.3 StatMonitorService Slack 연동

기존 흐름:
  집계 실패/정합성 불일치 → stat_alerts 기록

변경 후:
  집계 실패/정합성 불일치 → stat_alerts 기록 → Slack 알림 전송
  (severity가 critical인 경우에만 Slack 전송)

4.4 환경 설정

# .env 추가
SLACK_ALERT_WEBHOOK_URL=             # 알림 전용 채널 (미설정 시 LOG_SLACK_WEBHOOK_URL 사용)
SLACK_ALERT_ENABLED=true             # Slack 알림 활성화 여부
SLACK_ALERT_SERVER_NAME=개발서버      # 메시지에 표시할 서버명

4.4 Phase 5: MNG 관리자 패널

5.1 MNG에 sam_stat DB 연결 추가

// mng/config/database.php - connections 배열에 추가
'sam_stat' => [
    'driver' => 'mysql',
    'host' => env('STAT_DB_HOST', env('DB_HOST', '127.0.0.1')),
    'port' => env('STAT_DB_PORT', env('DB_PORT', '3306')),
    'database' => env('STAT_DB_DATABASE', 'sam_stat'),
    'username' => env('STAT_DB_USERNAME', env('DB_USERNAME')),
    'password' => env('STAT_DB_PASSWORD', env('DB_PASSWORD')),
    // ... 기본 설정
],
# mng/.env 추가
STAT_DB_HOST=127.0.0.1
STAT_DB_PORT=3306
STAT_DB_DATABASE=sam_stat
STAT_DB_USERNAME=samuser
STAT_DB_PASSWORD=sampass

5.2 StatAlert 모델 (MNG용)

// mng/app/Models/Stats/StatAlert.php
// - connection: sam_stat
// - 읽기 전용 (조회 + 상태 변경만)
// - fillable: is_read, is_resolved, resolved_at

5.3 SystemAlertController

라우트: /system/alerts
미들웨어: auth, hq.member, password.changed

기능:
GET  /system/alerts           — 알림 목록 (필터/페이지네이션)
POST /system/alerts/{id}/read — 읽음 처리
POST /system/alerts/{id}/resolve — 해결 처리
POST /system/alerts/read-all  — 전체 읽음 처리

필터 파라미터:
- domain: backup, sales, finance, production, system 등
- severity: info, warning, critical
- status: all, unread, unresolved
- date_from, date_to

5.4 알림 목록 Blade 페이지

페이지: mng/resources/views/system/alerts/index.blade.php
레이아웃: 기존 MNG 레이아웃 (사이드바 + 헤더)

UI 구성:
┌─────────────────────────────────────────────────────────┐
│ 시스템 알림                                    [전체 읽음]│
├─────────────────────────────────────────────────────────┤
│ 필터: [도메인 ▼] [심각도 ▼] [상태 ▼] [날짜 범위]       │
├─────────────────────────────────────────────────────────┤
│ 🔴 [backup] 백업 실패 — sam DB 백업 파일 미발견          │
│    2026-01-30 05:00  │ 미읽음 │ 미해결 │ [읽음] [해결]  │
├─────────────────────────────────────────────────────────┤
│ 🟡 [sales] 2026-01-29 데이터 누락                       │
│    2026-01-30 02:05  │ 읽음   │ 미해결 │        [해결]  │
├─────────────────────────────────────────────────────────┤
│ 🔴 [finance] deposit_amount 정합성 불일치                │
│    2026-01-29 02:10  │ 읽음   │ 해결됨 │                │
├─────────────────────────────────────────────────────────┤
│                   < 1 2 3 ... >                          │
└─────────────────────────────────────────────────────────┘

심각도 색상: critical=빨강, warning=노랑, info=파랑
HTMX 활용: 읽음/해결 버튼 클릭 시 페이지 리로드 없이 상태 변경

5. 컨펌 대기 목록

# 항목 변경 내용 영향 범위 상태
1 StatMonitorService 수정 recordBackupFailure() 메서드 추가 + Slack 연동 api/Services 완료
2 routes/console.php 수정 db:backup-check 스케줄 등록 (05:00) api/스케줄러 완료
3 crontab 등록 개발서버에 sam-db-backup.sh 등록 (04:30) 서버 서버 배포 시
4 SlackNotificationService 생성 Slack 웹훅 알림 서비스 신규 api/Services 완료
5 StatMonitorService Slack 연동 critical 알림 시 Slack 전송 api/Services 완료
6 MNG database.php 수정 sam_stat 연결 추가 mng/config 완료
7 MNG web.php 수정 /system/alerts 라우트 추가 mng/routes 완료

6. 변경 이력

날짜 항목 변경 내용 파일 승인
2026-01-30 - 문서 초안 작성 - -
2026-01-31 Phase 1.1 backup.conf.example 생성 api/scripts/backup/backup.conf.example
2026-01-31 Phase 1.2 sam-db-backup.sh 스크립트 생성 api/scripts/backup/sam-db-backup.sh
2026-01-31 Phase 2.1 recordBackupFailure() 추가 api/app/Services/Stats/StatMonitorService.php
2026-01-31 Phase 2.2 BackupCheckCommand 생성 api/app/Console/Commands/BackupCheckCommand.php
2026-01-31 Phase 2.3 db:backup-check 스케줄 등록 api/routes/console.php
2026-01-31 Phase 4.1 SlackNotificationService 생성 api/app/Services/SlackNotificationService.php
2026-01-31 Phase 4.2 BackupCheckCommand Slack 연동 api/app/Console/Commands/BackupCheckCommand.php
2026-01-31 Phase 4.3 StatMonitorService Slack 연동 api/app/Services/Stats/StatMonitorService.php
2026-01-31 Phase 4.3 .env.example 환경변수 추가 api/.env.example
2026-01-31 Phase 5.1 sam_stat DB 연결 추가 mng/config/database.php
2026-01-31 Phase 5.2 StatAlert 모델 생성 (MNG) mng/app/Models/Stats/StatAlert.php
2026-01-31 Phase 5.3 SystemAlertController 생성 mng/app/Http/Controllers/System/SystemAlertController.php
2026-01-31 Phase 5.4 시스템 알림 Blade + 라우트 mng/resources/views/system/alerts/index.blade.php, mng/routes/web.php

7. 참고 문서

  • 빠른 시작: docs/quickstart/quick-start.md
  • 품질 체크리스트: docs/standards/quality-checklist.md
  • 시스템 아키텍처: docs/architecture/system-overview.md
  • DB 스키마: docs/specs/database-schema.md
  • 기존 스케줄러: api/routes/console.php
  • StatMonitorService: api/app/Services/Stats/StatMonitorService.php
  • StatAlert 모델: api/app/Models/Stats/StatAlert.php
  • sam_stat 설계: docs/dev_plans/sam-stat-database-design-plan.md
  • MNG 라우트: mng/routes/web.php
  • MNG 레이아웃: mng/resources/views/layouts/
  • Slack 웹훅: api/.envLOG_SLACK_WEBHOOK_URL

8. 세션 및 메모리 관리 정책 (Serena Optimized)

8.1 세션 시작 시 (Load Strategy)

read_memory("db-backup-state")
read_memory("db-backup-snapshot")
read_memory("db-backup-active-symbols")

8.2 작업 중 관리 (Context Defense)

컨텍스트 잔량 Action 내용
30% 이하 Snapshot write_memory("db-backup-snapshot", "코드변경+논의요약")
20% 이하 Context Purge write_memory("db-backup-active-symbols", "주요 수정 파일/함수")
10% 이하 Stop & Save 최종 상태 저장 후 세션 교체 권고

8.3 Serena 메모리 구조

  • db-backup-state: { phase, progress, next_step, last_decision }
  • db-backup-snapshot: 현재까지의 논의 및 코드 변경점 요약
  • db-backup-active-symbols: 현재 수정 중인 파일/심볼 리스트

9. 검증 결과

작업 완료 후 이 섹션에 검증 결과 추가

9.1 테스트 케이스

입력값 예상 결과 실제 결과 상태
sam-db-backup.sh 수동 실행 daily/ 디렉토리에 .sql.gz 2개 생성
.backup_status 확인 JSON 형식, status=success
db:backup-check 실행 (백업 정상) "백업 상태 정상" 출력
db:backup-check 실행 (백업 없음) stat_alerts 기록 + Slack 알림 전송
8일 후 daily/ 확인 7일 초과 백업 자동 삭제
Slack 테스트 메시지 전송 지정 채널에 메시지 수신 확인
MNG /system/alerts 접속 알림 목록 표시, 필터 동작
MNG 읽음/해결 처리 상태 변경 후 DB 반영 확인

9.2 성공 기준 달성 현황

기준 달성 비고
sam + sam_stat 백업 파일 생성
gzip 압축 적용
보관 정책 (일간 7일, 주간 4주) 동작
Laravel 모니터링으로 백업 상태 확인
실패 시 stat_alerts 기록
실패 시 Slack 알림 전송
MNG에서 알림 목록 조회 가능
MNG에서 읽음/해결 처리 가능
운영서버 이식성 (backup.conf + .env 수정만으로 동작)

10. 자기완결성 점검 결과

10.1 체크리스트 검증

# 검증 항목 상태 비고
1 작업 목적이 명확한가? 1.1 배경에 명시
2 성공 기준이 정의되어 있는가? 9.2 성공 기준 9개
3 작업 범위가 구체적인가? 5 Phase, 14 항목
4 의존성이 명시되어 있는가? 기존 stat_alerts 인프라 활용
5 참고 파일 경로가 정확한가? 섹션 7에 명시
6 단계별 절차가 실행 가능한가? 섹션 4 상세 내용
7 검증 방법이 명시되어 있는가? 섹션 9 테스트 케이스
8 모호한 표현이 없는가? 크기/시간/경로 모두 구체적

10.2 새 세션 시뮬레이션 테스트

질문 답변 가능 참조 섹션
Q1. 이 작업의 목적은 무엇인가? 1.1 배경
Q2. 어디서부터 시작해야 하는가? 2.1 Phase 1
Q3. 어떤 파일을 수정해야 하는가? 3.4 파일 구조
Q4. 작업 완료 확인 방법은? 9. 검증 결과
Q5. 막혔을 때 참고 문서는? 7. 참고 문서

결과: 5/5 통과 → 자기완결성 확보


이 문서는 /sc:plan 스킬로 생성되었습니다.