FCM을 이용한 Push API 구현

dev-jjun·2023년 8월 13일
0

Server

목록 보기
13/33
📓 용어 정리

Notification Server

모바일 기기에 push 알림을 전송하는 서버

Client App

사용자의 모바일 기기에 설치된 app

Provider

Client App을 위한 서버 (= 나의 push server)

→ 필요시 Notification Server에 요청을 전송하여, Client App에 알림을 보내는 역할

FCM 전체 플로우

  1. 모바일 앱이 설치되는 순간 클라이언트 → Firebase 서버: 토큰 요청

  2. 클라이언트 → 서버: 토큰 전달

  3. 서버: userId와 파이어베이스(FB) 토큰을 매핑하여 서버 DB에 저장

    *이 토큰은 Firebase 서버에서 메시지 전송 요청 시 어디로 보낼지(클라이언트)를 식별하는 역할을 한다

이벤트 발생 시

  • 서버는 알림을 전달해줄 클라이언트의 FB 토큰을 DB에서 가져옴
  • 서버에서 해당 FB 토큰과 메시지 데이터를 HTTP 통신을 위해 Firebase 서버에 전달
  • Firebase 서버에서 전달받은 FB토큰으로 클라이언트를 찾아 알림 전달 = ⏰ 푸시알림!
    • 타겟 모바일 앱은 백그라운드 상태에서도 Listener로 이벤트를 감지함

푸시 서버 아키텍처

🧐 추가로 ***고려해야 할 사항***
  • 푸시 발송 시 필요한 유저들의 FB 토큰을 저장할 때, DB는 어떤 것을 사용?
    • Redis
    • MySQL
  • 실시간 통신을 더욱 빠르게 처리해주기 위한 시스템 도입
    • Kafka
  • 자동 푸시 발송 기능
    - Spring Batch

1️⃣ Firebase Admin SDK 설치 - FCMConfig

// Firebase 공식문서

FileInputStream serviceAccount =
new FileInputStream("path/to/serviceAccountKey.json");

FirebaseOptions options = new FirebaseOptions.Builder()
  .setCredentials(GoogleCredentials.fromStream(serviceAccount))
  .build();

FirebaseApp.initializeApp(options);

—> application.yml에 추가하고 @Value로 가져오는 방식으로 구현하였다.

2️⃣ FCM에 메시징 요청

💫 **타겟팅에 따른 구현**

공식 문서

앱 서버 전송 요청 작성  |  Firebase 클라우드 메시징

  • 단일 기기 : send() / sendAll()
    // 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);FirebaseMessagingSnippets.java
  • 다수 기기 : sendMulticast()
    // 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");FirebaseMessagingSnippets.java
  • 주제 구독 : send() / sendAll()
    // 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);FirebaseMessagingSnippets.java

*이밖에 sendAsync(), sendAllAsync() 와 같이 비동기를 처리하기 위한 메서드도 지원한다.

Message에 대한 내용을 담을 Data 객체는 공식문서를 참고한다.

  • JSON 형식
     * - Request
     * {
     *   "validate_only": boolean,
     *   "message": {
     *     object (Message)
     *   }
     * }
     *
     *
     * - Message
     * {
     *   "name": string,
     *   "data": {
     *     string: string,
     *     ...
     *   },
     *   "notification": {   ✅모든 플랫폼에서 사용할 기본 알림 템플릿
     *     object (Notification)
     *   },
     *   "android": {    FCM 연결 서버를 통해 전송된 메시지에 대한 Android 전용 옵션 TODO 이 부분을 서버 측에서 설정해줘야 하는지?
     *     object (AndroidConfig)
     *   },
     *   "webpush": {   Web 푸시 알림을 위한 webpush 프로토콘 옵션
     *     object (WebpushConfig)
     *   },
     *   "apns": {      Apple 푸시 알림 서비스 특정 옵션  TODO 이 부분을 서버 측에서 설정해줘야 하는지?
     *     object (ApnsConfig)
     *   },
     *   "fcm_options": {  모든 플랫폼에서 사용할 FCM SDK 기능 옵션용 템플릿
     *     object (FcmOptions)
     *   },
     *
     *   // Union field target can be only one of the following:
     *   "token": string,    메시지를 보낼 등록 토큰 (특정 클라이언트 대상)
     *   "topic": string,    Topic 발행의 경우, 사용
     *   "condition": string
     *   // End of list of possible types for union field target.
     * }
@Builder
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class FCMMessage {

    private boolean validateOnly;
    private Message message;

    @Builder
    @AllArgsConstructor
    @Getter
    public static class Message {
        private Notification notification;   // 모든 모바일 OS에 통합으로 사용할 수 있는 Notification
        private String token;   // 특정 디바이스(클라이언트)에 알림을 보내기 위한 토큰
    }

    @Builder
    @AllArgsConstructor
    @Getter
    public static class Notification {
        private String title;
        private String body;
        private String image;
    }

}

Apple

APNS와 FCM을 활용하여 푸시알림 구현이 가능하다!

필요한 작업

  • 스프링 서버에서 APNs 서버 구축

참고 자료

profile
서버 개발자를 꿈꾸며 성장하는 쭌입니다 😽

0개의 댓글