현재 모임 당 채팅이 한개 씩 존재하는 데 모임에서 채팅이 이뤄지고 있더라도 알 수 있는 방법이 없었다. 고로 모임에서 채팅을 하고 있다면 모임원들에게 채팅 알람을 보내고자한다.
어떻게 구현하면 좋을지 고민 중 Firebase에서 제공하는 FCM이라는 것이 있다는 것을 알게 되었고 이를 통해 채팅 알람을 구현해보고자한다.
메세지를 안정적으로 무료 전송할 수 있는 크로스 플랫폼 메시징 솔루션
💡 기존에는 iOS, Android, Web 등의 플랫폼에서 Push 메시지를 보내기 위해서는 각 플랫폼 환경(APNS, GCM)별로 개발해야 하는 불편함이 있었다.
하지만 FCM은 교차 플랫폼 메시지 솔루션이기 때문에 FCM을 이용해서 개발을 진행하면, 플랫폼에 종속되지 않고 Push 메시지를 전송할 수 있다.
{
"to": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification": {
"body": "great match!",
"title": "Portugal vs. Denmark",
"icon": "myicon"
}
}
{
"to": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification": {
"body": "great match!",
"title": "Portugal vs. Denmark",
"icon": "myicon"
}
}
메세지 종류 | 알림 가능 여부 | 알림 저장 개수 | 알림 처리 방법 |
---|---|---|---|
알림 메시지 | 가능 | 여러 알림을 저장하나, OS 환경마다 다르다. | 앱이 백그라운드 일 때 |
데이터 메시지 | 가능 | 1개의 알림만 저장 | 앱이 포그라운드 일 때 |
🔍 자세한 내용은 FCM 공식문서 FCM 메시지 정보를 확인하자
종류 | 대상수 | 설명 |
---|---|---|
단일 기기 | 1개 | 하나의 기기(앱 기준) |
기기 그룹 | 20개 | 알림 키에 허용되는 그룹 |
주제 구독 | 1000개 | 등록 토큰에 구독된 기기 |
💡 주제 구독(subscribe)?
STOMP나 Kafka를 사용해봤으면 알겠지만 어떠한 주제를 구독을 해놓으면 해당 주제에 업데이트된 사항이 있다면 해당 주제를 구독한 사람들에게 업데이트 정보를 보내준다.
💡 단, 위의 플로우 대로 메시지를 전송하려면 메시지를 수신할 클라이언트는 자신의 정보를 FCM Backend 서버에 등록해야한다.
FCM Backend 서버와 통신을 위한 어플리케이션 서버를 구축하기 위해선 다음 "3가지" 규칙을 지켜야 한다.
FCM Backend 서버에 FCM에서 지정한 형식의 메시지 요청을 보낼 수 있어야 한다.
지수 백오프를 사용하여 요청을 처리하고 다시 보낼 수 있어야 한다.
💡 지수 백오프: 요청이 실패할 때마다 다음 요청까지의 유효시간 간격을 n배씩 늘리면서 재요청을 지연시키는 알고리즘
-> 임의 지연을 사용하여 연쇄 충돌을 방지하기 위해서 사용한다.
💡 서버 승인 사용자의 인증 정보: 메시지를 보낼 앱 서버가 인증된 서버라는 것을 증명하는 정보
💡 클라이언트의 등록 토큰: 메시지를 보내고자 하는 디바이스의 정보
FCM을 이용해 각 유저들에게 푸시메시지를 전송하기 위해선 TOKEN, TOPIC을 활용해 푸시 메시지를 보낼 수 있다.
💡 즉, Token은 Firebase에서 관리하는 프로젝트별 접속하는 기기의 고유 ID로 볼 수 있다.
Firebase에서 발급된 토큰의 경우 발급 이후의 토큰관리를 하고있지 않기에, 이를 서버에서 따로 관리를 해줘야 함을 알 수 있다.
이때 토큰 또한, 서버에서 구독 이후 따로 관리를 해줘야 함을 알 수 있다.
메시지 발송 시, FCM에서 제공하는 발송 메서드들은 다음과 같다.
특정 기기 1개에 메시지를 보내려면 아래와 같이 기기의 등록 토큰을 전달한다.
// This registration token comes from the client FCM SDKs.
String registrationToken = "YOUR_REGISTRATION_TOKEN";
// See documentation on defining a message payload.
Message message = Message.builder()
.putData("score", "850")
.putData("time", "2:45")
.setToken(registrationToken)
.build();
// Send a message to the device corresponding to the provided
// registration token.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n"
);
MulticastMessage message = MulticastMessage.builder()
.putData("score", "850")
.putData("time", "2:45")
.addAllTokens(registrationTokens)
.build();
BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
// See the BatchResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " messages were sent successfully");
아까 말했던 특정 주제(Topic)을 구독(subscribe) 했을 때 해당 주제(Topic)을 구독한 사람들에게 메시지를 전달하는 방식이다.
// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";
// See documentation on defining a message payload.
Message message = Message.builder()
.putData("score", "850")
.putData("time", "2:45")
.setTopic(topic)
.build();
// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
🔍 더 많은 정보는 FCM 공식문서의 보내기 요청 작성을 확인하자.
이번 포스팅에서는 채팅 알람을 위한 FCM에 대해 정리해보는 시간을 가져보았다.
다음 포스팅에서는 FCM을 통해 알람을 구현해보는 시간을 가져보겠다.