Backend/⛺Firebase

[Firebase] FCM을 도입할 때 고려할 것들

seungwookim 2021. 11. 22. 08:13

최근 진행하는 프로젝트에 FCM을 앱 푸시 알림 서비스로 사용하게 되었다.

도입할 때 서버 개발자로서 고려할 것들을 정리하였다.

Firebase Cloud Messaging (FCM)

Firebase 클라우드 메시징(FCM)은 무료로 메시지를 안정적으로 전송할 수 있는 교차 플랫폼 메시징 솔루션이다.

 

푸시 알림 흐름

(사진 출처: dev.to)

 

흐름을 요약하자면 아래와 같다.

  1. FCM에 앱을 등록하고, 앱도 FCM과 연동한다.
  2. 앱 프론트는 필요할 때 FCM 토큰을 발급받고 백엔드로 보낸다.
  3. 백엔드는 토큰을 유저 정보와 연동하여 DB에 보관하다가, 필요할 때 조회해서 Notification Provider에 푸시 알림을 요청한다.
  • 여기서 FCM 토큰이란?
    • 푸시 알림을 보낼 디바이스들을 식별하기 위해 존재한다.
  • 각각의 디바이스에 어떻게 개별적으로 푸시 알림을 보낼까?
    • FCM 토큰으로 디바이스를 구분한다. 디바이스마다 별도의 FCM 토큰이 존재한다. 따라서 DB의 유저 테이블에 FCM 토큰 필드를 추가하고, 푸시 알람을 줄 때 유저의 토큰 필드를 조회하여 보내는 식이다.
  • 꼭 FCM 토큰을 DB에 저장해야할까?
    • 구현 방식에 따라 다르다. 아무래도 DB는 Client로부터 거리가 멀다. 성능이 크리티컬한 요소라면 In-memory 저장소를 고려해볼 수 있겠다.

 

FCM 토큰 생성 및 삭제

토큰의 생성

앱을 처음 실행할 때 FCM SDK는 클라이언트 앱 인스턴스에 대한 등록 토큰을 생성한다.

토큰의 만료(Expire)

FCM 토큰은 정해진 수명이나 갱신 주기가 없다.

따라서, 시간과 관계없이 아래 이벤트가 발생하지 않는다면 만료되지 않는다.

  • 앱이 인스턴스 ID를 삭제한 경우
  • 앱이 새 기기에서 복원되었을 경우
  • 사용자가 앱을 제거 / 재설치한 경우
  • 사용자가 앱 데이터를 지운 경우

토큰의 갱신(Refresh)

onTokenRefresh() 메서드는 토큰이 갱신될 때마다 호출된다.

갱신될 때마다 동작해야 하는 로직이 있다면, 해당 메서드를 오버라이딩하여 구현한다.

 

토큰 관리

  • 서버에 등록 토큰을 저장한다.
    • 서버의 주요 역할은 각 클라이언트의 토큰을 추적하고 활성 토큰의 업데이트된 목록을 유지하는 것이다.
    • 따라서, 토큰 타임스탬프를 구현하고 이 타임스탬프를 정기적으로 업데이트할 필요가 있다.
  • 토큰의 Refreshness(신선도) 보장을 위해 오래된 등록 토큰을 제거한다.
  • 토큰을 언제 서버에 보낼까?
    • 로그인 시점에 보낸다.
    • 또는 앱을 실행할 때마다 보낸다.
  • 토큰은 언제 삭제할까?
    • Provider가 Notification Server로 푸시 요청을 했을 때, 토큰이 만료되어 에러 메시지가 오는 경우, 핸들링하여 그 토큰을 삭제한다.
  • 보통 서버에서 토큰을 관리
    • DB의 유저 테이블에 FCM 토큰 필드를 추가
    • 로그인 시 서버에 유저 토큰을 저장
    • 푸시 알림을 보낼 때 이를 조회하여 Notification Server에 요청한다.

 

고려해야 할 부분

  • 같은 기기에서 다른 아이디를 쓰는 경우
    • 로그아웃 시점에 서버에서 유저 토큰을 삭제한다.
  • 같은 아이디로 여러 기기를 쓰는 경우
    • 하나의 유저가 여러 토큰을 보유할 수 있게 스키마를 구성한다.
  • 토큰이 갱신되어 서버와 동기화가 필요할 경우
    • 프론트에서 onTokenRefresh() 메서드를 오버라이딩하여 로그인된 유저의 토큰이 갱신될 경우 서버로 토큰을 업데이트하는 api를 전송한다.
  • 오래된 등록 토큰이 있는 비활성 장치에 메시지를 전송하여 리소스를 낭비하는 경우
    • 서비스의 규모가 커진다면 발생할 수 있는 문제, 아래에서 자세히 다룬다.

 

핵심은 토큰의 신선도 보장

서버 개발자 입장에서 핵심은 토큰의 신선도 보장이라는 생각이 들었다.

https://firebase.google.com/docs/cloud-messaging/manage-tokens?hl=ko

 

FCM 등록 토큰 관리 모범 사례  |  Firebase Documentation

Catch up on everthing we announced at this year's Firebase Summit. Learn more 이 페이지는 Cloud Translation API를 통해 번역되었습니다. Switch to English 의견 보내기 FCM 등록 토큰 관리 모범 사례 FCM API를 사용하여 프로

firebase.google.com

위 firebase 공식 문서에서도 언급되어있지만, 데이터베이스에 토큰이 쌓이다 보면 주기적 알림 서비스의 경우에 발생할 수 있는 이슈가 존재한다. 오래된 등록 토큰이 있는 비활성 장치에 메시지를 전송하여 리소스를 낭비하는 경우 푸시 알림의 전송 속도가 느려질 수 있다는 점이다.

 

따라서 정기적으로 토큰의 타임스탬프를 업데이트하는 서버 로직을 추가하고, 오래된 토큰을 판정하기 위한 임계 기간(ex. 2개월 이상) 동안 앱을 사용하지 않은 유저의 토큰은 삭제하며 서버의 모든 등록 토큰을 주기적으로 검색하고 업데이트하는 것이 좋다.

 

프론트엔드에서 해야 할 것

  1. FCM에 앱 등록
  2. 앱에 FCM 연동
  3. 서버에 로그인 요청할 때 FCM 토큰 전송 (등록)
  4. 서버에 로그아웃 요청할 때 FCM 토큰 전송 (삭제)
  5. 앱을 실행할 때 로그인되어 있으면 FCM 토큰을 서버에 전송 (타임스탬프 갱신)
  6. FCM 토큰이 갱신될 때 로그인되어 있으면 FCM 토큰을 서버에 전송

 

백엔드에서 해야할 것

  1. 로그인 시 유저의 FCM 토큰 저장
  2. 로그아웃 시 유저의 FCM 토큰 삭제
  3. 앱 실행 시 유저의 FCM 토큰 타임스탬프 갱신
  4. 토큰의 신선도 관리
  5. Notification Server에 푸시 알림 요청
  6. 요청했는데 토큰이 만료되었다는 에러 메시지를 수신할 경우 해당 유저의 토큰 삭제