플러터(Flutter)와 Firebase Cloud Messaging(FCM)을 연동하여 푸시 알림 기능을 구현하는 것은 이제 많은 앱의 필수적인 요소가 되었습니다. Firebase의 훌륭한 문서와 Flutter의 편리한 firebase_messaging
패키지 덕분에 기본적인 알림 수신까지는 비교적 순조롭게 진행됩니다. 하지만 많은 개발자들이 거의 예외 없이 부딪히는 거대한 장벽이 하나 있습니다. 바로 "분명히 알림은 오는데, 알림을 탭(클릭)해도 아무런 반응이 없는" 현상입니다.
앱이 실행 중일 때(Foreground)는 onMessage
가 잘 호출되지만, 앱이 백그라운드에 있거나 완전히 종료된 상태에서 수신된 알림을 클릭했을 때 약속된 onMessageOpenedApp
이나 getInitialMessage
가 전혀 동작하지 않는 이 문제는 개발자를 깊은 좌절에 빠뜨립니다. 패키지에 버그가 있는 것은 아닌지, 내 Flutter 코드에 문제가 있는 것인지 의심하며 수많은 GitHub 이슈와 Stack Overflow 질문들을 헤매게 됩니다. 하지만 놀랍게도 이 문제의 99%는 Flutter 코드나 패키지 버그가 아닌, FCM 메시지를 보내는 방식, 즉 서버 측 페이로드(Payload) 구성의 문제입니다.
이 글에서는 바로 이 문제의 근본적인 원인을 명확하게 파헤치고, 다시는 이 문제로 시간을 낭비하지 않도록 확실한 해결책과 단계별 구현 가이드, 그리고 효과적인 테스트 방법까지 총정리하여 제시합니다. 이 글을 끝까지 읽으신다면, 더 이상 동작하지 않는 푸시 알림 때문에 스트레스받는 일은 없을 것입니다.
문제의 핵심: Notification 메시지와 Data 메시지의 결정적 차이
이 모든 혼란의 시작은 FCM이 메시지를 처리하는 두 가지 주요 방식, 'Notification 메시지'와 'Data 메시지'의 차이를 이해하는 것에서부터 출발합니다. 많은 개발자들이 이 둘을 명확히 구분하지 않고 사용하기 때문에 문제가 발생합니다.
1. Notification 메시지 (알림 메시지)
Notification 메시지는 가장 간단하고 직관적인 방식입니다. Firebase 콘솔의 'Cloud Messaging' 섹션에서 '알림 보내기'를 통해 손쉽게 생성할 수 있는 메시지가 바로 이것입니다. 이 메시지는 앱의 상태(포그라운드, 백그라운드, 종료)에 따라 동작 방식이 완전히 달라집니다.
- 구조: JSON 페이로드에서
notification
키를 가집니다. 이 안에는title
,body
,image
등 시각적인 요소를 정의하는 필드들이 포함됩니다. - 동작 방식:
- 앱이 포그라운드(Foreground)일 때: 이 메시지는 Flutter 앱의
FirebaseMessaging.onMessage
스트림으로 전달됩니다. 개발자는 이 데이터를 받아 인앱 팝업을 띄우거나 UI를 업데이트하는 등 자유롭게 처리할 수 있습니다. 이때 시스템 알림 트레이에는 아무것도 표시되지 않습니다. - 앱이 백그라운드(Background) 또는 종료(Terminated) 상태일 때: 이 메시지는 Flutter 앱으로 전달되지 않고, 모바일 OS(Android, iOS)의 시스템이 직접 처리합니다. 시스템은
notification
객체의 정보를 바탕으로 표준적인 시스템 알림을 생성하여 상단 바(알림 트레이)에 표시합니다.
- 앱이 포그라운드(Foreground)일 때: 이 메시지는 Flutter 앱의
- 치명적인 함정: 앱이 백그라운드/종료 상태일 때 OS가 알림을 직접 처리하기 때문에, 사용자가 이 알림을 탭해도 기본적으로는 그냥 앱을 실행시키는 동작만 할 뿐, Flutter 코드의
onMessageOpenedApp
이나getInitialMessage
와 같은 특정 핸들러를 깨우지 않습니다. 이것이 바로 우리가 겪는 문제의 근본 원인입니다. 사용자가 알림을 통해 어떤 특정 페이지로 이동하거나 특정 데이터를 처리하게 만들고 싶은 우리의 의도와는 다르게 동작하는 것입니다.
// Notification 메시지 페이로드 예시
{
"to": "FCM_DEVICE_TOKEN",
"notification": {
"title": "새로운 소식!",
"body": "앱을 확인하여 최신 업데이트를 보세요.",
"sound": "default"
}
}
2. Data 메시지 (데이터 메시지)
Data 메시지는 이름 그대로 UI 요소 없이 데이터만 전달하는 데 사용되는 '조용한' 메시지입니다. 이 메시지의 처리 책임은 전적으로 애플리케이션에 있습니다.
- 구조: JSON 페이로드에서
data
키를 가집니다. 이 안에는 개발자가 정의한 임의의 Key-Value 쌍 데이터가 포함됩니다. (예:"screen": "profile"
,"itemId": "12345"
) - 동작 방식:
- 앱이 포그라운드(Foreground)일 때: Notification 메시지와 동일하게
FirebaseMessaging.onMessage
스트림으로 전달됩니다. - 앱이 백그라운드(Background) 또는 종료(Terminated) 상태일 때: 이 메시지는 Flutter 앱의 백그라운드 메시지 핸들러(
FirebaseMessaging.onBackgroundMessage
)로 전달됩니다. OS가 멋대로 처리하는 것이 아니라, 우리 앱의 코드가 깨어나서 이 데이터를 수신합니다.
- 앱이 포그라운드(Foreground)일 때: Notification 메시지와 동일하게
- 중요한 특징: Data 메시지는 그 자체로는 사용자에게 시각적인 알림을 보여주지 않습니다. 따라서 백그라운드/종료 상태에서 사용자에게 알림을 보여주려면,
onBackgroundMessage
핸들러 내에서 수신한 데이터를 바탕으로flutter_local_notifications
와 같은 로컬 알림 패키지를 사용하여 직접 알림을 생성하고 표시해야 합니다. 이는 번거롭지만, 알림의 모든 측면(아이콘, 채널, 액션 등)을 완벽하게 제어할 수 있다는 강력한 장점을 가집니다.
// Data 메시지 페이로드 예시
{
"to": "FCM_DEVICE_TOKEN",
"data": {
"type": "chat",
"senderId": "user_abc",
"message": "안녕하세요! 답장 기다릴게요.",
"screen_to_navigate": "/chat/user_abc"
},
"priority": "high" // 백그라운드에서 즉시 처리되도록 우선순위를 높여주는 것이 좋습니다.
}
3. 하이브리드 메시지 (Notification + Data) - 최고의 해결책
그렇다면 우리는 항상 로컬 알림을 직접 만들어야 하는 번거로움을 감수해야 할까요? 그렇지 않습니다. FCM은 Notification과 Data를 함께 보내는 하이브리드 방식을 지원하며, 이것이 바로 우리가 겪는 문제를 해결하는 가장 우아하고 권장되는 방법입니다.
- 구조: JSON 페이로드에
notification
과data
키를 모두 포함합니다. - 동작 방식:
- 앱이 포그라운드(Foreground)일 때:
onMessage
핸들러로notification
과data
객체가 모두 전달됩니다. - 앱이 백그라운드(Background) 또는 종료(Terminated) 상태일 때:
- OS 시스템이
notification
객체의 내용을 바탕으로 시스템 알림을 자동으로 표시해줍니다. (로컬 알림을 직접 생성할 필요 없음!) - 사용자가 이 알림을 탭하면, OS는 앱을 깨우고
data
객체에 담긴 데이터를 Flutter 앱의 상호작용 핸들러(onMessageOpenedApp
또는getInitialMessage
)로 전달해줍니다.
- OS 시스템이
- 앱이 포그라운드(Foreground)일 때:
- 결론: 이 방식은 Notification 메시지의 편리함(자동 알림 표시)과 Data 메시지의 강력함(탭 했을 때 데이터 전달 및 앱 제어)을 모두 누릴 수 있는 최적의 조합입니다.
// 하이브리드 메시지 페이로드 예시 (강력 추천)
{
"to": "FCM_DEVICE_TOKEN",
"notification": {
"title": "주문이 배송 시작되었습니다!",
"body": "주문 #12345의 배송 현황을 확인해보세요."
},
"data": {
"order_id": "12345",
"screen_to_navigate": "/order_details"
}
}
왜 Firebase 콘솔 테스트 메시지는 앱을 실행시키지 못할까?
이제 원인이 명확해졌습니다. 많은 개발자들이 처음 FCM을 테스트할 때 사용하는 Firebase 콘솔의 '알림 작성' 도구는 기본적으로 Notification 메시지만을 생성하기 때문입니다.

