Conversation
- pubspec.yaml에 firebase_messaging 및 flutter_local_notifications 의존성을 추가 - 안드로이드(AndroidManifest.xml, colors.xml)와 iOS(Info.plist, Runner.entitlements)에서 푸시 알림 지원을 위한 권한, 메타데이터, 백그라운드 모드를 포함한 설정 - 알림 서비스 (NotificationService.dart) 구현 - 백엔드와의 FCM 토큰 등록 연동 - 애플리케이션 구조 및 라우터 연동 (후에 딥링크 라우터 위함.)
- Ably 리시버 제거: FCM 메시지를 가로채어 CPU 점유율을 94%까지 높이던 Ably의 FirebaseMessagingReceiver를 AndroidManifest.xml에서 명시적으로 제외함. - 핸들러 등록 시점 조정: 시스템이 즉각 반응할 수 있도록 백그라운드 핸들러 등록 로직을 main() 함수의 최상단으로 이동. - 비차단 초기화: 권한 요청, 폰트 로딩 등 시간이 걸리는 로직에서 await를 제거하여 메인 스레드가 멈추는 현상 방지. - 고성능 로깅: 동기식 print를 비동기식 dart:developer.log로 교체하고, kDebugMode 가드와 문자열 길이 제한을 적용하여 디버깅 효율과 성능을 향상시킴. - 중복 리스너 최적화: AuthViewModel의 상태 변화에 따른 토큰 등록 리스너가 중복 생성되지 않도록 로직 정밀화.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 PR은 앱에 푸시 알림 기능을 전면적으로 도입하고 관련 인프라를 구축하는 것을 목표로 합니다. Firebase Cloud Messaging과 Flutter Local Notifications을 활용하여 사용자에게 알림을 보낼 수 있는 기반을 마련했으며, 안드로이드 및 iOS 플랫폼에 필요한 모든 설정을 완료했습니다. 또한, 알림 서비스의 안정성과 디버깅 편의성을 높이기 위한 여러 개선 사항과 네트워크 요청 로깅 기능도 포함되어 있습니다. 이를 통해 사용자 참여를 유도하고 중요한 정보를 효과적으로 전달할 수 있는 새로운 채널이 확보되었습니다. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
| /* | ||
| switch (notificationType) { | ||
| case 'LIKE': | ||
| case 'COMMENT': | ||
| case 'REPLY': | ||
| final diaryId = metadata['diaryId']; | ||
| if (diaryId != null) { | ||
| // 현재 일기 상세 라우트가 없으므로, 필요 시 GoRouter에 추가해야 함 | ||
| // GoRouter.of(context).push('/book-log/detail/$diaryId'); | ||
| if (kDebugMode) dev.log("Navigating to Diary Detail for diaryId: $diaryId (Currently commented out)", name: 'NOTIFICATION'); | ||
| } | ||
| break; | ||
| case 'FOLLOW': | ||
| final memberId = metadata['memberId']; | ||
| if (memberId != null) { | ||
| GoRouter.of(context).push('/profile/$memberId'); // 예시 라우트 | ||
| if (kDebugMode) dev.log("Navigating to Member Profile for memberId: $memberId (Currently commented out)", name: 'NOTIFICATION'); | ||
| } | ||
| break; | ||
| case 'QUIZ_COMPLETED': | ||
| final bookId = metadata['bookId']; | ||
| final challengeId = metadata['challengeId']; | ||
| if (bookId != null && challengeId != null) { | ||
| GoRouter.of(context).push('/reading-challenge/detail/$bookId?challengeId=$challengeId'); | ||
| if (kDebugMode) dev.log("Navigating to Reading Challenge Detail for bookId: $bookId, challengeId: $challengeId (Currently commented out)", name: 'NOTIFICATION'); | ||
| } | ||
| break; | ||
| default: | ||
| if (kDebugMode) dev.log("Unknown notification type or no navigation defined for: $notificationType", name: 'NOTIFICATION'); | ||
| break; | ||
| } | ||
| */ |
| <key>aps-environment</key> | ||
| <string>development</string> |
There was a problem hiding this comment.
iOS 푸시 알림 환경 설정(aps-environment)이 development로 직접 설정되어 있습니다. 프로덕션 빌드 시에는 이 값을 production으로 변경해야 합니다. Xcode 빌드 설정에서 CODE_SIGN_ENTITLEMENTS를 사용하여 빌드 구성에 따라 자동으로 development 또는 production으로 전환되도록 관리하는 것이 좋습니다. 이렇게 하면 수동 변경으로 인한 실수를 방지할 수 있습니다.
<key>aps-environment</key>
<string>$(APS_ENVIRONMENT)</string>
| // 로그인 상태가 아니거나 로딩 중이면 토큰 등록을 보류하거나 스킵 | ||
| // (나중에 로그인 성공 시 다시 호출하도록 로직 보완 필요할 수 있음) | ||
| if (authState.value is! AuthSuccess) { | ||
| if (kDebugMode) dev.log("User not logged in. Skipping FCM token registration.", name: 'NOTIFICATION'); | ||
| return; | ||
| } |
| String? title = message.notification?.title ?? message.data['title'] ?? message.data['messageTitle']; | ||
| String? body = message.notification?.body ?? message.data['body'] ?? message.data['messageBody'] ?? message.data['content']; |
There was a problem hiding this comment.
| // TODO: 여기서 데이터 파싱 및 라우팅 로직 구현 | ||
| // routerProvider 접근을 위해 BuildContext가 필요하며, | ||
| // NotificationService가 직접 Riverpod Consumer가 아니므로 | ||
| // rootNavigatorKey를 통해 context를 얻어 GoRouter를 사용해야 합니다. | ||
| final context = rootNavigatorKey.currentContext; | ||
| if (context == null) { | ||
| if (kDebugMode) dev.log("Router context not available for navigation.", name: 'NOTIFICATION'); | ||
| return; | ||
| } |
There was a problem hiding this comment.
_handleMessageData 함수 내에서 rootNavigatorKey.currentContext를 사용하여 라우터 컨텍스트를 가져오는 방식은 NotificationService가 BuildContext에 직접 의존하지 않도록 하는 좋은 방법입니다. 그러나 context가 null일 경우 dev.log만 하고 반환하는 것은 알림 클릭 시 내비게이션이 필요한 경우 사용자 경험에 영향을 줄 수 있습니다. context가 null이 아닌 경우에만 내비게이션 로직이 실행되도록 하는 것은 좋지만, null인 경우에 대한 사용자 피드백(예: 토스트 메시지)이나 추가적인 처리 방안을 고려해볼 수 있습니다.
- ios/Runner/Runner.entitlements의 aps-environment 값을 $(APS_ENVIRONMENT) 변수로 변경하여 빌드 환경에 따라 자동 전환되도록 수정 - NotificationService._registerToken에 지수 백오프(Exponential Backoff) 기반 재시도 로직을 추가하여 토큰 등록의 견고함을 강화 - 로그인 성공 시점 및 앱 초기 구동 시 로그인 상태를 감지하여 토큰 등록을 시도하는 리스너 로직을 고도화 - 네트워크 불안정 등으로 인한 토큰 등록 실패 케이스에 대응하고 로깅(Logging) 시스템을 강화
Fixes #227
변경사항
pubspec.yaml에 firebase_messaging 및 flutter_local_notifications 의존성을 추가
안드로이드(AndroidManifest.xml, colors.xml)와 iOS(Info.plist, Runner.entitlements)에서 푸시 알림 지원을 위한 권한, 메타데이터, 백그라운드 모드를 포함한 설정
알림 서비스 (NotificationService.dart) 구현
백엔드와의 FCM 토큰 등록 연동
애플리케이션 구조 및 라우터 연동 (후에 딥링크 라우터 위함.)
알림 기능 개선 (
NotificationService)네트워크 로깅 추가 (
DioClient)안드로이드 설정 수정
TODO
refactor: 푸시 알림 환경 동적 설정 및 FCM 토큰 등록 로직 개선