프로젝트를 진행하던 도중 특정 Device에 알림을 보내려 한다면 Firebase Cloud Messaging을 사용하게 될 것이다.
여기서 겪었던 몇가지 이슈를 다루어 보려한다.
데이터를 전송할때 단순히 메시지를 담아 보내기만 하면 된다고 생각하지만 환경에 따라 설정해 줘야하는 부분이 서로 다름을 알 수 있었다.
초기에 FCM을 고안할때는 단순히
Notification notification = Notification.builder()
.setTitle(title)
.setBody(body)
.build();
Message message = Message.builder()
.setToken(token)
.setNotification(notification)
.putAllData(data)
.build();
FirebaseMessaging.getInstance().send(message);
이런식으로 Noti와 Message만을 구현하여 처리하면 된다고 생각했지만 해당 코드 처럼 처리한 결과 AND환경에서는 정상 처리 되었지만 IOS의 경우 Notification 값(알림)만 제대로 나오고 Message안의 data는 정상적으로 처리 되지 않는 상황이 있었다.
FCM에서 메시지는 크게 두 가지로 생각하면 좋은데 공통 영역에 해당하는
Notification (title, body)
data (key-value)
부분과 플랫폼별로 설정을 해줘야 하는
AndroidConfig
ApnsConfig (iOS)
WebpushConfig 등
의 구역이 존재한다.
여기서 몰랐던 부분은 안드로이드는 공통 메시지(Notification + data)만으로도 어느 정도 정상 동작하도록 FCM/OS가 기본 처리를 해주지만 IOS는 다르다는 점이었다.
AndroidConfig는 우선순위, TTL, 채널 같은 세부 제어에 가까운 옵션이고, 별도의 설정이 없어도 알림과 data가 앱으로 비교적 정상적으로 전달되는 특성을 가진데에 비해
iOS는 구조적으로 FCM 메시지가 실제로는 APNs(Apple Push Notification Service)를 통해 전달되기 때문에 APNs가 요구하는 헤더(apns-push-type, apns-priority)와 APS 필드(content-available, alert)가 제대로 포함되어 있어야 한다.
이 설정이 빠져 있을 경우 iOS는 알림 배너만 띄우고, 앱으로 data payload를 전달하지 않거나 백그라운드 푸시 콜백을 호출하지 않는 상황이 발생한다는 것이었다.
이 차이 때문에 같은 메시지를 보내더라도 Android에서는 정상적으로 동작하지만 iOS에서는 Notification만 보이고 data가 전달되지 않는 현상이 발생했던 것이다.
추후 변경 코드
if (os.equals("AND"))
{
AndroidConfig androidConfig = AndroidConfig.builder()
.setPriority(AndroidConfig.Priority.HIGH)
.build();
msgBuilder.setAndroidConfig(androidConfig);
}
else if (os.equals("IOS"))
{
ApnsConfig apnsConfig = ApnsConfig.builder()
.putHeader("apns-priority", "10")
.putHeader("apns-push-type", "alert")
.setAps(Aps.builder()
.setContentAvailable(true) //백 그라운드 처리
.setAlert(ApsAlert.builder().setTitle(title).setBody(body).build())
.build())
.build();
msgBuilder.setApnsConfig(apnsConfig);
}