위 이미지의 '알림 제목'과 '알림 텍스트' 필드를 채우면 notification
객체가 만들어집니다. 만약 여기서 '추가 옵션'을 열어 '맞춤 데이터' 또는 '데이터' 섹션에 Key-Value 쌍을 추가하지 않는다면, 전송되는 페이로드에는 data
객체가 포함되지 않습니다. 그 결과, 백그라운드/종료 상태에서 수신된 알림은 OS가 처리하고, 탭 해도 앱은 그저 실행될 뿐, 우리가 원하는 특정 동작을 수행할 수 없었던 것입니다.
해결의 실마리: Firebase 콘솔에서 테스트할 때도, 반드시 '맞춤 데이터'(Key-Value)를 한 쌍 이상 추가하여 하이브리드 메시지 형태로 보내야만 백그라운드 탭 동작을 정상적으로 테스트할 수 있습니다.
해결책 1 (가장 권장): `data` 페이로드를 함께 전송하기
실제 프로덕션 환경에서는 Firebase 콘솔이 아닌 자체 백엔드 서버에서 API를 통해 FCM 메시지를 전송하게 됩니다. 이때, 반드시 notification
과 data
를 모두 포함하는 하이브리드 형태로 페이로드를 구성해야 합니다.
최신 FCM v1 API와 레거시 HTTP API의 페이로드 예시는 다음과 같습니다.
FCM v1 API (HTTP v1) 페이로드 예시
현재 Firebase에서 권장하는 최신 방식입니다. 더 안전하고 기능이 많으므로 새로 구현한다면 반드시 v1 API를 사용해야 합니다.
// POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send
{
"message": {
"token": "FCM_DEVICE_TOKEN",
"notification": {
"title": "새로운 댓글이 달렸습니다",
"body": "'플러터 정말 최고네요' 글에 댓글이 달렸어요."
},
"data": {
"postId": "flutter_is_best_101",
"type": "new_comment",
"deep_link": "myapp://posts/flutter_is_best_101"
},
"android": { // Android 플랫폼별 세부 설정
"notification": {
"channel_id": "new_comment_channel",
"click_action": "FLUTTER_NOTIFICATION_CLICK" // 하위 호환성을 위해 여전히 유용할 수 있음
}
},
"apns": { // iOS 플랫폼별 세부 설정
"payload": {
"aps": {
"category": "NEW_COMMENT_CATEGORY",
"sound": "default"
}
}
}
}
}
위 예시에서 볼 수 있듯이, message
객체 안에 notification
과 data
를 나란히 배치하는 것이 핵심입니다.
레거시 HTTP API 페이로드 예시
아직 v1으로 마이그레이션하지 않은 기존 시스템에서 사용하는 방식입니다.
// POST https://fcm.googleapis.com/fcm/send
{
"to": "FCM_DEVICE_TOKEN",
"priority": "high",
"notification": {
"title": "새로운 댓글이 달렸습니다",
"body": "'플러터 정말 최고네요' 글에 댓글이 달렸어요.",
"sound": "default",
"click_action": "FLUTTER_NOTIFICATION_CLICK" // 레거시에서는 이 부분이 중요!
},
"data": {
"postId": "flutter_is_best_101",
"type": "new_comment",
"deep_link": "myapp://posts/flutter_is_best_101"
}
}
레거시 방식에서는 notification
객체 안에 click_action: "FLUTTER_NOTIFICATION_CLICK"
을 명시해주는 것이 안드로이드에서 탭 동작을 보장하는 데 중요한 역할을 합니다. (자세한 내용은 해결책 2에서 다룹니다)
해결책 2 (레거시 방식 및 보조 수단): `click_action` 사용하기
만약 어떤 이유로든 data
페이로드를 사용할 수 없고, 오직 Notification 메시지만을 보내야 하는 상황이라면 (예: 일부 마케팅 자동화 툴과의 연동), 안드로이드에 한해 차선책이 존재합니다. 바로 click_action
을 이용하는 것입니다.
이 방법은 안드로이드 OS에게 "이 종류의 알림을 탭하면, 기본 앱 실행 동작 대신 특정 인텐트(Intent)를 발생시켜줘!"라고 알려주는 것과 같습니다. firebase_messaging
패키지는 이 특정 인텐트를 감지하여 Flutter 앱의 핸들러를 깨우도록 미리 설정되어 있습니다.
1단계: AndroidManifest.xml 파일 수정
android/app/src/main/AndroidManifest.xml
파일을 열고, MainActivity
를 선언하는 <activity>
태그 내부에 새로운 <intent-filter>
를 추가합니다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.my_app">
<application ...>
<activity
android:name=".MainActivity"
...>
<!-- 일반적인 앱 실행을 위한 인텐트 필터 -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- FCM 알림 클릭을 처리하기 위한 인텐트 필터 (이 부분을 추가!) -->
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
...
</application>
</manifest>
이 코드는 FLUTTER_NOTIFICATION_CLICK
이라는 액션을 가진 인텐트가 발생했을 때, 우리의 MainActivity
를 실행하도록 안드로이드 시스템에 등록하는 역할을 합니다.
2단계: FCM 페이로드에 `click_action` 추가
이제 서버에서 Notification 메시지를 보낼 때, notification
객체 내부에 click_action
키와 값으로 "FLUTTER_NOTIFICATION_CLICK"
을 포함시켜야 합니다.
// 레거시 HTTP API에서 click_action 사용 예시
{
"to": "FCM_DEVICE_TOKEN",
"notification": {
"title": "이벤트 알림",
"body": "특별 할인 이벤트가 시작되었습니다! 탭하여 확인하세요.",
"click_action": "FLUTTER_NOTIFICATION_CLICK" // 바로 이 부분!
}
// data 객체가 없어도 동작함
}
이렇게 하면, 백그라운드/종료 상태에서 이 알림을 탭했을 때 안드로이드 시스템은 FLUTTER_NOTIFICATION_CLICK
인텐트를 발생시키고, AndroidManifest.xml
설정에 따라 앱이 실행되면서 firebase_messaging
패키지가 이 이벤트를 감지하여 onMessageOpenedApp
또는 getInitialMessage
로 알림 정보를 전달해줍니다.
주의사항: 이 방법은 data
페이로드가 없기 때문에 알림을 탭했을 때 추가적인 데이터를 전달할 수 없다는 명백한 한계가 있습니다. 또한 주로 안드로이드에서 사용되는 방식이며, iOS에서는 다른 메커니즘으로 동작하므로 범용적인 해결책은 아닙니다. 따라서 가급적이면 해결책 1인 하이브리드 메시지 방식을 사용하는 것을 강력히 권장합니다.
Flutter 앱 완벽 구현: 단계별 코드 가이드
이제 원인과 해결책을 모두 알았으니, Flutter 앱에서 FCM 메시지를 완벽하게 처리하는 전체 코드를 단계별로 작성해 보겠습니다.
1. Firebase 설정 및 패키지 추가
먼저, Flutter 프로젝트에 Firebase를 연동하고 필요한 패키지를 추가합니다. (Firebase 공식 문서 참조)
pubspec.yaml
파일에 다음 패키지들을 추가하세요.
dependencies:
flutter:
sdk: flutter
firebase_core: ^2.27.0 # 최신 버전으로 사용
firebase_messaging: ^14.7.19 # 최신 버전으로 사용
flutter_local_notifications: ^17.0.0 # 포그라운드 알림 표시에 유용
2. `main.dart` 초기화 및 백그라운드 핸들러 설정
FCM의 가장 중요한 규칙 중 하나는 백그라운드 메시지 핸들러가 반드시 최상위(top-level) 함수여야 한다는 것입니다. 즉, 어떤 클래스의 메서드여서는 안 됩니다. main
함수 바깥에 핸들러를 정의해야 합니다.
main.dart
파일의 상단에 다음 코드를 추가합니다.
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
// ✨ 백그라운드 메시지 핸들러는 반드시 최상위 함수여야 합니다.
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// 백그라운드에서 메시지를 처리해야 할 경우, 여기서 Firebase를 초기화해야 할 수도 있습니다.
await Firebase.initializeApp();
print("백그라운드에서 메시지를 처리 중입니다: ${message.messageId}");
print("백그라운드 메시지 데이터: ${message.data}");
// 여기서 로컬 알림을 띄우거나, 데이터를 로컬 DB에 저장하는 등의 작업을 할 수 있습니다.
}
그리고 main
함수를 수정하여 Firebase를 초기화하고 백그라운드 핸들러를 등록합니다.
Future<void> main() async {
// Flutter 엔진과 위젯 트리의 바인딩을 보장합니다.
WidgetsFlutterBinding.ensureInitialized();
// Firebase 앱을 초기화합니다.
await Firebase.initializeApp();
// 백그라운드 메시지 핸들러를 설정합니다.
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(const MyApp());
}
3. 알림 권한 요청 및 메시지 스트림 리스닝
앱이 시작될 때 사용자에게 알림 권한을 요청하고, 다양한 상태(포그라운드, 백그라운드 탭, 종료 상태 탭)의 메시지를 처리하는 로직을 작성합니다. 보통 StatefulWidget
의 initState
에서 이 설정 함수를 호출합니다.
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _messageData = "메시지 데이터가 여기에 표시됩니다.";
@override
void initState() {
super.initState();
_setupInteractedMessage();
}
Future<void> _setupInteractedMessage() async {
// 1. 알림 권한 요청
FirebaseMessaging messaging = FirebaseMessaging.instance;
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
print('사용자에게 부여된 권한: ${settings.authorizationStatus}');
// 2. 포그라운드 메시지 처리
// 앱이 실행 중일 때 메시지를 수신하면 호출됩니다.
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('포그라운드에서 메시지를 받았습니다!');
print('메시지 데이터: ${message.data}');
if (message.notification != null) {
print('메시지는 알림을 포함하고 있습니다: ${message.notification}');
// 여기서 flutter_local_notifications 등을 사용하여 인앱 알림 UI를 보여줄 수 있습니다.
setState(() {
_messageData = "포그라운드 수신: ${message.notification?.title ?? ''}";
});
}
});
// 3. 백그라운드 상태에서 알림을 탭했을 때 처리
// 앱이 백그라운드에 있지만 종료되지는 않은 상태에서 사용자가 알림을 탭하면 호출됩니다.
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('백그라운드에서 알림이 탭되었습니다.');
print('메시지 데이터: ${message.data}');
_handleMessage(message);
});
// 4. 앱이 종료된 상태에서 알림을 탭했을 때 처리
// 앱이 완전히 종료된 상태에서 사용자가 알림을 탭하면, 이 메서드가 Future<RemoteMessage?>를 반환합니다.
RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) {
print('종료 상태에서 알림이 탭되었습니다.');
print('메시지 데이터: ${initialMessage.data}');
_handleMessage(initialMessage);
}
}
// 메시지 데이터를 기반으로 특정 페이지로 이동하는 등의 로직 처리
void _handleMessage(RemoteMessage message) {
setState(() {
_messageData = "알림 탭! 데이터: ${message.data.toString()}";
});
if (message.data['screen_to_navigate'] == '/order_details') {
final orderId = message.data['order_id'];
// Navigator.push(context, MaterialPageRoute(builder: (context) => OrderDetailsScreen(orderId: orderId)));
print("주문 상세 페이지로 이동합니다. 주문 ID: $orderId");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('FCM 완벽 가이드')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('수신된 메시지 정보:', style: TextStyle(fontSize: 18)),
const SizedBox(height: 10),
Text(_messageData),
],
),
),
),
);
}
}
테스트 및 디버깅 전략
이제 코드는 완성되었습니다. 가장 중요한 것은 올바른 페이로드로 테스트하는 것입니다. 앞서 설명했듯이, Firebase 콘솔만으로는 한계가 명확합니다. 따라서 API 클라이언트 도구를 사용하여 직접 페이로드를 구성하고 전송하는 방법을 익혀야 합니다.
cURL을 이용한 직접 테스트
터미널에서 cURL 명령어를 사용하면 가장 빠르고 확실하게 테스트할 수 있습니다.
1. FCM v1 API 테스트용 cURL 명령어
v1 API는 OAuth 2.0 토큰 인증이 필요하여 약간 더 복잡하지만 훨씬 안전합니다.
- Google Cloud SDK 설치 후
gcloud auth application-default print-access-token
명령으로 액세스 토큰을 발급받습니다. - Firebase 프로젝트 ID와 테스트할 기기의 FCM 토큰을 준비합니다.
curl -X POST \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
"https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send" \
-d '{
"message": {
"token": "YOUR_DEVICE_FCM_TOKEN",
"notification": {
"title": "cURL 테스트 (v1)",
"body": "이 알림을 탭하면 데이터가 전달되어야 합니다."
},
"data": {
"test_id": "curl-v1-1234",
"screen_to_navigate": "/order_details",
"order_id": "98765"
}
}
}'
2. 레거시 HTTP API 테스트용 cURL 명령어
Firebase 콘솔의 `프로젝트 설정 > 클라우드 메시징` 탭에서 '서버 키'를 복사하여 사용합니다.
curl -X POST \
-H "Authorization: key=YOUR_LEGACY_SERVER_KEY" \
-H "Content-Type: application/json" \
"https://fcm.googleapis.com/fcm/send" \
-d '{
"to": "YOUR_DEVICE_FCM_TOKEN",
"priority": "high",
"notification": {
"title": "cURL 테스트 (Legacy)",
"body": "이 알림을 탭하면 데이터가 전달되어야 합니다.",
"click_action": "FLUTTER_NOTIFICATION_CLICK"
},
"data": {
"test_id": "curl-legacy-5678",
"screen_to_navigate": "/order_details",
"order_id": "98765"
}
}'
이 명령어들을 사용하여 메시지를 보냈을 때, 앱이 백그라운드/종료 상태에서 알림을 탭하면 Flutter 앱의 디버그 콘솔에 "백그라운드에서 알림이 탭되었습니다." 또는 "종료 상태에서 알림이 탭되었습니다."라는 로그와 함께 `data` 객체의 내용이 출력되어야 합니다. 만약 그렇다면, 당신은 성공한 것입니다!
결론: 메시지 페이로드가 모든 것의 열쇠다
플러터에서 FCM 알림 탭이 동작하지 않는 문제는 패키지의 버그나 복잡한 네이티브 코드의 문제일 것이라는 선입견을 갖기 쉽습니다. 하지만 오늘 살펴본 바와 같이, 그 원인은 대부분 서버에서 보내는 메시지 페이로드의 구조에 있었습니다.
이 문제로 고민하고 있다면 다음 세 가지를 기억하세요.
- Notification 메시지와 Data 메시지를 명확히 구분하세요. 전자는 OS가, 후자는 내 앱이 처리합니다.
- 가장 확실한 해결책은 Notification과 Data를 함께 보내는 '하이브리드 메시지'입니다. 이것이 알림의 편리함과 앱 제어의 유연성을 모두 잡는 방법입니다.
- Firebase 콘솔의 기본 알림만으로 테스트하지 마세요. 반드시 '맞춤 데이터'를 추가하거나, cURL, Postman과 같은 API 도구로 정확한 하이브리드 페이로드를 만들어 테스트해야 합니다.
이제 여러분은 FCM 푸시 알림이 클릭되지 않는 문제의 원인과 해결책을 완벽하게 이해했습니다. 이 지식을 바탕으로 사용자에게 풍부한 알림 경험을 제공하고, 알림을 통해 사용자를 앱의 정확한 위치로引导하는 강력한 기능을 자신 있게 구현하시길 바랍니다.
0 개의 댓글:
Post a Comment