이 글은 Firebase Cloud Messaging 공식 문서를 기반으로 합니다.
궁금한 내용, 틀린 내용이 있다면 언제든지 댓글을 달아주세요!
스타카토에 공동 카테고리 기능이 생기면서 드디어 다른 사용자와 소통할 수 있게 되었습니다.
배경 이해를 돕기 위해 서비스 용어를 간단히 설명드리자면,
💡 카테고리는 기록을 모아 볼 수 있는 폴더의 개념입니다.
- 기본 카테고리 : 당사자만 기록 가능 (Private)
- 공동 카테고리 : 친구를 초대해 함께 기록 가능 (Shared)
공동 카테고리는 초기부터 구상한 핵심 기능이자, 많은 사용자들이 요청해주셨던 기능입니다.
그래서인지 배포하고 감회가 남달랐는데요.
막상 사용해보니 숙원을 이룬 것 치고 어딘가 밋밋한 기분이 들었습니다.
마치 닭갈비를 다 먹고 볶음밥을 추가하지 않은 것처럼 말이죠.
이 허전함의 원인은 바로…
실시간 알림의 부재였습니다.
공동 카테고리란 말이 무색하게도, 알림 기능이 없어 다른 사용자의 업데이트를 빠르게 알아챌 수 없었죠.
이대로라면 기껏 개발한 신기능을 아무도 사용하지 않을 것 같아 재빨리 디스커션을 남겼고
알림의 트리거가 다른 사용자의 활동인 만큼, 기기에서 직접 알림을 생성하는 로컬 알림보다는 FCM이 적합하다는 의견을 나눴습니다.
일 벌리기 좋아하는 팀원들 덕분에 빠르게 담당자가 정해져 개발을 시작할 수 있었습니다 !
FCM은 Google에서 💰무료💰로 제공하는 크로스 플랫폼 푸시 알림 서비스로,
서버에서 클라이언트로 실시간 메시지를 전송할 수 있도록 다양한 기능을 지원합니다.
FCM 메시지는 서버
→ Firebase
→ 클라이언트
흐름으로 이동합니다.
Firebase
는 서버와 클라이언트 사이에서 메시지를 라우팅하는 중개자 역할을 하죠.
혹자는 이런 의문을 가질 수도 있습니다.
"그냥 서버에서 클라이언트로 직접 보내면 안되나?" 🤔
그러나 서버가 수많은 클라이언트와 연결을 유지하면서 안정적으로 메시지를 보내는 것은 굉장히 어려운 일입니다.
또한 클라이언트의 한정된 자원과 OS의 백그라운드 제한으로, 앱이 실행 중이 아닐 때에도 실시간 알림을 수신하도록 직접 구현하기는 매우 까다롭습니다.
반면 FCM은 구글의 글로벌 분산 메시징 인프라를 기반으로 수억대의 기기에 안정적으로 메시지를 전송합니다.
또한 클라이언트에서는 각 플랫폼의 시스템 수준 전송 계층을 거치기 때문에 앱이 꺼져 있어도 메시지 수신이 가능합니다.
서버에서 FCM 메시지가 만들어져 클라이언트 기기에 도착하기까지의 과정을 좀 더 자세히 살펴보겠습니다. (이미지 출처 - Firebase 공식 문서)
앞서 설명했듯, 플랫폼마다 메시지를 수신하고 처리하는 방식은 제각각입니다.
이를 고려해 Firebase는 메시지를 클라이언트 디바이스에 직접 전달하지 않고, 각 플랫폼의 전송 계층을 거쳐 전달합니다.
이러한 구조 덕분에 다양한 플랫폼을 아우르며 메시지를 전송할 수 있는 것이죠.
Firebase
→ APNs
→ iOS 기기
→ 앱
Google Mobile Services(이하 GMS)에 포함된 구글 플레이 서비스는 안드로이드에서 FCM 메시지를 수신하기 위해 사용하는 핵심 계층입니다.
FCM 서버에서 GMS가 탑재된 디바이스에 메시지를 전송하면, 구글 플레이 서비스에 내장된 FCM 클라이언트가 메시지를 수신합니다.
이렇게 수신된 메시지는 앱의 상태(포그라운드, 백그라운드)에 따라 다르게 처리됩니다.
더 자세한 처리 과정은 아래 FCM 메시지 처리 방식에서 다루겠습니다.
+) 흥미로운 사실 😲
중국에서는 구글 규제 정책으로 대부분의 안드로이드 기기에 GMS가 탑재되지 않습니다.
그래서 GMS에 포함된 구글 플레이 서비스를 사용할 수 없고, 당연히 FCM도 지원하지 않습니다.
대신 제조사가 개발한 자체 푸시 시스템을 사용한다고 합니다.
(샤오미 - Mi Push, 화웨이 - Huawei Push Kit)
따라서 중국 제조사의 안드로이드 기기를 위한 푸시 알림은 별도로 고려해야 합니다.
서버가 FCM 메시지를 전송하려면 클라이언트의 FCM 등록 토큰을 알고 있어야 합니다.
이 토큰은 디바이스를 식별하고 메시지를 라우팅하기 위해 사용하는 고유한 문자열 입니다.
FCM 토큰은 특정 조건에서 새롭게 생성되므로, 이때마다 서버에 알려 항상 최신 토큰을 유지하는 것이 중요합니다.
FCM 토큰 갱신 시점
FirebaseMessaging.deleteToken()
호출로 명시적으로 토큰이 삭제되었을 때FID는 앱 인스턴스를 구별하기 위해 Firebase SDK가 생성하는 ID로, FCM을 포함한 Firebase의 여러 기능에서 공통 식별자로 사용됩니다.
따라서 FID가 바뀌면 이에 종속된 FCM 토큰도 함께 갱신됩니다.
FID 갱신 시점
FirebaseInstallations.delete()
가 호출되었을 때파이어베이스 공식 문서를 참고하여, 서버 및 iOS와 함께 수립한 스타카토의 토큰 관리 전략은 아래와 같습니다.
플랫폼 타입(Android/iOS)
과 디바이스 ID(FID)
를 함께 전송한다.FCM 메시지에는 알림(notification)
필드와 데이터(data)
필드가 있습니다.
각 필드의 존재 여부에 따라 알림
, 데이터
, 알림+데이터
총 세 개의 유형으로 구분됩니다.
알림 메시지는 Firebase에서 정의한 키를 활용해 구성할 수 있습니다.
{
"to": "<FCM token>",
"notification": {
"title": "스타카토가 추가됐어요",
"body": "OOO님이 OOO에 남긴 스타카토를 확인해 보세요"
}
}
데이터 메시지는 사용자가 정의한 커스텀 키-값 쌍으로 구성됩니다.
{
"to": "<FCM token>",
"data": {
"title": "스타카토가 추가됐어요",
"body": "OOO님이 OOO에 남긴 스타카토를 확인해 보세요",
"type": "STACCATO_CREATED",
"staccatoId": "123",
}
}
알림 필드와 데이터 필드가 모두 존재하는 메시지 유형입니다.
{
"to": "<FCM token>",
"notification": {
"title": "스타카토가 추가됐어요",
"body": "OOO님이 OOO에 남긴 스타카토를 확인해 보세요"
},
"data": {
"type": "STACCATO_CREATED",
"staccatoId": "123",
}
}
아래에서 자세히 다루겠지만, FCM 메시지 유형은 메시지 처리 방식을 결정하는 핵심 요인입니다.
따라서 본격적으로 기능을 개발하기에 앞서, 알림 기능의 목적과 플랫폼을 고려해 우리 서비스에는 어떤 유형이 적절한지 서버–클라이언트가 사전에 협의할 것을 추천드립니다.
(스타카토는 Android, iOS를 지원하고 화면 이동을 구현하기 위해 알림+데이터
를 사용하고 있습니다.)
FCM 메시지 처리 방식은 크게 세 요인에 의해 결정됩니다.
해당 시리즈에서는 첫번째 요인이 '안드로이드 플랫폼'인 경우만 다룰 예정입니다.
Android
, iOS
, Web
포그라운드
, 백그라운드
알림
, 데이터
, 알림+데이터
앞서 FCM 메시지는 앱의 포그라운드/백그라운드 여부에 따라 다르게 처리된다고 설명했습니다.
앱은 사용자 행동에 따라 포그라운드와 백그라운드를 자유롭게 오갈 수 있으므로 일반적으로는 두 상태를 모두 고려해야 합니다.
앱이 포그라운드에 있는 경우
메시지가 앱
으로 전달되며 개발자가 직접 작성한 코드를 통해 메시지를 처리할 수 있습니다.
따라서 더 복잡하고 플랫폼 종속적인 기능(화면 이동, DB 저장 등)을 자유롭게 구현할 수 있습니다.
앱이 백그라운드에 있는 경우
2-1. notification
필드를 포함하지 않는다면
앱이 포그라운드에 있을 때처럼 메시지가 앱으로 전달됩니다.
2-2. notification
필드를 포함한다면
시스템에서 알림 UI
를 표시합니다. 이후 사용자가 알림을 클릭하면 시스템은 Intent로 앱을 깨웁니다.
Notification 필드
Data 필드
Notification + Data 필드
❓ 의문점
그렇다면 백그라운드에서도 알림을 수신하기 위해 항상 Data 필드만 사용해야 하는 걸까?
Notification + Data 조합을 사용 중이라면 백그라운드에서 어떻게 알림을 처리할 수 있을까?
해답은 다음 글에서 공개합니다!
지금까지 FCM을 활용하기 위해 필요한 정보를 알아보았습니다.
위 내용을 바탕으로, 다음 편에서는 본격적으로 안드로이드에서 FCM 알림을 수신하는 방법에 대해 알아보겠습니다.
To Be Continued
이거 개발 블로그 아니고 개그 블로그 아니에요?