5단계. 리모트 푸시 수신
Android 환경에서 도착한 리모트 푸시 메시지를 앱 클라이언트에서 처리합니다.
본 문서에서는 Hive Axyl FCM 플러그인으로 실행 중 메시지를 수신하고, 사용자가 알림을 탭해 앱이 실행된 경우의 페이로드를 확인하는 과정을 안내합니다.
FCM 푸시 수신 처리 구현 방법은 아래와 같습니다.
- 방법 1. 실행 중 메시지 수신
- 방법 2. 알림 탭 진입 처리
FCM 플러그인은 수신 이벤트와 콜드 스타트 메시지 조회 기능만 제공합니다. 메시지 표시 방식, 데이터 해석, 화면 이동 처리는 앱 클라이언트에서 직접 수행합니다.
Note
- FCM 플러그인은 Android 디바이스 전용입니다. Unity Editor를 포함한 다른 환경에서는 포트가 등록되지 않으므로 OS 분기 또는
HiveCore.TryResolve<T>()로 보호하세요. - 백그라운드에서 도착해 시스템 알림으로 표시되는 메시지는 OS가 직접 처리하므로 앱 코드가 개입하지 않습니다.
방법 1. 실행 중 메시지 수신
앱이 메시지를 받을 수 있는 상태에서 원격 메시지가 도착하면 NotificationReceived 이벤트가 발생합니다. 이벤트는 엔진 메인 스레드로 전달되므로 핸들러에서 바로 UI를 다룰 수 있습니다.
FCM SDK 동작에 따라 이벤트 발생 조건은 아래와 같습니다.
- 포그라운드: 모든 메시지에서 발생합니다.
- 백그라운드: 데이터(data) 메시지에서만 발생합니다. 알림(notification) 메시지는 시스템 알림으로 표시되며 이벤트가 발생하지 않습니다.
호출 예시
using Hive.Axyl.Core;
using Hive.Axyl.Push.Addon.FCM;
IFCMPlugin fcm = HiveCore.Resolve<IFCMPlugin>();
fcm.NotificationReceived += message =>
{
// 포그라운드 수신 - 인앱 배너 표시 등 앱이 결정합니다.
// 데이터 전용 메시지는 message.Notification이 null입니다.
string title = message.Notification?.Title ?? string.Empty;
string body = message.Notification?.Body ?? string.Empty;
if (message.Data.TryGetValue("deepLink", out var deepLink))
{
// 앱이 정의한 데이터 키를 해석해 처리합니다.
}
};
호출 시 고려 사항
NotificationReceived이벤트를 받으려면 FCM 플러그인 인스턴스가 유지되어야 합니다.- 포그라운드에서 알림을 어떻게 표시할지는 앱 클라이언트가 결정합니다.
- 백그라운드 알림(notification) 메시지는 OS가 시스템 알림으로 표시합니다. 사용자가 알림을 탭해 앱이 실행된 경우에는 알림 탭 진입 처리를 사용하세요.
방법 2. 알림 탭 진입 처리
사용자가 알림을 탭해 앱을 실행하거나 다시 띄운 경우, GetColdStartMessageAsync()로 해당 알림의 데이터 페이로드를 조회합니다.
public Task
GetColdStartMessageAsync();
콜드 스타트 메시지 버퍼는 1회용입니다. 일반 실행이거나 이미 한 번 꺼낸 뒤에는 Message가 null인 Success가 반환되며, 이는 실패가 아닙니다. 앱 시작 시점에 한 번 호출해 알림 탭 진입 여부를 확인하세요.
Note
앱이 종료된 상태에서 알림 탭으로 실행된 경우(콜드 런치)는 추가 설정 없이 동작합니다. 앱이 실행 중일 때 알림 탭으로 재진입한 경우(웜 탭)까지 페이로드를 받으려면 호스트 Activity가 onNewIntent를 Hive Axyl로 전달해야 합니다.
호출 파라미터
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
ct | CancellationToken | Optional | 호출을 취소할 때 사용하는 취소 토큰입니다. 생략하면 기본값이 사용됩니다. |
호출 예시
GetColdStartMessageAsync()의 반환 객체 FcmServiceGetColdStartMessageResult는 성공, 실패 상태로 나뉩니다. 메서드 호출 시 예외(Exception)를 발생시키지 않으며, 모든 처리 결과가 반환 객체로 전달됩니다. 따라서 별도의 try/catch 구문을 사용하지 않고 switch 구문으로 응답 상태를 분기해 처리합니다.
using Hive.Axyl.Core;
using Hive.Axyl.Push.Addon.FCM;
FcmServiceGetColdStartMessageResult result = await fcm.GetColdStartMessageAsync();
switch (result)
{
case FcmServiceGetColdStartMessageResult.Success success when success.Data.Message != null:
// 알림 탭으로 진입 - 페이로드를 해석해 특정 화면으로 이동하는 등 처리합니다.
var data = success.Data.Message.Data;
break;
case FcmServiceGetColdStartMessageResult.Success:
// 일반 실행 또는 이미 꺼낸 버퍼 - 처리할 알림이 없습니다.
break;
// 공통 실패 처리 - 자세한 에러 모델은 [에러 처리](PLACEHOLDER_에러처리_링크) 참고
case FcmServiceGetColdStartMessageResult.Failure failure:
HiveError err = failure.Problem;
Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
break;
// 안전망: 알 수 없는 신규 결과
default:
Debug.LogWarning($"처리되지 않은 결과: {result.GetType().Name}");
break;
}
호출 시 고려 사항
- 앱 시작 시점에 한 번 호출해 알림 탭 진입 여부를 확인하세요.
Success가 반환되어도Message가null이면 일반 실행이거나 이미 꺼낸 버퍼입니다.- 페이로드를 기반으로 화면 이동을 수행할 때는 앱 초기화와 로그인 상태 확인이 끝난 뒤 처리하세요.
응답 데이터
성공 시 FcmServiceGetColdStartMessageResult.Success의 Data에 메시지가 담깁니다.
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Data.Message | FcmRemoteMessage | Optional | 사용자가 탭한 알림의 페이로드입니다. 일반 실행이거나 이미 꺼낸 버퍼면 null입니다. |
응답 상태
반환 객체 FcmServiceGetColdStartMessageResult는 아래 케이스로 분기됩니다. switch 구문으로 처리하세요.
| 응답 케이스 | 설명 | 앱 클라이언트 대응 |
|---|---|---|
Success | 조회에 성공했습니다. 알림 탭 진입이면 Message에 페이로드가 담기고, 일반 실행이면 null입니다. | Message 유무로 분기 처리 |
Failure | 네이티브 연동 오류. Problem(HiveError)에 상세가 담깁니다. | 일반 실행으로 간주 또는 오류 기록 |
참고. 수신 메시지 데이터 확인
FCM 메시지는 두 부분으로 구성될 수 있습니다.
- 알림(notification): 제목, 본문 등 OS가 표시하는 내용입니다.
FcmRemoteMessage.Notification으로 전달됩니다. - 데이터(data): 앱이 해석하는 키-값 페이로드입니다.
FcmRemoteMessage.Data딕셔너리로 전달됩니다.
앱은 수신한 Data의 키를 해석해 화면 이동, 상태 갱신 같은 동작을 구현합니다. 데이터는 표시되는 알림(notification)에 동봉해 전달하며, 데이터만 단독으로 담은 메시지(무음 푸시, data-only)의 발송 가능 여부는 푸시 발송(서버) 명세를 따릅니다.
참고: FcmRemoteMessage 구조
수신 메시지는 FCM의 원격 메시지(RemoteMessage)를 그대로 옮긴 구조입니다.
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
MessageId | string | Required | 메시지 식별자입니다. |
SentTime | DateTimeOffset | Required | 발송 시각(UTC)입니다. |
From | string | Required | 발신자입니다. |
CollapseKey | string | Required | 메시지 병합 키입니다. |
Priority | int | Required | 전달 우선순위입니다. 0은 알 수 없음, 1은 높음, 2는 보통입니다. |
Ttl | TimeSpan | Required | 메시지 유효 기간입니다. |
Data | IReadOnlyDictionary<string,string> | Required | 데이터 페이로드입니다. 데이터가 없으면 빈 딕셔너리입니다(null 아님). |
Notification | FcmNotification | Optional | 알림 표시 정보입니다. 데이터 전용 메시지면 null입니다. |
FcmNotification
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Title | string | Required | 알림 제목입니다. 값이 없으면 빈 문자열입니다(null 아님, 이하 string 필드 동일). |
Body | string | Required | 알림 본문입니다. |
ImageUrl | string | Required | 알림 이미지 URL입니다. |
Icon | string | Required | 알림 아이콘입니다. |
Sound | string | Required | 알림 사운드입니다. |
Tag | string | Required | 알림 태그입니다. |
ClickAction | string | Required | 알림 탭 시 실행할 액션입니다. |
ChannelId | string | Required | Android 알림 채널 ID입니다. |
Color | string | Required | 알림 색상입니다. |
Link | string | Required | 알림 링크 URL입니다. |
TitleLocKey | string | Required | 제목 현지화 키입니다. |
BodyLocKey | string | Required | 본문 현지화 키입니다. |
TitleLocArgs | IReadOnlyList<string> | Required | 제목 현지화 인자입니다. 없으면 빈 목록입니다. |
BodyLocArgs | IReadOnlyList<string> | Required | 본문 현지화 인자입니다. 없으면 빈 목록입니다. |
연관 문서
본 문서의 내용과 관련하여 참조하는 문서는 아래와 같습니다.