오류 log

iOS에서 Flutter Firebase 푸시 알림 충돌? APNs 오류 해결 방법

Alan__kang__morlang 2025. 5. 16. 09:48
반응형

Firebase FCM iOS 빌드 크래시 이슈 보고서

문제 요약

Flutter 앱에서 Firebase Cloud Messaging(FCM)을 연동한 후 iOS 기기에서 앱을 실행하면 앱이 곧바로 크래시(crash) 되는 문제가 보고되었습니다. 특히 푸시 알림 권한을 승인받거나 FCM 토큰을 요청하는 시점에 문제가 발생하며, 디버그 콘솔에는 "APNS token has not been set yet. Please ensure the APNS token is available by calling getAPNSToken()"와 같은 오류 메시지가 나타납니다. 이는 iOS에서 FCM 초기화 또는 푸시 수신 과정에서 필요한 APNs 토큰을 찾지 못해 예외가 발생한 상황으로, 사용자는 정상적인 FCM 토큰 발급이나 알림 수신 전에 앱이 종료되는 증상을 겪게 됩니다.

원인 분석

이 크래시는 Firebase FCM iOS SDK의 토큰 연동 방식 때문에 발생합니다. FCM은 iOS에서 **Apple Push Notification service(APNs)**를 통해 푸시를 전달받는데, FCM 토큰을 발급하거나 주제를 구독하기 전에 **디바이스의 APNs 토큰(디바이스 토큰)**이 준비되어 있어야 합니다. 최신 FlutterFire(firebase_messaging)에서는 APNs 토큰이 없을 경우 FirebaseMessaging.instance.getToken()이나 subscribeToTopic() 호출 시 예외를 던지도록 변경되었는데, iOS에서 APNs 토큰을 얻기 전에 FCM 관련 메서드를 호출하면 예외가 발생하며 이것이 크래시로 이어집니다. 요약하면, iOS 기기에서 푸시 알림을 받기 위한 사전 준비 부족 또는 타이밍 이슈가 근본 원인입니다.

구체적인 원인 시나리오는 다음과 같습니다:

  • APNs 미설정 또는 권한 미획득: iOS 프로젝트에서 Push Notifications 기능이나 Remote Notifications 백그라운드 모드가 활성화되지 않았거나, 사용자에게 알림 권한을 요청하지 않은 경우 APNs 토큰이 발급되지 않습니다. 그 상태에서 FCM 토큰을 요청하면 APNs 토큰 누락으로 예외가 발생할 수 있습니다.
  • 초기 토큰 요청 타이밍: 앱 첫 실행 시 사용자 권한을 받자마자 바로 FCM 토큰을 요청하면, 내부적으로 APNs 토큰이 아직 준비되지 않아 [firebase_messaging/apns-token-not-set] 예외가 발생할 수 있습니다. 이는 초기 실행 시점의 토큰 동기화 지연 문제로 볼 수 있습니다.
  • 메서드 스위즐링 비활성화: 고급 설정으로 Info.plist에서 FirebaseAppDelegateProxyEnabledNO로 설정해 Firebase 자동 설정을 비활성화한 경우, APNs 토큰을 FCM에 수동으로 연결해야 합니다. 만약 개발자가 AppDelegatedidRegisterForRemoteNotificationsWithDeviceToken 구현에서 Messaging.messaging().apnsToken = deviceToken 처리를 누락하면 APNs 토큰이 FCM에 등록되지 않아 동일한 문제가 발생합니다.

해결책

