[monthler] firebase 푸시 알림과 fcm 토큰
FCM 아키텍처 개요
- 메시지 요청을 작성하거나 구현하는 도구 : 현재 프로젝트에서 람다로 구현되어있음
- FCM 백엔드 : 메시지 요청을 수락하는 등 여러 기능을 수행하는 FCM 백엔드는 주제를 통해 메시지 팬아웃을 수행하고 메시지 ID와 같은 메시지 메타데이터를 생성
- 플랫폼 수준 전송 레이어: 기기로 타겟팅된 메시지를 라우팅하고, 메시지 전송을 처리하고, 필요한 경우 플랫폼별 구성을 적용
- Google Play 서비스를 사용하는 Android 기기용 Android 전송 레이어(ATL)
- Apple 기기용 Apple 푸시 알림 서비스(APN)
- 웹 앱용 웹 푸시 프로토콜
- 사용자 기기의 FCM SDK: 알림이 표시되거나 앱의 포그라운드/백그라운드 상태 및 관련 애플리케이션 로직에 따라 메시지가 처리됨
Firebase 에서 메시징 보고서
Firebase Console의 보고서 탭에서는 FCM API를 통해 전송된 메시지를 비롯하여 Android나 Apple 플랫폼 FCM SDK에 전송된 메시지에 대해 다음과 같은 데이터를 확인할 수 있습니다.
- 전송 — 메시지 전송을 위해 대기열에 추가되었거나 전송을 위해 APN과 같은 제3자 서비스에 성공적으로 전달되었을 때 확인할 수 있습니다.
- 수신됨(Android 기기에만 제공) — 데이터 메시지가 앱에 수신되었을 때 확인할 수 있습니다. 이 데이터는 수신 Android 기기에 FCM SDK 18.0.1 이상이 설치된 경우에 사용할 수 있습니다.
- 노출(Android 기기의 알림 메시지에만 제공) — 앱이 백그라운드 상태일 때 디스플레이 알림이 기기에 표시되었을 때 확인할 수 있습니다.
- 확인 — 사용자가 알림 메시지를 확인했을 때 데이터를 확인할 수 있습니다. 앱이 백그라운드 상태일 때 수신된 알림만 보고됩니다.
아키텍처 상 서버에서 FCM 서버로 보내면 전송으로 카운트됩니다. 그리고 플랫폼 수준 레이어에서 앱, 웹으로 보내진 건 수신됨, 노출으로 표시되는데 애플은 카운트되지 않는다고 합니다.
FCM 아키텍처에서 백엔드에서 신경써야 할 부분
백엔드에서 담당하고 있는 부분은 아래와 같습니다.
FCM 토큰과 메시지를 FCM 백엔드 서버로 보내기
현재 프로젝트에서는 FCM 토큰을 DB 에 저장하고, 알림 발송 시 서버에서 모든 사용자의 FCM 토큰을 모아서 람다로 보냅니다. 람다는 FCM 토큰과 메시지를 FCM 백엔드로 보냅니다.
이떄 주로 발생하는 에러는 ``UNREGISTERED (HTTP 오류 코드 = 404)` 입니다. 이는 앱 인스턴스가 FCM에서 등록 취소되었으며 일반적으로 사용된 토큰이 더 이상 유효하지 않으며 새 토큰을 사용해야 함을 의미합니다.
이 오류는 등록 토큰 누락 또는 등록되지 않은 토큰으로 인해 발생할 수 있습니다. 등록 누락: 메시지 대상이
token
값인 경우 요청에 등록 토큰이 포함되어 있는지 확인합니다. 등록되지 않음: 다음을 비롯한 여러 상황에서 기존 등록 토큰이 더 이상 유효하지 않게 될 수 있습니다. - 클라이언트 앱이 FCM에서 등록 취소되는 경우 - 클라이언트 앱이 자동으로 등록 취소되는 경우. 사용자가 애플리케이션을 제거한 경우에 발생할 수 있습니다. 예를 들어 iOS에서 APNs 피드백 서비스가 APN 토큰이 잘못되었다고 보고한 경우입니다. - 등록 토큰이 만료된 경우 (예: Google에서 등록 토큰 새로고침을 결정했거나 iOS 기기에서 APN 토큰이 만료된 경우) - 클라이언트 앱이 업데이트되었지만 새 버전이 메시지를 수신하도록 구성되지 않은 경우 위와 같은 경우에는 앱 서버에서 등록 토큰을 삭제하고 더 이상 메시지 전송에 이 등록 토큰을 사용하지 마세요.
토큰이 유효하지 않음을 말하는데 약 20% 비율로 발생합니다. 이 에러는 람다에서 FCM 서버로 보낼 때 FCM 서버에서 오류를 반환한 토큰으로, 전송에 카운트되지 않습니다.
전송에 비해 수신됨, 노출이 낮음
6월 7일 기준으로 전송이 26K, 수신됨, 노출이 6.4K 으로 약 24% 만 수신했습니다. 여러가지 이유가 있겠지만 일단 문제는 아키텍처 상 FCM 서버 이후에 발생한 것입니다. 애초에 람다 -> FCM 서버 사이에 발생한 에러는 전송으로 기록되지 않으니까요.
사용자 기종 카운트 결과 50% 정도가 아이폰이니 13K 는 제외해야 합니다. 애플은 수신됨, 노출로 카운트되지 않기 때문입니다. 안드로이드만 따졌을 때 전송과 수신됨, 노출 비율이 50% 입니다.
그리고 휴대폰이 꺼졌거나, 시스템 설정에서 알림을 꺼놨다면 FCM 토큰은 유효하지만 알림은 표시되지 않습니다.
- 휴대폰이 꺼져 있는 경우: 메시지는 2단계(Firebase Cloud Messaging)에서 3단계(Platform-level message transport)로 전달되지만, 4단계(SDK on device)에서 디바이스가 꺼져 있어 알림이 표시되지 않습니다.
- 시스템 설정에서 알림이 꺼져 있는 경우: 메시지는 2단계(Firebase Cloud Messaging)에서 3단계(Platform-level message transport)로 정상적으로 전달되고, 4단계(SDK on device)에서 디바이스에 도달하지만, 시스템 설정에 의해 알림이 표시되지 않습니다.
토큰을 DB 에 저장
현재 로직은 FCM 토큰을 DB 에 저장하고 있습니다. FCM 토큰은 새로 로그인할 때마다 새로 발급받아서 DB 를 업데이트를 하고 있습니다. 이때 같은 사용자라고 하더라도 여러 기기를 사용하고 있으면 활성화된 FCM 토큰이 여러 개일 수 있습니다.
따라서 사용자에 대한 FCM 토큰 이 아니라 기기에 대한 FCM 토큰 을 구현해야 합니다. 프로젝트에서는 MAC address 로 이를 구현했습니다. 그리고 백엔드 서버에서 람다로 알림 처리를 요청할 때 실패한 FCM 토큰을 응답값으로 받게 됩니다. 실패한 FCM 토큰은 주로 만료된 토큰이니 DB 에서 이를 사제처리 합니다.
댓글남기기