ㅑ# Phase 6: 커뮤니케이션 & 통계

**기간:** 1-2주
**우선순위:** 중간 (완성도 및 부가 기능)
**의존성:** Phase 1-5 (모든 데이터 활용)

## 📋 Phase 개요

고객 커뮤니케이션 및 데이터 분석 기능을 완성합니다.

**포함 기능:**
1. 설정 - 이메일 관리
2. 설정 - 문자 관리
3. 통계 (Statistics & Analytics)

---

## 1️⃣ 설정 - 이메일 관리

### 기능 목록

#### 1.1 SMTP 설정
- **경로:** `/mng/settings/email/smtp`
- **기능:**
  - SMTP 서버 정보 (호스트, 포트, 암호화)
  - 인증 정보 (사용자명, 비밀번호)
  - 발신자 정보 (이름, 이메일)
  - 테스트 메일 발송
- **권한:** `settings.email.smtp`

#### 1.2 이메일 템플릿 관리
- **경로:** `/mng/settings/email/templates`
- **기능:**
  - 템플릿 생성/수정/삭제
  - 타입별 템플릿 (회원가입, 비밀번호 재설정, 결제 완료 등)
  - HTML 에디터 (변수 치환 지원)
  - 미리보기
- **권한:** `settings.email.templates`

#### 1.3 이메일 발송 내역
- **경로:** `/mng/settings/email/history`
- **기능:**
  - 발송 내역 목록
  - 검색 (수신자, 제목)
  - 필터 (상태, 날짜)
  - 재발송
  - 실패 로그 확인
- **권한:** `settings.email.history`

#### 1.4 이메일 예약 발송
- **경로:** `/mng/settings/email/scheduled`
- **기능:**
  - 예약 발송 목록
  - 새 예약 생성
  - 예약 취소
- **권한:** `settings.email.scheduled`

### DB 스키마

```sql
CREATE TABLE email_settings (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id BIGINT UNSIGNED NULL COMMENT 'NULL = 전역 설정',
    smtp_host VARCHAR(255) NOT NULL,
    smtp_port INT DEFAULT 587,
    smtp_encryption ENUM('tls', 'ssl', 'none') DEFAULT 'tls',
    smtp_username VARCHAR(255) NOT NULL,
    smtp_password VARCHAR(255) NOT NULL COMMENT '암호화 저장',
    from_name VARCHAR(255) NOT NULL,
    from_email VARCHAR(255) NOT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    INDEX idx_tenant_id (tenant_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE email_templates (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id BIGINT UNSIGNED NULL,
    name VARCHAR(255) NOT NULL,
    type VARCHAR(100) NOT NULL COMMENT 'welcome, password_reset, payment_success 등',
    subject VARCHAR(255) NOT NULL,
    body TEXT NOT NULL COMMENT 'HTML 내용',
    variables JSON NULL COMMENT '사용 가능한 변수',
    is_default BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP NULL,

    INDEX idx_tenant_id (tenant_id),
    INDEX idx_type (type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE email_logs (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id BIGINT UNSIGNED NULL,
    template_id BIGINT UNSIGNED NULL,
    recipient_email VARCHAR(255) NOT NULL,
    recipient_name VARCHAR(255) NULL,
    subject VARCHAR(255) NOT NULL,
    body TEXT NOT NULL,
    status ENUM('pending', 'sent', 'failed') DEFAULT 'pending',
    sent_at TIMESTAMP NULL,
    failed_reason TEXT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    INDEX idx_tenant_id (tenant_id),
    INDEX idx_status (status),
    INDEX idx_recipient_email (recipient_email),
    INDEX idx_sent_at (sent_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

### API 엔드포인트

| Method | Endpoint | Description | FormRequest |
|--------|----------|-------------|-------------|
| GET | `/mng/settings/email/smtp` | SMTP 설정 조회 | - |
| PUT | `/mng/settings/email/smtp` | SMTP 설정 저장 | `UpdateSmtpRequest` |
| POST | `/mng/settings/email/smtp/test` | 테스트 메일 발송 | `TestEmailRequest` |
| GET | `/mng/settings/email/templates` | 템플릿 목록 | - |
| POST | `/mng/settings/email/templates` | 템플릿 생성 | `StoreEmailTemplateRequest` |
| PUT | `/mng/settings/email/templates/{id}` | 템플릿 수정 | `UpdateEmailTemplateRequest` |
| GET | `/mng/settings/email/history` | 발송 내역 | - |
| POST | `/mng/settings/email/send` | 이메일 발송 | `SendEmailRequest` |

### Service 클래스

```php
// app/Services/EmailService.php
class EmailService
{
    public function getSettings(int $tenantId = null): ?EmailSetting;
    public function updateSettings(array $data, int $tenantId = null): EmailSetting;
    public function testConnection(EmailSetting $setting, string $testEmail): bool;

