채팅 푸시 알림이 온 상태에서 앱을 실행하면 사용자가 알림을 누르지 않았음에도 메세지의 채팅방으로 이동되는 현상이 발생했습니다. 코드를 살펴본 결과 메세지가 왔을 때 채팅방으로 이동시키고 있어 사용자의 푸시 알림 클릭 여부를 확인해 알림을 눌러 앱을 실행했을 때에만 채팅방으로 이동시키도록 수정하면 될 것으로 예상했지만 확인 결과 두 가지 문제가 있었습니다.
PushNotificationIOS.addEventListener를 통해 수신되는 notification이 null로 반환되는 현상푸시 알림을 눌러 앱에 진입한 경우, 사용자를 바로 채팅방으로 이동시키거나 읽지 않은 알림 카운트를 초기화하는 등 적절한 액션을 수행할 수 있습니다. 이를 위해 푸시 알림이 전달된 상황을 확인하는 로직이 필요합니다.
이때 앱 상태에 따라 푸시 알림 확인 방법이 달라집니다.
현재, Background에서 Foreground로 전환되었을 때 푸시 알림을 처리하는 로직은 App.tsx에, Quit 상태에서 Foreground로 전환되었을 때의 로직은 앱 부팅 관련 로직 쪽에서 관리하고 있었습니다.
// App.tsx
// Background -> Foreground일 때 처리
useEffect(() => {
PushNotificationIOS.addEventListener('notification', async (notification) => {
const notificationData = notification?.getData();
if (!notificationData) return;
if (notificationData?.sendbird) {
... // 채팅방 이동 로직
}
notification.finish(PushNotificationIOS.FetchResult.NoData);
});
return () => {
PushNotificationIOS.removeEventListener('notification');
};
}, []);
// Quit -> Foreground일 때
// App Boot 관련 로직
const notificationData = await PushNotificationIOS.getInitialNotification();
if(notificationData) {
// 채팅방 이동 로직
}
PushNotificationIOS의 공식문서에서는 사용자가 푸시 알림을 눌러서 들어왔는지 감지할 수 있는 방법을 안내하고 있습니다.
notification.getData().userInteraction 값이 1이면 사용자가 푸시 알림을 눌러 앱을 실행했음을 의미합니다.getInitialNotification() 함수를 사용할 경우: 푸시 알림을 통해 앱이 실행되었을 때만 PushNotificationIOS 타입의 객체를 반환하며, 그 외의 경우에는 null을 반환합니다. 즉, 반환값이 null이 아니라면 사용자가 푸시 알림을 눌러 앱을 실행한 것입니다.하지만 시뮬레이터에서 실행한 결과,
notification 이벤트는 발생하지만, notification.getData()의 반환값이 null이어서 userInteraction 속성을 확인할 수 없었습니다.getInitialNotification() 함수는 null을 반환해야 하는 상황에서도 null이 아닌 값을 반환하고 있었습니다.원인을 분석하던 중, 사일런트 푸시(Silent Push) 관련 설정이 영향을 미치고 있다는 가설을 세웠습니다.
❗사일런트 푸시란?
사일런트 푸시는 사용자 인터페이스에 알림을 표시하지 않고 백그라운드에서 데이터를 갱신하는 푸시 알림입니다. 즉, 앱이 백그라운드 또는 종료된 상태에서도 백그라운드에서 데이터를 미리 가져올 수 있도록 도와줍니다.
현재 채팅 관련 푸시 알림은 사일런트 푸시를 사용하고 있었기에 문제에 대한 시나리오를 다음과 같이 추측했습니다.

사일런트 푸시 관련 설정을 비활성화한 후 테스트하니 위 사진과 같은 결과를 얻을 수 있었습니다.
백그라운드에서 메세지를 처리하는 과정이 빠지자 Quit 상태일 때 푸시 알림을 누르지 않고 앱에 진입하면 정상적으로 PushNotificationIOS.getInitialNotification()이 null을 반환해 채팅방으로 이동하지 않고 앱이 켜지게 되었습니다.
다만 아직도 앱이 백그라운드 상태에서 푸시알림이 온 경우에는 푸시 알림을 눌러 앱을 진입했을 때 채팅방으로 가지 않고 앱이 단순히 켜지기만 하는 문제가 남아있었습니다.
// App.tsx
// Background -> Foreground일 때 처리
useEffect(() => {
PushNotificationIOS.addEventListener(**'notification'**, async (notification) => {
const notificationData = notification?.getData();
if (!notificationData) return;
const isClicked = notificationData.userInteraction === 1
if (notificationData?.sendbird && isClicked) {
... // 채팅방 이동 로직
}
notification.finish(PushNotificationIOS.FetchResult.NoData);
});
return () => {
PushNotificationIOS.removeEventListener('notification');
};
}, []);
기존 코드를 다시 살펴보니 addEventListener에 notification 이벤트가 연결되어 있었습니다.
Sendbird의 공식 문서에서 메세지를 수신했을 때 FCM의 BackgroundMessageHandler에서 Notifee를 이용해 수신한 메세지 내용을 로컬 알림으로 보여주고 있었고 푸시 알림 클릭을 다루기 위해 localNotification 이벤트에 이벤트 핸들러를 연결한다는 내용을 확인할 수 있었습니다.
따라서 기존 notification 이벤트를 localNotification 이벤트로 수정하니 백그라운드 상태에서도 채팅 푸시 알림을 눌렀을 때 정상적으로 채팅방으로 이동되는 것을 확인할 수 있었습니다.