About Firebase Cloud Messaging - YJGwon/connectruck GitHub Wiki

Firebase Cloud Messaging(FCM)

iOS, Android, Web λ“± λ‹€μ–‘ν•œ ν™˜κ²½μ—μ„œ λ©”μ‹œμ§€λ₯Ό 무료둜 전솑할 수 μžˆλŠ” 크둜슀 ν”Œλž«νΌ λ©”μ‹œμ§• μ†”λ£¨μ…˜

처리 흐름

fcm-architecture

  1. server β†’ FCM backend λ©”μ‹œμ§€ λ°œμ†‘ μš”μ²­
  2. FCM backend β†’ λ©”μ‹œμ§€ ID λ“± 메타 데이터 생성, topic 톡해 fan-out μˆ˜ν–‰
  3. ν”Œλž«νΌ 전솑 λ ˆμ΄μ–΄ β†’ client 기기둜 λ©”μ‹œμ§€ λΌμš°νŒ…, ν•„μš”ν•œ 경우 ν”Œλž«νΌ 별 ꡬ성 적용
    • Android용 ATL, iOS용 APN, Web push protocol 등이 포함
  4. client 기기의 FCM SDKκ°€ λ‘œμ§μ— 따라 λ©”μ‹œμ§€ 처리

ν•„μš”ν•œ 것

  1. μ•Œλ¦Ό 전솑할 client κΈ°κΈ° 토큰 (FCM js SDK ν†΅ν•΄μ„œ νšλ“)
  2. μ„œλ²„μ˜ FCM λ°œμ†‘ μš”μ²­ 둜직 (Firebase Admin SDK μ‚¬μš© λ˜λŠ” API μš”μ²­)
  3. client app의 λ©”μ‹œμ§€ 처리 둜직 (FCM js SDK μ‚¬μš©)
    • λ°±κ·ΈλΌμš΄λ“œ 처리 μœ„ν•΄μ„œλŠ” service worker 등둝

FCM λ©”μ‹œμ§€ μ’…λ₯˜

μœ ν˜•

  1. μ•Œλ¦Ό λ©”μ‹œμ§€: FCM SDKμ—μ„œ μžλ™μœΌλ‘œ μ‚¬μš©μžμ—κ²Œ ν‘œμ‹œ
    • push μ•Œλ¦Ό λ°œμƒ 및 λ°±κ·ΈλΌμš΄λ“œ 처리 등을 FCM SDKμ—μ„œ μžλ™μœΌλ‘œ 처리
    • optionalν•˜κ²Œ data payload 포함할 수 있음 - notification κ΄€λ ¨ payloadλŠ” FCM SDKκ°€, data payloadλŠ” client app이 처리
  2. 데이터 λ©”μ‹œμ§€: client appμ—μ„œ 처리

μ•Œλ¦Ό λ©”μ‹œμ§€ ν˜•μ‹

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    }
  }
}
  • token: μ‚¬μš©μž κΈ°κΈ° 토큰
  • notification.title, body: μ‚¬μš©μžμ—κ²Œ ν‘œμ‹œλ˜λŠ” μ•Œλ¦Ό 제λͺ©, λ³Έλ¬Έ
    • ν•΄λ‹Ή ν•„λ“œλ“€μ€ ν”Œλž«νΌμ— 관계 없이 해석될 수 μžˆλŠ” 곡톡 ν•„λ“œ

데이터 λ©”μ‹œμ§€ ν˜•μ‹

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data":{
      "Nick" : "Mario",
      "body" : "great match!",
      "Room" : "PortugalVSDenmark"
    }
  }
}
  • data: client app이 ν•΄μ„ν•΄μ„œ μ²˜λ¦¬ν•  data
    • ν”Œλž«νΌμ— 관계없이 ν•΄μ„λ˜λŠ” 곡톡 ν•„λ“œ
    • custom key-value에 μ˜ˆμ•½μ–΄λŠ” μ‚¬μš©ν•˜μ§€ 말것(from, notification, message_type, google*, gcm*)

데이터 ν•„λ“œ ν¬ν•¨ν•œ μ•Œλ¦Ό λ©”μ‹œμ§€ μ˜ˆμ‹œ

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    },
    "data" : {
      "Nick" : "Mario",
      "Room" : "PortugalVSDenmark"
    }
  }
}

Firebase Admin SDK

λ°±μ—”λ“œμ˜ FCM λ°œμ†‘ μš”μ²­μ„ κ΅¬ν˜„ν•˜λŠ” 방법은 크게 두 κ°€μ§€

  1. SDK μ‚¬μš© - Java, Node.js, Python, C#, Go 지원
  2. API 직접 호좜 - μ„Έ κ°€μ§€ ν”„λ‘œν† μ½œ 지원(μ΅œμ‹  HTTP v1 API, κΈ°μ‘΄ HTTP, κΈ°μ‘΄ XMPP - μ΅œμ‹  ν”„λ‘œν† μ½œ ꢌμž₯)

SDKλŠ” μ΅œμ‹  HTTP v1 API ν”„λ‘œν† μ½œ 기반 β†’ μ§€μ›λ˜λŠ” 언어일 경우 SDK μ‚¬μš©ν•˜λ©΄ 편리

μ„œλ²„μ— SDK μΆ”κ°€

  1. gradle μ˜μ‘΄μ„± μΆ”κ°€
  2. Firebase ν”„λ‘œμ νŠΈ 생성 및 ν‚€ 파일 생성
    • Firebase Consoleμ—μ„œ 생성 κ°€λŠ₯, json 파일
  3. ν‚€ 파일의 인증 정보 μ΄μš©ν•΄μ„œ FirebaseApp μ΄ˆκΈ°ν™”

Gradle μ˜μ‘΄μ„± μΆ”κ°€

build.gradle

dependencies {
  implementation 'com.google.firebase:firebase-admin:9.2.0'
}

build.gradle.kts

dependencies {
    implementation("com.google.firebase:firebase-admin:9.2.0")
}

json ν‚€ 파일둜 Firebase App μ΄ˆκΈ°ν™”

Spring의 ClassPathResource μ‚¬μš© (μ•„λž˜ μ½”λ“œλŠ” bean 등둝 method의 λ‚΄μš©)

final ClassPathResource firebaseAccountResource = new ClassPathResource("/config/firebase-admin-account.json");
try {
    final FirebaseOptions options = FirebaseOptions.builder()
            .setCredentials(GoogleCredentials.fromStream(firebaseAccountResource.getInputStream()))
            .build();

    if (FirebaseApp.getApps().isEmpty()) {
        FirebaseApp.initializeApp(options);
        log.info("Firebase app initialized");
    }
    return FirebaseMessaging.getInstance();
} catch (IOException e) {
    throw new RuntimeException("FirebaseApp을 μ΄ˆκΈ°ν™”ν•  수 μ—†μŠ΅λ‹ˆλ‹€.", e);
}

reference