    public function listTemplates(int $tenantId = null): Collection;
    public function createTemplate(array $data): EmailTemplate;
    public function updateTemplate(EmailTemplate $template, array $data): EmailTemplate;
    public function render(EmailTemplate $template, array $variables): string;

    public function send(string $to, string $subject, string $body, int $templateId = null): EmailLog;
    public function sendBulk(array $recipients, string $subject, string $body): int;
    public function getHistory(array $filters): LengthAwarePaginator;
    public function retry(EmailLog $log): bool;
}
```

### 개발 체크리스트

- [ ] `EmailSetting`, `EmailTemplate`, `EmailLog` 모델 작성
- [ ] `EmailService` 클래스 작성
- [ ] Laravel Mail + Queue 설정
- [ ] SMTP 연결 테스트 기능
- [ ] 템플릿 변수 치환 로직
- [ ] 예약 발송 스케줄러 (Laravel Schedule)
- [ ] 실패 재시도 로직
- [ ] FormRequest 작성
- [ ] i18n 키 작성
- [ ] 테스트 작성

---

## 2️⃣ 설정 - 문자 관리

### 기능 목록

#### 2.1 SMS API 설정
- **경로:** `/mng/settings/sms/api`
- **기능:**
  - API 연동 설정 (알리고, 카카오 알림톡 등)
  - API 키 관리
  - 발신 번호 설정
  - 테스트 문자 발송
- **권한:** `settings.sms.api`

#### 2.2 문자 템플릿 관리
- **경로:** `/mng/settings/sms/templates`
- **기능:**
  - 템플릿 생성/수정/삭제
  - SMS (90자), LMS (2000자) 구분
  - 변수 치환 지원
  - 바이트 수 자동 계산
- **권한:** `settings.sms.templates`

#### 2.3 문자 발송 내역
- **경로:** `/mng/settings/sms/history`
- **기능:**
  - 발송 내역 목록
  - 검색 (수신자, 내용)
  - 필터 (상태, 날짜, 타입)
  - 재발송
  - 실패 로그 확인
- **권한:** `settings.sms.history`

#### 2.4 대량 문자 발송
- **경로:** `/mng/settings/sms/bulk`
- **기능:**
  - 엑셀 업로드 (수신자 목록)
  - 템플릿 선택
  - 예약 발송
  - 발송 결과 확인
- **권한:** `settings.sms.bulk`

### DB 스키마

```sql
CREATE TABLE sms_settings (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id BIGINT UNSIGNED NULL,
    provider VARCHAR(50) NOT NULL COMMENT 'aligo, kakao 등',
    api_key VARCHAR(255) NOT NULL COMMENT '암호화 저장',
    api_secret VARCHAR(255) NULL,
    sender_number VARCHAR(20) NOT NULL COMMENT '발신 번호',
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    INDEX idx_tenant_id (tenant_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE sms_templates (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id BIGINT UNSIGNED NULL,
    name VARCHAR(255) NOT NULL,
    type ENUM('sms', 'lms', 'mms') DEFAULT 'sms',
    content TEXT NOT NULL,
    variables JSON NULL,
    byte_count INT NOT NULL COMMENT '바이트 수',
    is_default BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP NULL,

    INDEX idx_tenant_id (tenant_id),
    INDEX idx_type (type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE sms_logs (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id BIGINT UNSIGNED NULL,
    template_id BIGINT UNSIGNED NULL,
    recipient_number VARCHAR(20) NOT NULL,
    content TEXT NOT NULL,
    type ENUM('sms', 'lms', 'mms') DEFAULT 'sms',
    status ENUM('pending', 'sent', 'failed') DEFAULT 'pending',
    sent_at TIMESTAMP NULL,
    failed_reason TEXT NULL,
    api_message_id VARCHAR(255) NULL COMMENT 'API 메시지 ID',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    INDEX idx_tenant_id (tenant_id),
    INDEX idx_status (status),
    INDEX idx_sent_at (sent_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

### API 엔드포인트

| Method | Endpoint | Description | FormRequest |
|--------|----------|-------------|-------------|
| GET | `/mng/settings/sms/api` | SMS API 설정 조회 | - |
| PUT | `/mng/settings/sms/api` | SMS API 설정 저장 | `UpdateSmsApiRequest` |
| POST | `/mng/settings/sms/api/test` | 테스트 문자 발송 | `TestSmsRequest` |
| GET | `/mng/settings/sms/templates` | 템플릿 목록 | - |
| POST | `/mng/settings/sms/templates` | 템플릿 생성 | `StoreSmsTemplateRequest` |
| POST | `/mng/settings/sms/send` | 문자 발송 | `SendSmsRequest` |
| POST | `/mng/settings/sms/bulk` | 대량 발송 | `SendBulkSmsRequest` |
| GET | `/mng/settings/sms/history` | 발송 내역 | - |

### Service 클래스

```php
// app/Services/SmsService.php
class SmsService
{
    public function getSettings(int $tenantId = null): ?SmsSetting;
    public function updateSettings(array $data, int $tenantId = null): SmsSetting;
    public function testConnection(SmsSetting $setting, string $testNumber): bool;

    public function listTemplates(int $tenantId = null): Collection;
    public function createTemplate(array $data): SmsTemplate;
    public function updateTemplate(SmsTemplate $template, array $data): SmsTemplate;
    public function calculateByteCount(string $content): int;

    public function send(string $to, string $content, string $type = 'sms', int $templateId = null): SmsLog;
    public function sendBulk(array $recipients, string $content, string $type = 'sms'): int;
    public function getHistory(array $filters): LengthAwarePaginator;
    public function retry(SmsLog $log): bool;
}
```

### 개발 체크리스트

- [ ] `SmsSetting`, `SmsTemplate`, `SmsLog` 모델 작성
- [ ] `SmsService` 클래스 작성
- [ ] SMS API 연동 (알리고 우선)
- [ ] 바이트 수 계산 로직 (한글 2바이트)
- [ ] 대량 발송 큐 처리
- [ ] 엑셀 업로드 파싱 (PhpSpreadsheet)
- [ ] 발송 결과 웹훅 처리
- [ ] FormRequest 작성
- [ ] i18n 키 작성
- [ ] 테스트 작성

---

## 3️⃣ 통계 (Statistics & Analytics)

### 기능 목록

#### 3.1 대시보드
- **경로:** `/mng/dashboard`
- **기능:**
  - 주요 KPI 카드 (회원 수, 매출, 구독 현황)
  - 최근 활동 로그
  - 영업 파이프라인 요약
  - 결제 통계
- **권한:** `dashboard.view`

#### 3.2 회원 통계
- **경로:** `/mng/statistics/users`
- **기능:**
  - 가입자 추세 (일별, 월별)
  - 활성/비활성 비율
  - 부서별 분포
  - 엑셀 내보내기
- **권한:** `statistics.users`

#### 3.3 매출 통계
- **경로:** `/mng/statistics/revenue`
- **기능:**
  - 매출 추세 (일별, 월별, 연별)
  - 플랜별 매출
  - MRR (Monthly Recurring Revenue)
  - ARR (Annual Recurring Revenue)
  - 차트 (Chart.js 또는 ApexCharts)
- **권한:** `statistics.revenue`

#### 3.4 영업 통계
- **경로:** `/mng/statistics/sales`
- **기능:**
  - 파이프라인 단계별 통계
  - 전환율 (Conversion Rate)
  - 담당자별 성과
  - 기간별 비교
- **권한:** `statistics.sales`

#### 3.5 구독 통계
- **경로:** `/mng/statistics/subscriptions`
- **기능:**
  - 플랜별 구독 현황
  - 이탈률 (Churn Rate)
  - 업그레이드/다운그레이드 추세
  - 리텐션 분석
- **권한:** `statistics.subscriptions`

### DB 스키마

```sql
-- 통계 스냅샷 (일별 집계)
CREATE TABLE statistics_snapshots (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id BIGINT UNSIGNED NULL COMMENT 'NULL = 전체',
    snapshot_date DATE NOT NULL,
    metric_type ENUM('users', 'revenue', 'sales', 'subscriptions') NOT NULL,
    metric_data JSON NOT NULL COMMENT '통계 데이터',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_tenant_id (tenant_id),
    INDEX idx_snapshot_date (snapshot_date),
    INDEX idx_metric_type (metric_type),
    UNIQUE KEY unique_snapshot (tenant_id, snapshot_date, metric_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

### API 엔드포인트

| Method | Endpoint | Description | Query Params |
|--------|----------|-------------|--------------|
| GET | `/mng/dashboard` | 대시보드 데이터 | - |
| GET | `/mng/statistics/users` | 회원 통계 | `start_date`, `end_date`, `group_by` |
| GET | `/mng/statistics/revenue` | 매출 통계 | `start_date`, `end_date`, `group_by` |
| GET | `/mng/statistics/sales` | 영업 통계 | `start_date`, `end_date` |
| GET | `/mng/statistics/subscriptions` | 구독 통계 | `start_date`, `end_date` |
| GET | `/mng/statistics/export` | 엑셀 내보내기 | `type`, `start_date`, `end_date` |

### Service 클래스

```php
// app/Services/StatisticsService.php
class StatisticsService
{
    public function getDashboardData(int $tenantId = null): array;

    public function getUserStats(array $filters): array;
    public function getRevenueStats(array $filters): array;
    public function getSalesStats(array $filters): array;
    public function getSubscriptionStats(array $filters): array;

    public function calculateMRR(int $tenantId = null): float;
    public function calculateARR(int $tenantId = null): float;
    public function calculateChurnRate(array $filters): float;
    public function calculateConversionRate(array $filters): float;

    public function exportToExcel(string $type, array $filters): string; // 파일 경로
    public function createSnapshot(string $metricType, int $tenantId = null): void; // 일별 스냅샷 생성
}
```

### UI 컴포넌트

```
┌─────────────────────────────────────────────────────────┐
│ 대시보드                                                 │
├─────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐   │
│ │회원 1,234│ │매출 5.2M │ │구독 567  │ │영업 89   │   │
│ │↑ 12%     │ │↑ 8%      │ │↓ 3%      │ │↑ 15%     │   │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘   │
│                                                         │
│ ┌─────────────────────────────────────────────────────┐│
│ │ 매출 추세 (최근 6개월)          [Chart.js 꺾은선]  ││
│ └─────────────────────────────────────────────────────┘│
│                                                         │
│ ┌─────────────────────────────────────────────────────┐│
│ │ 영업 파이프라인               [Chart.js 퍼널 차트] ││
│ └─────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
```

### 개발 체크리스트

- [ ] `StatisticsSnapshot` 모델 작성
- [ ] `StatisticsService` 클래스 작성
- [ ] 통계 계산 로직 (MRR, ARR, Churn Rate 등)
- [ ] Chart.js 또는 ApexCharts 통합
- [ ] 일별 스냅샷 스케줄러
- [ ] 엑셀 내보내기 (PhpSpreadsheet)
- [ ] 대시보드 UI 작성
- [ ] 날짜 필터 UI (Alpine.js)
- [ ] i18n 키 작성
- [ ] 테스트 작성

---

## 🎯 Phase 6 완료 조건

### 기능 완성도
- [ ] 이메일 발송 동작
- [ ] 문자 발송 동작
- [ ] 통계 차트 표시
- [ ] 엑셀 내보내기 동작

### 코드 품질
- [ ] Service-First, FormRequest 준수
- [ ] 큐 처리 안정성
- [ ] i18n 키 사용
- [ ] Pint, PHPStan 통과

### 외부 연동
- [ ] SMTP 연결 안정성
- [ ] SMS API 연동 동작
- [ ] 웹훅 처리 (발송 결과)

### 성능
- [ ] 대량 발송 큐 처리
- [ ] 통계 쿼리 최적화
- [ ] 스냅샷 생성 스케줄러

### 테스트
- [ ] 이메일 발송 테스트 (Mock)
- [ ] 문자 발송 테스트 (Mock)
- [ ] 통계 계산 로직 테스트
- [ ] 엑셀 생성 테스트

---

## 🎉 MNG 애플리케이션 전체 완료

Phase 6가 완료되면 MNG 애플리케이션의 핵심 기능이 모두 구현됩니다.

**다음 단계:**
1. 전체 통합 테스트
2. 성능 최적화
3. 사용자 매뉴얼 작성
4. 배포 준비

**참고 문서:**
- `00_OVERVIEW.md` - 전체 개발 계획
- `99_TECHNICAL_STANDARDS.md` - 기술 표준

---

**최종 업데이트:** 2025-11-21
**작성자:** Claude Code
**버전:** 1.0.0