PromleeBlog
sitemapaboutMe

posting thumbnail
Flutter에서 FCM 푸쉬 알림 보내기
Send push notifications from Flutter to FCM

📅

🚀

들어가기 전에🔗

이 포스팅은 Flutter 3.24 버전 기준으로 작성되었습니다.
플러터 프로젝트 및 파이어베이스 프로젝트가 모두 연결되어 있다는 가정하에 작성되었습니다. 만약 파이어베이스 프로젝트가 없다면 아래 링크를 참고하여 파이어베이스 프로젝트를 생성해주세요.
Firebase에 Flutter 기반 앱 등록하기

FCM이란?🔗

FCM 아키텍처 개요 - (출처) https://firebase.google.com/docs/cloud-messaging/fcm-architecture
FCM 아키텍처 개요 - (출처) https://firebase.google.com/docs/cloud-messaging/fcm-architecture
Firebase Cloud Messaging(FCM)은 무료로 메시지를 안정적으로 전송할 수 있는 크로스 플랫폼 메시징 솔루션입니다.
FCM 구현에는 송수신을 위한 두 가지 주요 구성요소가 필요하며 간단히 설명하면 다음과 같습니다.
  1. Cloud Functions for Firebase 또는 앱 서버와 같이 메시지를 작성, 타겟팅, 전송할 수 있는 신뢰할 수 있는 환경
  2. 해당 플랫폼별 전송 서비스를 통해 메시지를 수신하는 Apple, Android 또는 웹(자바스크립트) 클라이언트 앱
주로 1번은 백엔드 서버, 2번은 플러터 앱이라고 보시면 됩니다. 이번 포스팅에서는 주로 2번, 플러터 앱에서 FCM토큰을 발급받고, 푸쉬 알림을 수신하는 방법을 알아보겠습니다.

🚀

1. IOS 설정🔗

Apple developer 계정이 필요합니다. 없다면 Apple Developer에 가입, 폭은 이 과정은 패스 후 안드로이드만 진행해주세요

1.1. APNs 인증키 생성🔗

Apple Developer 포털 - Auth Keys에 접속 후 로그인을 해준 후 Keys 제목 오른쪽에 있는 + 버튼을 눌러 새로운 인증키를 생성합니다.
  1. 임의의 이름을 입력 후 APNs를 선택합니다.
  2. Configure 버튼을 눌러 목적에 맞게 원하는 속성을 선택해 설정을 마무리합니다.
  3. 설정 완료 후 Continue -> Register 버튼을 차례로 눌러 키 생성을 완료해주세요.
image
🖐️
주의!!!! 여기서 꼭 키를 다운받아 잘 저장해주세요.
image
완료되었다면 다음과 같이 key가 발급되게 됩니다.
image

1.2. Identifiers 설정🔗

Apple Developer 포털 - Identifiers에 접속 후 로그인을 해준 후 Identifiers 제목 오른쪽에 있는 + 버튼을 눌러 새로운 식별자를 생성합니다.
  1. App IDs를 선택, 다음 창에서 App을 선택하고 Continue 합니다.
    image
    image
  2. 설명, 번들ID 입력 후 아래로 쭉 내려 Push Notifications 체크 후 Continue, Register 버튼을 차례로 눌러 식별자 생성을 완료해주세요.
    Bundle ID는 /ios/Runner.xcodeproj/project.pbxproj 파일에 있는 PRODUCT_BUNDLE_IDENTIFIER 값입니다(예시: com.example.promleeblog).
    image

1.3. Xcode Capability 추가🔗

VSCode에서 /ios 폴더에 우클릭 후 Open in Xcode 버튼을 눌러 Xcode로 열어줍니다.
Runner > Runner > Signing & Capabilities 탭으로 이동 후 + Capability 버튼 클릭 후 Push Notifications를 검색해 추가해줍니다.
image
추가적으로 Signing & Capabilities 탭에서 Background Modes에 다음과 같이 체크해줍니다.
image

1.4. Firebase Cloud Console 설정🔗

Firebase Console에 접속 후 로그인, 원하는 프로젝트를 선택해준 후
클라우드 메시징
탭까지 아래와 같이 이동합니다.
image
다음 사진과 같이 키를 업로드 해주면 됩니다. 키는 1.1. 에서 생성한 키를 업로드 해주면 됩니다. 키 ID는 해당 키 화면에서, 팀 ID는 Apple Developer 포털 - Account 페이지에서 확인할 수 있습니다.
image
팀 ID 위치
팀 ID 위치
이렇게 IOS환경에서 설정을 마무리 했습니다.

