# 알림음 시스템 구현 계획 > **작성일**: 2025-01-07 > **목적**: FCM 푸시 알림 타입별 커스텀 알림음 구현 > **영향 범위**: app (Capacitor), api (Laravel), mng (Laravel) > **상태**: ✅ 핵심 기능 완료 (4.3 알림 설정 테이블은 후순위) --- ## 📍 현재 진행 상태 | 항목 | 내용 | |------|------| | **마지막 완료 작업** | Phase 5 - 테스트 및 검증 완료 ✅ | | **다음 작업** | 완료 (4.3 알림 설정 테이블은 후순위) | | **진행률** | 10/11 (91%) - 핵심 기능 완료 | | **마지막 업데이트** | 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` | ✅ | | 2025-01-07 | 5.1/5.2 | 테스트 및 검증 완료 | 서버 배포 후 실기기 테스트 | ✅ | --- ## 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 스킬로 생성되었습니다.*