From c00d74a04f3630c25f478245f29e94df42f8315c Mon Sep 17 00:00:00 2001 From: kent Date: Wed, 7 Jan 2026 20:10:19 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EC=95=8C=EB=A6=BC=EC=9D=8C=20=EC=8B=9C?= =?UTF-8?q?=EC=8A=A4=ED=85=9C=20=EA=B5=AC=ED=98=84=20=EA=B3=84=ED=9A=8D=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Phase 1~4 완료 (73%) - Phase 5 테스트 및 검증 대기 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- plans/notification-sound-system-plan.md | 423 ++++++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100644 plans/notification-sound-system-plan.md diff --git a/plans/notification-sound-system-plan.md b/plans/notification-sound-system-plan.md new file mode 100644 index 0000000..ef3bdbb --- /dev/null +++ b/plans/notification-sound-system-plan.md @@ -0,0 +1,423 @@ +# 알림음 시스템 구현 계획 + +> **작성일**: 2025-01-07 +> **목적**: FCM 푸시 알림 타입별 커스텀 알림음 구현 +> **영향 범위**: app (Capacitor), api (Laravel), mng (Laravel) +> **상태**: 🔄 진행중 + +--- + +## 📍 현재 진행 상태 + +| 항목 | 내용 | +|------|------| +| **마지막 완료 작업** | Phase 4.1/4.2 - 이벤트 기반 자동 푸시 서비스 생성 및 연동 ✅ | +| **다음 작업** | Phase 5 - 테스트 및 검증 | +| **진행률** | 8/11 (73%) | +| **마지막 업데이트** | 2025-01-07 | + +--- + +## 1. 개요 + +### 1.1 배경 + +현재 SAM 앱은 FCM 푸시 알림 시 2개 채널(`push_default`, `push_urgent`)만 지원합니다. +비즈니스 요구사항에 따라 알림 타입별로 다른 알림음이 필요합니다: + +- 결제 알림 → 결제 전용 알림음 +- 수주 알림 → 수주 전용 알림음 +- 발주 알림 → 발주 전용 알림음 +- 계약 알림 → 계약 전용 알림음 +- 일반 알림 → 기본 알림음 +- 신규업체 등록 → 긴급 알림음 + +### 1.2 목표 구조 + +| 타입 | 채널 ID | 알림음 파일 | 설명 | +|------|---------|------------|------| +| 결제 | `push_payment` | `push_payment.wav` | 결제 관련 알림 | +| 수주 | `push_sales_order` | `push_sales_order.wav` | 수주 관련 알림 | +| 발주 | `push_purchase_order` | `push_purchase_order.wav` | 발주 관련 알림 | +| 계약 | `push_contract` | `push_contract.wav` | 계약 관련 알림 | +| 일반 | `push_default` | `push_default.wav` | 일반 알림 (기존) | +| 신규업체 등록 | `push_urgent` | `push_urgent.wav` | 신규업체 등록 (기존) | + +### 1.3 현재 상태 분석 + +#### App (Capacitor Android) +- **파일**: `app/android/app/src/main/java/com/codebridgex/webapp/MainActivity.java` +- **현재**: 2개 채널 (`push_default`, `push_urgent`) +- **알림음**: `res/raw/push_default.wav`, `res/raw/push_urgent.wav` + +#### API (Laravel) +- **파일**: `api/app/Services/Fcm/FcmSender.php` +- **현재**: `channel_id` 파라미터 지원, 사운드는 `'default'` 하드코딩 +- **문제**: 커스텀 사운드 미지원 + +#### MNG (Laravel) +- **파일**: `mng/app/Http/Controllers/FcmController.php` +- **현재**: `sound_key` 파라미터 존재하나 실제 활용 안됨 + +### 1.4 시스템 흐름 + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ FCM 알림음 시스템 흐름 │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ MNG (발송 UI) │ +│ ┌─────────────────┐ │ +│ │ 타입 선택 │ ← 결제/수주/발주/계약/일반/신규업체 │ +│ │ channel_id 설정 │ │ +│ └────────┬────────┘ │ +│ │ │ +│ ▼ │ +│ API (FCM 발송) │ +│ ┌─────────────────┐ │ +│ │ FcmSender │ │ +│ │ channel_id → │ │ +│ │ android.channel │ │ +│ └────────┬────────┘ │ +│ │ │ +│ ▼ │ +│ Firebase Cloud Messaging │ +│ ┌─────────────────┐ │ +│ │ FCM Server │ │ +│ └────────┬────────┘ │ +│ │ │ +│ ▼ │ +│ App (Capacitor) │ +│ ┌─────────────────┐ │ +│ │ NotificationChannel │ ← channel_id로 매칭 │ +│ │ 채널별 사운드 재생 │ ← push_payment.wav 등 │ +│ └─────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 2. 대상 범위 + +### 2.1 Phase 1: App - 채널 및 알림음 추가 + +| # | 작업 항목 | 상태 | 파일 | +|---|----------|:----:|------| +| 1.1 | 알림음 파일 준비 (4개) | ✅ | `res/raw/*.wav` | +| 1.2 | MainActivity.java 채널 추가 (4개) | ✅ | `MainActivity.java` | + +### 2.2 Phase 2: API - FcmSender 수정 + +| # | 작업 항목 | 상태 | 파일 | +|---|----------|:----:|------| +| 2.1 | buildMessage() 사운드 동적 처리 | ✅ | `FcmSender.php` | +| 2.2 | 채널-사운드 매핑 (FcmSender 내부 통합) | ✅ | `FcmSender.php` | + +### 2.3 Phase 3: MNG - 발송 UI 수정 + +| # | 작업 항목 | 상태 | 파일 | +|---|----------|:----:|------| +| 3.1 | 타입 선택 드롭다운 추가 | ✅ | `fcm/send.blade.php` | +| 3.2 | 타입-채널 매핑 로직 | ✅ | `FcmController.php` | + +### 2.4 Phase 4: 이벤트 기반 자동 푸시 + +| # | 작업 항목 | 상태 | 파일 | +|---|----------|:----:|------| +| 4.1 | PushNotificationService 생성 | ✅ | `api/app/Services/PushNotificationService.php` | +| 4.2 | 신규 거래처 등록 시 푸시 | ✅ | `api/app/Services/ClientService.php` | +| 4.3 | 알림 설정 테이블 (추후) | ⏭️ | 후순위 | + +### 2.5 Phase 5: 테스트 및 검증 + +| # | 작업 항목 | 상태 | 비고 | +|---|----------|:----:|------| +| 5.1 | 각 타입별 푸시 발송 테스트 | ⏳ | 6개 타입 | +| 5.2 | 알림음 재생 확인 | ⏳ | Android 실기기 | + +--- + +## 3. 상세 작업 내용 + +### 3.1 Phase 1: App - 채널 및 알림음 추가 + +#### 1.1 알림음 파일 준비 + +**위치**: `app/android/app/src/main/res/raw/` + +| 파일명 | 상태 | 비고 | +|--------|------|------| +| `push_default.wav` | ✅ | 일반 알림 | +| `push_urgent.wav` | ✅ | 신규업체 등록 | +| `push_payment.wav` | ✅ | 결제 알림 | +| `push_sales_order.wav` | ✅ | 수주 알림 | +| `push_purchase_order.wav` | ✅ | 발주 알림 | +| `push_contract.wav` | ✅ | 계약 알림 | + +> **완료**: 6개 알림음 파일 모두 준비됨 (2025-01-07) + +#### 1.2 MainActivity.java 수정 + +**현재 코드** (2개 채널): +```java +public static final String CHANNEL_DEFAULT = "push_default"; +public static final String CHANNEL_URGENT = "push_urgent"; +``` + +**목표 코드** (6개 채널): +```java +public static final String CHANNEL_DEFAULT = "push_default"; +public static final String CHANNEL_URGENT = "push_urgent"; +public static final String CHANNEL_PAYMENT = "push_payment"; +public static final String CHANNEL_SALES_ORDER = "push_sales_order"; +public static final String CHANNEL_PURCHASE_ORDER = "push_purchase_order"; +public static final String CHANNEL_CONTRACT = "push_contract"; +``` + +### 3.2 Phase 2: API - FcmSender 수정 + +#### 2.1 buildMessage() 수정 + +**현재** (`FcmSender.php:112`): +```php +'android' => [ + 'notification' => [ + 'channel_id' => $channelId, + 'sound' => 'default', // 하드코딩 + ], +], +``` + +**목표**: +```php +'android' => [ + 'notification' => [ + 'channel_id' => $channelId, + 'sound' => $this->getSoundForChannel($channelId), + ], +], +``` + +#### 2.2 채널-사운드 매핑 + +```php +// config/fcm.php 또는 FcmSender 내부 +private function getSoundForChannel(string $channelId): string +{ + return match($channelId) { + 'push_payment' => 'push_payment', + 'push_sales_order' => 'push_sales_order', + 'push_purchase_order' => 'push_purchase_order', + 'push_contract' => 'push_contract', + 'push_urgent' => 'push_urgent', + default => 'push_default', + }; +} +``` + +### 3.3 Phase 3: MNG - 발송 UI 수정 + +#### 3.1 타입 선택 UI + +```html + +``` + +#### 3.2 타입 → 채널 매핑 + +```php +$channelMap = [ + 'general' => 'push_default', + 'payment' => 'push_payment', + 'sales_order' => 'push_sales_order', + 'purchase_order' => 'push_purchase_order', + 'contract' => 'push_contract', + 'new_company' => 'push_urgent', +]; +``` + +### 3.4 Phase 4: 이벤트 기반 자동 푸시 + +#### 4.1 PushNotificationService 생성 + +**파일**: `api/app/Services/PushNotificationService.php` + +```php +getChannelForEvent($event); + + // 해당 테넌트의 활성 토큰 조회 + $tokens = PushDeviceToken::where('tenant_id', $tenantId) + ->where('is_active', true) + ->pluck('token') + ->toArray(); + + if (empty($tokens)) { + return; + } + + $this->fcmSender->sendToMany( + $tokens, + $title, + $body, + $channelId, + $data + ); + } + + /** + * 이벤트 → 채널 매핑 + */ + private function getChannelForEvent(string $event): string + { + return match($event) { + 'payment' => 'push_payment', + 'sales_order' => 'push_sales_order', + 'purchase_order' => 'push_purchase_order', + 'contract' => 'push_contract', + 'new_client' => 'push_urgent', + default => 'push_default', + }; + } +} +``` + +#### 4.2 ClientService에서 푸시 호출 + +**파일**: `api/app/Services/ClientService.php` (store 메서드) + +```php +/** 생성 */ +public function store(array $data) +{ + $tenantId = $this->tenantId(); + + $data['client_code'] = $this->generateClientCode($tenantId); + $data['tenant_id'] = $tenantId; + $data['is_active'] = $data['is_active'] ?? true; + + $client = Client::create($data); + + // 신규 거래처 등록 푸시 발송 + app(PushNotificationService::class) + ->setTenantId($tenantId) + ->sendByEvent( + 'new_client', + $tenantId, + '신규 거래처 등록', + "새로운 거래처 '{$client->name}'이(가) 등록되었습니다.", + ['client_id' => $client->id] + ); + + return $client; +} +``` + +#### 4.3 이벤트 타입 정의 + +| 이벤트 | 채널 | 발생 시점 | +|--------|------|----------| +| `new_client` | `push_urgent` | 거래처 신규 등록 | +| `payment` | `push_payment` | 결제 완료/요청 | +| `sales_order` | `push_sales_order` | 수주 등록/변경 | +| `purchase_order` | `push_purchase_order` | 발주 등록/변경 | +| `contract` | `push_contract` | 계약 등록/만료 | + +--- + +## 4. 변경 승인 정책 + +| 분류 | 예시 | 승인 | +|------|------|------| +| ✅ 즉시 가능 | 알림음 파일 추가, 채널 추가 | 불필요 | +| ⚠️ 컨펌 필요 | FcmSender 로직 변경, UI 수정 | **필수** | +| 🔴 금지 | FCM 구조 변경, 기존 채널 삭제 | 별도 협의 | + +--- + +## 5. 컨펌 대기 목록 + +| # | 항목 | 변경 내용 | 영향 범위 | 상태 | +|---|------|----------|----------|------| +| 1 | 알림음 파일 | 6개 wav 파일 준비 | app | ✅ 완료 | + +--- + +## 6. 변경 이력 + +| 날짜 | 항목 | 변경 내용 | 파일 | 승인 | +|------|------|----------|------|------| +| 2025-01-07 | - | 계획 문서 초안 작성 | - | - | +| 2025-01-07 | 1.2 | MainActivity.java 6개 채널 추가 | `MainActivity.java` | ✅ | +| 2025-01-07 | 2.1/2.2 | FcmSender 사운드 동적 처리 + getSoundForChannel 추가 | `FcmSender.php` | ✅ | +| 2025-01-07 | 3.1 | MNG 알림 타입 드롭다운 추가 (6개 타입) | `fcm/send.blade.php` | ✅ | +| 2025-01-07 | 3.2 | FcmController channel_id 검증 + sound_key 제거 | `FcmController.php` | ✅ | +| 2025-01-07 | 4.1 | PushNotificationService 생성 (이벤트 기반 푸시) | `PushNotificationService.php` | ✅ | +| 2025-01-07 | 4.2 | ClientService.store()에 푸시 알림 연동 | `ClientService.php` | ✅ | + +--- + +## 7. 참고 문서 + +- **FCM 푸시 계획**: `docs/plans/react-fcm-push-notification-plan.md` +- **API 규칙**: `docs/standards/api-rules.md` + +--- + +## 8. 알림음 파일 준비 가이드 + +### 요구사항 +- **포맷**: WAV (권장) 또는 MP3 +- **길이**: 1-3초 권장 +- **샘플레이트**: 44.1kHz +- **비트레이트**: 16bit + +### 임시 방안 +알림음 파일이 준비되지 않은 경우, 기존 파일을 복사하여 사용: + +```bash +cd app/android/app/src/main/res/raw/ +cp push_default.wav push_payment.wav +cp push_default.wav push_sales_order.wav +cp push_default.wav push_purchase_order.wav +cp push_default.wav push_contract.wav +``` + +### 무료 알림음 리소스 +- [Pixabay Sound Effects](https://pixabay.com/sound-effects/) +- [Freesound](https://freesound.org/) +- [Zapsplat](https://www.zapsplat.com/) + +--- + +*이 문서는 /sc:plan 스킬로 생성되었습니다.* \ No newline at end of file