1.5 Podfile 권한 설정🔗

/ios/Podfile 파일에 다음과 같이 권한을 추가해줍니다. 이미 추가되어있는 경우는 PERMISSION_NOTIFICATIONS 항목이 주석 해제되어있는지만 확인해주시면 됩니다.
Podfile 코드
/ios/Podfile
post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      # You can remove unused permissions here
      # for more information: https://github.com/BaseflowIT/flutter-permission-handler/blob/master/permission_handler/ios/Classes/PermissionHandlerEnums.h
      # e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0'
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',
 
        ## dart: PermissionGroup.calendar
        # 'PERMISSION_EVENTS=1',
        
        ## dart: PermissionGroup.calendarFullAccess
        # 'PERMISSION_EVENTS_FULL_ACCESS=1',
 
        ## dart: PermissionGroup.reminders
        # 'PERMISSION_REMINDERS=1',
 
        ## dart: PermissionGroup.contacts
        # 'PERMISSION_CONTACTS=1',
 
        ## dart: PermissionGroup.camera
        # 'PERMISSION_CAMERA=1',
 
        ## dart: PermissionGroup.microphone
        # 'PERMISSION_MICROPHONE=1',
 
        ## dart: PermissionGroup.speech
        # 'PERMISSION_SPEECH_RECOGNIZER=1',
 
        ## dart: PermissionGroup.photos
        # 'PERMISSION_PHOTOS=1',
 
        ## The 'PERMISSION_LOCATION' macro enables the `locationWhenInUse` and `locationAlways` permission. If
        ## the application only requires `locationWhenInUse`, only specify the `PERMISSION_LOCATION_WHENINUSE`
        ## macro.
        ##
        ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
        # 'PERMISSION_LOCATION=1',
        # 'PERMISSION_LOCATION_WHENINUSE=0',
 
        ## dart: PermissionGroup.notification
        'PERMISSION_NOTIFICATIONS=1',
 
        ## dart: PermissionGroup.mediaLibrary
        # 'PERMISSION_MEDIA_LIBRARY=1',
 
        ## dart: PermissionGroup.sensors
        # 'PERMISSION_SENSORS=1',
 
        ## dart: PermissionGroup.bluetooth
        # 'PERMISSION_BLUETOOTH=1',
 
        ## dart: PermissionGroup.appTrackingTransparency
        # 'PERMISSION_APP_TRACKING_TRANSPARENCY=1',
 
        ## dart: PermissionGroup.criticalAlerts
        # 'PERMISSION_CRITICAL_ALERTS=1',
 
        ## dart: PermissionGroup.criticalAlerts
        # 'PERMISSION_ASSISTANT=1',
      ]
 
    end
  end
end

🚀

2. 안드로이드 설정🔗

안드로이드는 권한 설정만 해주시면 됩니다.(Android 13(API 수준 33) 이상)
/android/app/src/main/AndroidManifest.xml
<manifest ...>
	<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
	<application ...>
			...
	</application>
</manifest>

🚀

3. 푸쉬 알림 수신 Flutter 코드 작성하기🔗

3.1. firebase_messaging 패키지 설치하기🔗

flutter pub add firebase_messaging

3.2. 알림 수신 권한 허용🔗

알림 수신 권한 허용을 받을 위치에 다음 코드를 추가합니다.
import 'package:firebase_messaging/firebase_messaging.dart';
 
// 적절한 위치에 선언
FirebaseMessaging messaging = FirebaseMessaging.instance;
NotificationSettings settings = await messaging.requestPermission(
  alert: true,
  announcement: false,
  badge: true,
  carPlay: false,
  criticalAlert: false,
  provisional: false,
  sound: true,
);
print('User granted permission: ${settings.authorizationStatus}');

3.3. 푸쉬 알림 수신 코드 작성 (백그라운드)🔗

가장 상위 파일인 main.dart에 다음 코드를 추가합니다.
백그라운드 메시지 핸들러와 관련하여 유의해야 할 몇 가지 사항이 있습니다. 주의해주세요
  1. 익명 함수가 아니어야 합니다.
  2. 최상위 수준 함수여야 합니다(예: 초기화가 필요한 클래스 메서드가 아님).
  3. Flutter 버전 3.3.0 이상을 사용하는 경우 메시지 핸들러는 함수 선언 바로 위에 @pragma('vm:entry-point')로 주석을 달아야 합니다(그렇지 않으면 출시 모드의 경우 트리 쉐이킹 중에 삭제될 수 있음).
