개요
안녕하세요. 이번에는 그동안 프로젝트에서 FCM (Firebase Cloud Messaging)을 통한 알림 기능을 개발하기 위해 공부했던 과정을 기록해보고자 합니다. 고민할 점이 많고, 시행착오도 많았어서 전달드릴 게 많을 것 같다는 생각이 들었습니다.
왜 FCM을 선택하였나?
먼저 기술을 선택할 때에는 가능한 후보가 어떤 것들이 있는지 나열해 본 뒤 그중에서 판단에 따라 선택해야 한다고 생각합니다. 알림 기능을 전송해야 하는 과정에서, 후보 및 FCM을 도입하게 된 이유는 아래와 같았습니다.
폴링 (Polling) / 긴 폴링 (Long Polling) / 스트리밍 (Streaming)
- HTTP는 일반적으로 비연결성 (Connectionless)의 특성을 가지기 때문에, 수신자에게 알림을 보내기 위해서는 연결된 상태여야 합니다. 위 세 가지 방식은 커넥션을 계속 가지게 함으로써 수신자에게 알림을 보낼 수 있습니다.
- 폴링 방식은 클라이언트가 서버에게 주기적으로 요청을 보내면서, 서버에 알림 이벤트가 발생했을 때 그 결과를 가져오는 방식입니다. 간단한 방식이지만 클라이언트가 계속 요청을 보냄에 따라 리소스 비용이 발생할 수 있고 실시간성이 보장되지 않을 수도 있다는 생각이 들었습니다.
- 긴 폴링 방식은 폴링 방식을 보완한 방식으로, 폴링 방식이 요청을 보내는 주기를 늘린 방식입니다. 예시로 폴링 방식은 요청과 동시에 응답을 받는 방식이지만, 긴 폴링 방식은 요청의 유효 시간을 더 늘릴 수 있습니다. 그리고 그 시간 동안 서버에서 이벤트가 발생했다면 가져오게 됩니다. 폴링 방식에 비해 요청을 보내는 주기가 길어 리소스 비용이 상대적으로 낮고, 실시간성 또한 향상됩니다. 그러나 이벤트가 자주 발생하거나 다수의 클라이언트에게 보내야 하는 상황이라면 요청을 끝내고 다시 재요청을 해야 하기에 순간적으로 부담이 발생할 수 있겠다는 생각이 들었습니다.
- 스트리밍 방식은 응답을 받았을 때 커넥션을 종료시키지 않고, 계속 커넥션을 유지한 채로 다음 응답을 받아오는 방식입니다. 서버는 일정 시간 동안 요청을 대기시키고, Chunked 메시지를 이용해서 응답 시 연결을 계속 유지합니다. 사용자 수가 늘어난다면 그만큼 연결을 유지해야 할 수가 많아질 수 있겠다는 생각이 들어 선택하지 않게 되었습니다.
웹 소켓 (Web Socket)
- 웹 소켓 방식은 최초 접속 시에만 HTTP를 이용하고 이후에는 웹 소켓을 이용함으로써 클라이언트와 서버 양방향 소통이 가능하도록 한 방식입니다.
- 기존 HTTP 요청과 다르게 웹소켓 포트에 접속해 있는 모든 클라이언트에게 이벤트 방식으로 응답합니다.
- 위의 HTTP 방식들에 비해 비용이 절약되지만, 한편으로는 알림 기능은 서버가 클라이언트에게 전달하는 단방향이기에 양방향 기능은 알림 기능과는 적합하지 않다고 생각이 들었습니다.
SSE (Server-Sent Events)
- SSE 방식은 서버가 클라이언트에게 정보를 푸시하는 방식입니다. 웹에서는 클라이언트가 서버에 요청을 보내면 서버가 응답을 하는 구조이지만, SSE는 서버에서 초기 연결 후 계속해서 데이터를 클라이언트에게 보낼 수 있게 해 줍니다.
- Spring MVC에서는 SseEmitter, Spring Webflux에서는 Flux로 개발할 수 있습니다.
- 그러나 웹 소켓 방식처럼 지속적으로 연결되어 있어야 한다는 부담이 따릅니다.
FCM (Firebase Cloud Messaging)
- iOS, Android 등 클라이언트 플랫폼에 종속되지 않고 개발할 수 있습니다.
- 다른 블로그 글들에서도 쉽게 찾을 수 있어 레퍼런스 자료가 많습니다.
- 웹 소켓, SSE 방식에 비해서는 실시간성이 떨어집니다.
- 애플리케이션 서버가 아니라 클라우드 메시징 서버가 메시지 전송의 역할을 담당합니다. 이는 수신자가 애플리케이션에 계속 접속하고 있어야 할 부담을 덜어줍니다. 예를 들어 FCM을 이용하면 사용자가 앱을 실행하고 있지 않을 때에도 알림을 받을 수 있습니다.
- 동기/비동기 두 가지 방식으로 전송할 수 있습니다.
플랫폼에 종속되지 않고 개발할 수 있다는 점, 애플리케이션 서버에 대한 커넥션 비용을 절감시킬 수 있다는 점, 앱에 접속하고 있지 않은 상태에서도 알림을 수신할 수 있다는 점 때문에 본 프로젝트에 FCM을 이용하기로 하였습니다.
FCM 원리 (FCM 아키텍처)
FCM을 적용했을 때 알림 아키텍처는 다음과 같이 흘러갑니다.
![](https://blog.kakaocdn.net/dn/bydidx/btsISdH2nNh/IdoJHhSL4eWpKvhkGGDLBk/img.png)
메시지 요청을 작성하거나 구현하는 도구
FCM 서버 프로토콜을 지원하는 신뢰할 수 있는 서버 환경에서 메시지 요청을 구현합니다. 프로젝트의 경우 스프링 서버가 해당됩니다.
FCM 백엔드
메시지 요청을 수락하는 등 여러 기능을 수행하는 FCM 백엔드는 주제를 통해 메시지 팬아웃 (클라이언트 애플리케이션의 수신 대상에 대한 메시지 분배 방식)을 수행하고 메시지 ID와 같은 메시지 메타데이터를 생성합니다.
플랫폼 수준 전송 레이어
클라이언트 기기로 타겟팅 된 메시지를 라우팅 하고, 메시지 전송 처리 및 플랫폼별 구성을 적용합니다.
사용자 기기의 FCM SDK
실제적으로 클라이언트 기기에 알림이 전달됩니다.
결론
워낙 푸시 알림 방식에서 FCM 방식이 유명하게 퍼져 있지만, 정확히 왜 FCM을 선택하게 되었는지를 정리할 수 있었습니다.
다음 글에서는 FCM 토큰 관리 방법 및 실제 스프링 코드를 보여드리겠습니다.