일반적인 해결 방법은 iOS에서 FCM 푸시를 위한 설정을 완전하게 하고, APNs 토큰이 준비된 후에 FCM 기능을 사용하도록 하는 것입니다. 최신 Flutter 및 Firebase 환경에서 검증된 해결 절차는 다음과 같습니다.

  1. iOS 프로젝트 설정 확인: Xcode에서 Push Notifications 기능과 Background ModesRemote notifications 항목이 활성화되어 있는지 확인합니다. 이는 앱에 aps-environment 권한을 추가하여 APNs 토큰 발급을 가능하게 합니다. 또한 Apple Developer 콘솔에 APNs 인증 키를 등록하고 Firebase 프로젝트에 해당 키를 업로드했는지 확인합니다 (FCM이 APNs와 통신하기 위함).
  2. 알림 권한 요청: Flutter 앱 실행 시, iOS 사용자에게 푸시 알림 권한을 요청해야 합니다. FirebaseMessaging.instance.requestPermission(...) 메서드를 호출하여 알림 허용을 받아야만 APNs 토큰이 기기에 발급됩니다. 권한 획득 후 UIApplication.shared.registerForRemoteNotifications()가 자동으로 호출되어 APNs에 디바이스를 등록합니다 (FlutterFire가 내부적으로 수행).
  3. APNs 토큰 확보 후 FCM 사용: 중요: 권한을 얻었다면 곧바로 FCM 토큰을 요청하거나 주제 구독을 하지 말고, APNs 토큰이 준비될 시간을 확보해야 합니다. 실무적으로 약간의 지연을 준 후 FCM 토큰을 요청하거나, APNs 토큰을 직접 확인하여 받은 다음 진행합니다. 예를 들어 다음과 같이 구현할 수 있습니다:위 코드는 iOS에서 getAPNSToken()으로 APNs 토큰을 가져올 때 처음에 null이면 잠시 후 재시도하여 토큰을 확보한 뒤 getToken()을 호출하는 방식입니다. 이렇게 하면 초기 실행 시점의 토큰 미발급으로 인한 크래시를 예방할 수 있습니다. 실제 Stack Overflow 사례에서도 3초 지연 후 재시도 전략으로 문제를 해결하였으며, Firebase도 “APNS 토큰이 준비된 후 FCM 토큰을 받아야 한다”고 안내하고 있습니다.
  4. if (Platform.isIOS) { // APNs 토큰 확인 String? apnsToken = await FirebaseMessaging.instance.getAPNSToken(); if (apnsToken == null) { await Future.delayed(Duration(seconds: 2)); // 잠시 대기 apnsToken = await FirebaseMessaging.instance.getAPNSToken(); } } // 이제 FCM 토큰 획득 혹은 주제 구독 진행 String fcmToken = await FirebaseMessaging.instance.getToken();
  5. 자동 초기화 설정 점검: 특별한 경우가 아니라면 **Firebase의 iOS Delegate 프록시(메서드 스위즐링)**를 비활성화하지 않는 것이 좋습니다. 기본 설정을 유지하면 Firebase iOS SDK가 앱 실행 시 자동으로 APNs 토큰과 FCM을 연동해주므로 개발자가 수동으로 처리할 필요가 없습니다. 만약 필요에 의해 프록시를 끄는 경우, AppDelegate.application(_:didRegisterForRemoteNotificationsWithDeviceToken:) 구현을 추가하고 그 안에서 Messaging.messaging().apnsToken = deviceToken 코드를 넣어 수동으로 APNs 토큰을 FCM에 설정해야 합니다.
  6. 실제 기기에서 테스트: 시뮬레이터에서는 APNs 푸시 토큰이 발급되지 않으므로, 반드시 실제 iOS 디바이스에서 테스트해야 합니다. 실제 기기에서 위 설정과 코드를 적용하면 FCM 토큰이 정상적으로 발급되고 푸시 알림 수신 시 크래시 없이 동작할 것입니다.

요약하면, iOS에서 FCM 사용 시에는 APNs 연동과 권한 처리를 정확히 하고, 토큰 발급의 타이밍을 조절하는 것이 핵심 해결책입니다. 이를 통해 해당 크래시를 방지하고 Firebase FCM 기능을 정상적으로 사용할 수 있습니다.

참고 링크

  • FlutterFire 공식 문서: FCM iOS(APNs) 통합 가이드 – iOS에서 Push NotificationsBackground Modes 설정 방법, 앱 딜리게이트에서 APNs 토큰 연동 방법 등이 설명되어 있습니다.
  • Stack Overflow Q&A:Flutter - APNS token has not been set yet...” – iOS에서 APNs 토큰 미설정으로 FCM 토큰 요청시 예외가 발생하는 문제를 다룬 질문으로, APNs 토큰을 확보한 뒤 토픽 구독/토큰요청을 수행하는 해결책을 제시합니다.
  • GitHub 이슈 논의: FlutterFire 저장소 이슈에서 유사한 오류 로그와 해결 논의가 이루어진 사례 – [firebase_messaging/apns-token-not-set] 예외와 Unhandled Exception 로그를 통해 원인과 해결 필요성을 파악할 수 있습니다. 이는 본 문제의 원인이 APNs 토큰 미연동임을 잘 보여줍니다.

 

반응형