/lib/main.dart
import 'package:firebase_messaging/firebase_messaging.dart';
 
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
}
 
void main() {
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  runApp(MyApp());
}

3.4. 푸쉬 알림 수신 코드 작성 (포그라운드)🔗

가장 상위 파일에 다음과 같은 리스너를 추가합니다.
/lib/main.dart
import 'package:firebase_messaging/firebase_messaging.dart';
 
void main(){
	// ...
	FirebaseMessaging.onMessage.listen((RemoteMessage message) {
		print('Got a message whilst in the foreground!');
		print('Message data: ${message.data}');
 
		if (message.notification != null) {
			print('Message also contained a notification: ${message.notification}');
		}
	});
  runApp(MyApp());
}

🚀

4. FCM 토큰 발급받기🔗

4.1. FCM 토큰이란?🔗

FCM 토큰은 플러터 앱에서 FCM 서버와 통신하기 위해 사용되는 고유 식별자입니다. 플러터 앱에서 FCM 토큰을 발급받으면 푸쉬 알림을 수신할 수 있습니다.

4.2. FCM 토큰 발급받기🔗

import 'package:firebase_messaging/firebase_messaging.dart';
 
// 적절한 위치에 선언
final req = await FirebaseMessaging.instance.requestPermission(
	alert: true,
	badge: true,
	sound: true,
);
final fcmToken = await FirebaseMessaging.instance.getToken();
if (req.authorizationStatus == AuthorizationStatus.authorized && fcmToken != null) {
	print('FCM Token: $fcmToken');
} else {
	print('FCM Token: null');
}

🚀

5. 테스트 메시지 보내기🔗

먼저 기기에 앱이 설치되어 있어야 합니다.
Firebase Console - Cloud Messaging에 접속 후 로그인 후 원하는 프로젝트를 선택합니다.
첫번째 캠페인 생성 버튼을 누른 후 Firebase 알림 메시지를 선택 후 만들기 버튼을 눌러 진행합니다.
image
알림 작성 버튼이 나타나면 알림 제목, 텍스트 입력 후 테스트 메시지 전송 버튼을 눌러 위에서 발급한 FCM 토큰에 푸쉬 알림을 보낼 수 있습니다.
image

🚀

문제 발생 및 해결🔗

IOS fcm 토큰 발급받기 실패🔗

apns token has not been set yet. please ensure the apns token is available by calling getapnstoken()
기본적인 설정을 모두 제대로 했는데도 해당 에러가 발생한다면 flutter에서 APNS 토큰을 자동으로 발급받지 못하는 버그가 발생한 것입니다. 그렇기에 수동으로 APNS 토큰을 발급받아야 합니다.
/lib/main.dart
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
 
void main() async {
	WidgetsFlutterBinding.ensureInitialized();
	FirebaseMessaging messaging = FirebaseMessaging.instance;
	await messaging.requestPermission(
		alert: true,
		announcement: false,
		badge: true,
		carPlay: false,
		criticalAlert: false,
		provisional: false,
		sound: true,
	);
	firebase.getAPNSToken() // 이 코드 추가
	await messaging.getToken();
	runApp(MyApp());
}
IOS 실 기기에 앱을 설치하고 실행하면 위와 같은 에러가 발생할 수 있습니다. 이는 IOS에서 FCM 토큰을 발급받기 위해 APNs 토큰이 필요하기 때문입니다. 이 문제를 해결하기 위해서는 앱을 실행하고 APNs 토큰을 발급받은 후 FCM 토큰을 발급받아야 합니다. 이를 해결하기 위해 다음과 같이 코드를 수정해줍니다.

🚀

결론🔗

파이어베이스의 클라우드 메시징을 사용하면 푸쉬 알림을 쉽게 보낼 수 있습니다. 하지만 푸쉬 알림 클릭 시 특정 페이지로 이동하거나 특정 행동을 실행하는 기능은 구현하기 어렵습니다. 이 기능을 구현하기 위해서는 추가적인 작업이 필요합니다. 이 부분은 다음 포스팅에서 다루도록 하겠습니다.

더 생각해 보기🔗

참고🔗