Files
sam-manage/docs/06_PHASE6_COMM_STATS.md
hskwon 76c8a94e4f docs: MNG 프로젝트 문서 정비
- 개발 단계별 문서 추가 (00_OVERVIEW ~ 06_PHASE)
- 기술 표준 문서 추가 (99_TECHNICAL_STANDARDS)
- 개발 프로세스 및 패턴 문서 추가
  - API_FLOW_TESTER_DESIGN, DEV_PROCESS
  - HTMX_API_PATTERN, LAYOUT_PATTERN
  - SETUP_GUIDE, MNG_PROJECT_PLAN
- 프로젝트 관리 문서 추가 (project-management/)
- INDEX.md, MNG_CRITICAL_RULES.md 업데이트
2025-11-30 21:04:19 +09:00

500 lines
18 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

ㅑ# 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