๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค์•ˆ๋“œ๋กœ์ด๋“œ ๊ฐœ๋ฐœ ๊ธฐ๋ก/๊ธฐ์ˆ™์‚ฌ ํ”„๋กœ์ ํŠธ ๊ธฐ๋ก

๐Ÿ”” Android FCM ์ ์šฉ๊ธฐ 2ํƒ„ : FCM + Retrofit

by hyeonha 2024. 1. 7.

๋ชฉ์ฐจ

    ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—

    ์•ˆ๋…•ํ•˜์„ธ์š”!

    1ํƒ„์— ์ด์–ด ๋ณธ๊ฒฉ์ ์ธ FCM๊ณผ Retrofit ๊ณผ ํ•จ๊ป˜ ๋Œ์•„์˜จ Mandy์ž…๋‹ˆ๋‹ค ๐Ÿ˜€

    ์ง€๋‚œ 1ํƒ„์—์„œ๋Š” Android์˜ Notification์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜๋Š”๋ฐ์š”!

    ์˜ค๋Š˜์€ ๋” ๋‚˜์•„๊ฐ€ FCM๊ณผ Retrofit์„ ์ด์šฉํ•˜์—ฌ ์„ธํƒ ์™„๋ฃŒ ์•Œ๋ฆผ ๊ธฐ๋Šฅ์„ ๋งˆ๋ฌด๋ฆฌ ํ•ด๋ณด๋ ค๊ณ  ํ•ด์š”. ์ง€๋‚œ 1ํƒ„๋ณด๋‹ค ์กฐ๊ธˆ ๋” ๋งŽ์€ ๋‚ด์šฉ์„ ๋‹ค๋ฃฐ ์˜ˆ์ •์ด๋ผ์„œ ์ฐจ๊ทผ์ฐจ๊ทผ ๋”ฐ๋ผ์™€์ฃผ์„ธ์š” ใ…Žใ…Ž

     

    ๊ฒฐ๊ณผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ

    ๋ณธ๊ฒฉ์ ์ธ ๊ฐœ๋ฐœ์— ์•ž์„œ์„œ ๊ตฌํ˜„ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋จผ์ € ๋ณด๋„๋ก ํ• ๊ฒŒ์š”!

    [ ์˜์ƒ ์ฒจ๋ถ€ํ•˜๊ธฐ] 

     

    ์ด์ œ ์‹œ์ž‘ํ•ด๋ด…์‹œ๋‹ค !! 

    FCM ์ดํ•ดํ•˜๊ธฐ

    FCM์€ ๋ชจ๋ฐ”์ผ ์•ฑ ๋ฐ ์›น ์•ฑ์—์„œ ์‹ค์‹œ๊ฐ„ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด์—์š”. ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ ๋””๋ฐ”์ด์Šค๋กœ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‹ค์–‘ํ•œ ์•Œ๋ฆผ ์œ ํ˜•์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”!

     

    FCM ํ๋ฆ„ ์ •๋ฆฌ

    1๏ธโƒฃ FCM์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๋„๋ก ๊ธฐ๊ธฐ ๋“ฑ๋ก

    • ํด๋ผ์ด์–ธํŠธ ์•ฑ์ด ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๋„๋ก ๋“ฑ๋กํ•˜์—ฌ ์šฐ๋ฆฌ์˜ ํœด๋Œ€์ „ํ™” ๊ธฐ๊ธฐ์„ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ํ•˜๋Š” ๋“ฑ๋ก ํ† ํฐ์„ ๋ฐ›์•„์š”.

    2๏ธโƒฃ ๋ฉ”์‹œ์ง€ ์ „์†ก ๋ฐ ์ˆ˜์‹ 

    • ๋ฉ”์‹œ์ง€๋Š” FCM console ํ™˜๊ฒฝ์ด๋‚˜ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ(HTTP ๋“ฑ)์—์„œ ์ž‘์„ฑ๋˜๋ฉฐ ๋ฉ”์‹œ์ง€ ์š”์ฒญ์ด FCM ๋ฐฑ์—”๋“œ๋กœ ์ „์†ก๋˜์–ด์š”
    • FCM ๋ฐฑ์—”๋“œ(์„œ๋ฒ„)๋Š” ๋ฉ”์‹œ์ง€ ์š”์ฒญ์„ ์ˆ˜์‹ ํ•˜๊ณ  ๋ฉ”์‹œ์ง€ ID์™€ ๊ธฐํƒ€ ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์•ˆ๋“œ๋กœ์ด๋“œ ์ „์†ก ๊ณ„์ธต (Android transport layer)๋กœ ๋ณด๋‚ด์š”.
    • ๊ธฐ๊ธฐ์—์„œ ํด๋ผ์ด์–ธํŠธ์•ฑ์ด ๋ฉ”์‹œ์ง€ ๋˜๋Š” ์•Œ๋ฆผ์„ ์ˆ˜์‹ ํ•ด์š”.

     FCM ๋ฐฑ์—”๋“œ๋Š” ์„œ๋ฒ„์™€ ๋™์ผํ•œ ๊ฒƒ์ธ๊ฐ€์š”?


    ๋„ค ! FCM ์„œ๋ฒ„๋ž€ firebase cloud messaging์„ ์ง€์›ํ•˜๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์„œ๋ฒ„ ์‹œ์Šคํ…œ์„ ๋งํ•ด์š”! ์ด ์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์•ฑ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜์—ฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์š”.

     

    FCM ์„œ๋ฒ„์˜ ์—ญํ• 

    1๏ธโƒฃ๋ฉ”์‹œ์ง€ ์ „์†ก :

    ํด๋ผ์ด์–ธํŠธ์•ฑ์— ํ‘ธ์‹œ ์•Œ๋ฆผ ๋ฐ ๋ฐ์ดํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•ด์š”. ์ด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ ๋””๋ฐ”์ด์Šค๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์š”,

    2๏ธโƒฃ๋””๋ฐ”์ด์Šค ๊ด€๋ฆฌ

    FCM ์„œ๋ฒ„๋Š” ๊ฐ ๋””๋ฐ”์ด์Šค์— ๊ณ ์œ ํ•œ ์‹๋ณ„์ž์ธ FCM ํ† ํฐ์„ ํ•˜๋Š”๋ฐ์š”. ์ด ํ† ํฐ์„ ์‚ฌ์šฉํ•ด ์„œ๋ฒ„๋Š” ํŠน์ • ๋””๋ฐ”์ด์Šค์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ์–ด์š”!

    ์šฐ๋ฆฌ ํ”Œ์ ์—์„œ๋Š” Retrofit ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ FCM ์„œ๋ฒ„์— HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์„ ์ด์šฉํ–ˆ์–ด์š”!

    ์ด๋ฅผ ์œ„ํ•ด FCM ์„œ๋ฒ„์— ํ‘ธ์‹œ์•Œ๋ฆผ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•œ Retrofit ์ธํ„ฐํŽ˜์ด์Šค์ธ NotiAPI๋ฅผ ์ •์˜ํ•ด์ฃผ์—ˆ์–ด์š”.

     

    ๋ชฉํ‘œ

    • ์œ ์ €์˜ ํ† ํฐ ์ •๋ณด๋ฅผ ๋ฐ›์•„์™€์„œ
    • Firebase ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋ผ๊ณ  ๋ช…๋ นํ•˜๊ณ 
    • Firebase ์„œ๋ฒ„์—์„œ ์•ฑ์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด์ฃผ๊ณ 
    • ์•ฑ์—์„œ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„์„œ → ๋ฉ”์‹œ์ง€ ์ˆ˜์‹  ๋ถ€๋ถ„
    • ์•ฑ์—์„œ๋Š” ์•Œ๋žŒ์„ ๋„์›Œ์คŒ → ๋ฉ”์‹œ์ง€ ์ˆ˜์‹  ๋ถ€๋ถ„์—์„œ notification ์ฒ˜๋ฆฌ

    ์šฐ๋ฆฌ์˜ ๋ชฉํ‘œ๋Š” ์œ„์™€ ๊ฐ™์•„์š”๐Ÿ’ช์ด๋ฅผ ์œ„ํ•ด ๊ธฐ๋ณธ ์„ค์ •์„ ํ•ด์ค„๊ฒŒ์š”.

     

    ์•ฑ ๋งค๋‹ˆํŽ˜์ŠคํŠธ ์ˆ˜์ •

    FirebaseMessagingService ๋ž€ 

    FCM์„ ์‚ฌ์šฉํ•˜์—ฌ ๋””๋ฐ”์ด์Šค๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ์„œ๋น„์Šค ๋ฅผ ๋งํ•ด์š”.

    ์ด ์„œ๋น„์Šค๋ฅผ ํ™•์žฅํ•˜์—ฌ FCM ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ํฌ๊ทธ๋ผ์šด๋“œ ๋ฐ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ์–ด์š”.

    ์ด๋ฅผ ์œ„ํ•ด FirebaseMessagingService๋ฅผ ํ™•์žฅํ•˜๋Š” ์„œ๋น„์Šค๋ฅผ ๋งค๋‹ˆํŽ˜์ŠคํŠธ ํŒŒ์ผ์— ์ถ”๊ฐ€ํ•ด์ค˜์š”.

     

    ์„œ๋น„์Šค๋ž€?

    ๋”๋ณด๊ธฐ

    ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ Service๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰๋˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งํ•ด์š”!

    • ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…
      • ์˜ˆ๋ฅผ ๋“ค์–ด ์Œ์•…์•ฑ์ด ํ™”๋ฉด์— ํ‘œ์‹œ๋˜์ง€ ์•Š์•„๋„ ์Œ์•… ์žฌ์ƒ์ด ๊ณ„์† ๋˜๋Š” ๊ฒƒ์„ ์ƒ๊ฐํ•˜๋ฉด ๋˜์–ด์š”!
    • ๊ณ„์†๋œ ์‹คํ–‰
      • ์˜ˆ๋ฅผ ๋“ค์–ด ์œ„์น˜ ์ถ”์  ์„œ๋น„์Šค๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์–ด๋–ค ์•ฑ์„ ์‚ฌ์šฉํ•˜๋“  ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๊ณ„์†ํ•ด์„œ ์œ„์น˜๋ฅผ ์ถ”์ ํ•ด์š”!
    • ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€ ํ†ต์‹ 
      • ์„œ๋น„์Šค๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ, ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ ์ˆ˜์‹ ์ž ๋“ฑ๊ณผ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ฅผ ํ†ตํ•ด ์•ฑ์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์•ฑ์—์„œ ์Œ์•…์„ ์žฌ์ƒํ•˜๋Š” ์„œ๋น„์Šค๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ์˜ ์•กํ‹ฐ๋น„ํ‹ฐ์—์„œ ์Œ์•…์„ ์ผ์‹œ์ •์ง€ํ•˜๊ฑฐ๋‚˜ ์Šคํ‚ฌํ•  ๋•Œ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.
    • ์ƒ๋ช… ์ฃผ๊ธฐ ๊ด€๋ฆฌ
      • ์„œ๋น„์Šค๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ์™€๋Š” ๋‹ค๋ฅธ ์ž์ฒด ์ƒ๋ช… ์ฃผ๊ธฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์š”.
    <service
                android:name=".fcm.FirebaseCloudMessagingService"
                android:exported="false"
                android:permission="TODO">
                <intent-filter>
                    <action android:name="com.google.firebase.MESSAGING_EVENT" />
                </intent-filter>
            </service>

     

    ๐Ÿšจ์ฃผ์˜์‚ฌํ•ญ

    android:name์—๋Š” **FirebaseMessagingService** ๋ฅผ ์ƒ์†๋ฐ›์€ ํด๋ž˜์Šค๋ช…์„ ์ ์–ด์ฃผ์–ด์•ผํ•ด์š”.

    ๋‹ค๋ฅธ ์•กํ‹ฐ๋น„ํ‹ฐ ํด๋ž˜์Šค๋‚˜ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ช…์„ ์ ์„ ๊ฒฝ์šฐ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋‹ˆ ์ฃผ์˜ํ•ด์ฃผ์„ธ์š”!

    ์ด๊ฒƒ๋•Œ๋ฌธ์— ๊ณ ์ƒํ•œ ๊ธฐ์–ต์ด.. ๐Ÿ˜

     

    ์œ ์ €์˜ ํ† ํฐ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ

    ์ด์ œ ์•ž์„  ์–ธ๊ธ‰ํ–ˆ๋˜ ํ† ํฐ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ๊ฒŒ์š”!

    ํ† ํฐ์€ ๋””๋ฐ”์ด์Šค๋ฅผ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ํ•ด์ฃผ๊ณ , ์„œ๋ฒ„์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ํŠน์ • ๋””๋ฐ”์ด์Šค๋กœ ์ „์†ก๋  ๋•Œ ์‚ฌ์šฉ๋ผ์š”.

    FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
                    if (!task.isSuccessful) {
                        Log.w(TAG, "Fetching FCM registration token failed", task.exception)
                        return@addOnCompleteListener
                    }
    
                    // Get new FCM registration token
                    val token = task.result
    
                    // Log
                    Log.d("token๋ณด๊ธฐ", token)
             }

     

    ์œ ์ €์˜ ํ† ํฐ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ MainActivity์—์„œ ์œ„ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ์–ด์š”!

    ์ด๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ๋กœ์„œ ํ˜„์žฌ์˜ token์„ ์•Œ ์ˆ˜ ์žˆ์–ด์š”

    ํ•˜์ง€๋งŒ ์ถ”ํ›„ ์Šคํ”Œ๋ž˜์‹œ ํ™”๋ฉด์„ ์ถ”๊ฐ€ํ•˜๊ณ , ์Šคํ”Œ๋ž˜์‹œ ํ™”๋ฉด์ด ๋– ์žˆ๋Š” ๋™์•ˆ token ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋„๋ก ๋กœ์ง์„ ์ด๋™ํ•  ์˜ˆ์ •์ด์—์š”!

     

    ์•„๋ž˜์˜ ๋กœ๊ทธ๋ฅผ ๋ณด๋ฉด ํ† ํฐ์ด ์ž˜ ๊ฐ€์ ธ์™€์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”!

     

    ๐Ÿ’ŒFirebase Console์—์„œ ํ…Œ์ŠคํŠธ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ

     

    FCM ์‹œ์ž‘์„ ์œ„ํ•ด ์•ฑ์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ์ผ ๋•Œ ์ฝ˜์†” ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœ ๊ธฐ๊ธฐ๋กœ ํ…Œ์ŠคํŠธ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•ด๋ณด๋Š” ์‹ค์Šต์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”!

    ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์•ฑ์— ํ…Œ์ŠคํŠธ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ  |  Firebase ํด๋ผ์šฐ๋“œ ๋ฉ”์‹œ์ง•

     

    ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์•ฑ์— ํ…Œ์ŠคํŠธ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ  |  Firebase ํด๋ผ์šฐ๋“œ ๋ฉ”์‹œ์ง•

    Google I/O 2023์—์„œ Firebase์˜ ์ฃผ์š” ์†Œ์‹์„ ํ™•์ธํ•˜์„ธ์š”. ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ ์˜๊ฒฌ ๋ณด๋‚ด๊ธฐ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์•ฑ์— ํ…Œ์ŠคํŠธ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด ์ •๋ฆฌํ•˜๊ธฐ ๋‚ด ํ™˜๊ฒฝ์„ค์ •์„ ๊ธฐ์ค€์œผ๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ์ €์žฅํ•˜๊ณ 

    firebase.google.com

     

    ๊ธฐ๋ณธ ์„ค์ •

    • ํ”„๋กœ์ ํŠธ ์ˆ˜์ค€์˜ Gradle ํŒŒ์ผ์—์„œ dependencies ๋‚ด๋ถ€์— ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.
    classpath 'com.google.gms:google-services:4.3.15'
    • ๋ชจ๋“ˆ(์•ฑ ์ˆ˜์ค€) Gradle ํŒŒ์ผ์— ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”
    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:32.1.0')
    
        // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-messaging-ktx'
        implementation 'com.google.firebase:firebase-analytics-ktx'
    }

     

     

    ๋“ฑ๋ก ํ† ํฐ

    ํŠน์ • ๊ธฐ๊ธฐ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ† ํฐ์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ์•„์•ผํ•œ๋‹ค๊ณ  ํ–ˆ์—ˆ์ฃ ?

    ์ฝ˜์†”ํ™˜๊ฒฝ์—์„œ ์ด ๋•Œ ๊ฐ€์ ธ์˜จ ํ† ํฐ์„ ์ž…๋ ฅํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”.

     

    ์•ž์„œ ๋งค๋‹ˆํŽ˜์ŠคํŠธ ํŒŒ์ผ์—์„œ ์„œ๋น„์Šค๋กœ ๋“ฑ๋กํ•ด์ค€ ํด๋ž˜์Šค ํŒŒ์ผ์„ ์—ด์–ด์ฃผ์„ธ์š”.

    class FirebaseCloudMessagingService :FirebaseMessagingService()

    ์ฒ˜๋Ÿผ FirebaseMessagingService๋ฅผ ํ™•์žฅํ•˜๊ณ  onNewToken ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•ด์ค„๊ฑฐ์˜ˆ์š”.

     

    override fun onNewToken(token: String) {
            super.onNewToken(token)
        }

     

     

    โž• ๋“ฑ๋ก ํ† ํฐ์ด ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ

    ๋”๋ณด๊ธฐ
    • ์•ฑ์ด ์ƒˆ ๊ธฐ๊ธฐ์— ๋ณต์›๋˜๋Š” ๊ฒฝ์šฐ
    • ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ์„ ์ œ๊ฑฐ / ์žฌ์„ค์น˜ํ•˜๋Š” ๊ฒฝ์šฐ
    • ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์šฐ๋Š” ๊ฒฝ์šฐ

    ๐Ÿ’Œ๋ฉ”์‹œ์ง€ ๋ฐ›๊ธฐ

    ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์œผ๋ ค๋ฉด FirebaseMessagingServiceํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ onMessageReceived ๋ฉ”์†Œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜์—ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

    Firebase ์„œ๋ฒ„์—์„œ ์ˆ˜์‹ ๋œ RemoteMessage ๊ฐ์ฒด๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋ฉ”์‹œ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด์š”

     

    ์•„๋ž˜์™€ ๊ฐ™์ด ํŒŒ์ด์–ด๋ฒ ์ด์Šค ์„œ๋ฒ„์—์„œ ๋ณด๋‚ด์˜ค๋Š” RemoteMessage๋ฅผ ๋ฐ›์•„ Log๋กœ ์ฐ์–ด๋ณด๋ฉด ํ™•์ธํ•ด๋ณด์•˜์–ด์š”!

     

    // message.data๋ฅผ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ
    val title= message.data["title"].toString()
            val body = message.data["content"].toString()
    
            Log.d("Cloud",message.data.toString())

     

    //message.notification๋ฅผ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ 
    if (message.notification != null) {
                Log.e("CloudMessage", "Notification ${message.notification}")
                Log.e("CloudMessage", "Notification Title  ${message.notification!!.title}")
                Log.e("CloudMessage", "Notification Body ${message.notification!!.body}")

     

    ์œ„ ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๋กœ ์•„๋ž˜์ฒ˜๋Ÿผ ๋กœ๊ทธ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ์–ด์š”.

         ์ฒซ ๋ฒˆ์งธ ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๋Š” Cloud ํƒœ๊ทธ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

         ๋‘ ๋ฒˆ์งธ ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๋Š” CloudMessage ํƒœ๊ทธ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

     

    ์—ฌ๊ธฐ์„œ ์™œ CloudMessageํƒœ๊ทธ์—๋Š” null์ด ๋œจ๊ณ  ์žˆ์„๊นŒ์š”?

     

    message.notification๊ณผ message.data๋Š” ๋ฌด์Šจ ์ฐจ์ด๊ฐ€ ์žˆ์„๊นŒ์š”?

    FCM์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ์œ ํ˜•์˜ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋งํ•ด์š”.

    • message.notification

    message.notification๋Š” notification๋งŒ ๋ณด๋‚ด๋Š” ๋ฉ”์‹œ์ง€๋กœ ์šฐ๋ฆฌ๊ฐ€ firebase console์—์„œ Cloud Message๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•ด์š”

    ์œ„์ฒ˜๋Ÿผ ์ฝ˜์†”ํ™˜๊ฒฝ์—์„œ ํ† ํฐ์„ ์ด์šฉํ•ด ์ œ ๊ธฐ๊ธฐ๋กœ ํ…Œ์ŠคํŠธ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•ด๋ณด์•˜๋Š”๋ฐ์š”. ์•„๋ž˜์˜ ๋กœ๊ทธ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด message.notification์„ ํ†ตํ•ด ์ „๋‹ฌ๋˜๊ณ  ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์–ด์š”.

     

    message.data

    message.data ํŽ˜์ด๋กœ๋“œ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ •์˜ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ๋•Œ ์‚ฌ์šฉํ•ด์š”.

    ํด๋ผ์ด์–ธํŠธ ์•ฑ์—์„œ ์ˆ˜๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ฃผ์–ด์•ผํ•ด์š”.

    ๋‹ค์‹œ ๋งํ•ด  ํฌ๊ทธ๋ผ์šด๋“œ ๋˜๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ onMessageReceived ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์ฃผ์–ด์•ผํ•ด์š”.

     

    ์ œ๊ฐ€ ๊ตฌํ˜„ํ•œ message.data์˜ ํ˜•ํƒœ๋Š” ์•„๋ž˜์˜ ๋ฐ์ดํ„ฐํด๋ž˜์Šค๋ฅผ ๋”ฐ๋ฅด๊ณ  ์žˆ์–ด์š”,

    data class NotiModel(
        val title:String="",
        val content:String=""
    )

     

    ๊ทธ๋ž˜์„œ ๋กœ๊ทธ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์ •์˜ํ•ด์ค€ title๊ณผ content ํ˜•ํƒœ๋ฅผ ๋”ฐ๋ฅด๊ณ  ์žˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

     

    ์ €๋Š” onMessageReceived ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ

    1๏ธโƒฃ ์ฝ˜์†”์—์„œ ๋ณด๋‚ด์˜จ ๋ฉ”์‹œ์ง€๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด message.notification๋ฅผ Log๋กœ ํ™•์ธํ•˜๋Š” ์ฝ”๋“œ

    2๏ธโƒฃ์ œ๊ฐ€ ์ •์˜ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ message.data ์ฝ”๋“œ

    3๏ธโƒฃ์ด์ „ ์ฑ•ํ„ฐ์—์„œ ์ด์•ผ๊ธฐํ–ˆ๋˜ ์•Œ๋ฆผ ์ฑ„๋„๊ณผ notification์„ ์ƒ์„ฑํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์ฃผ์—ˆ์–ด์š”.

     

    ๐ŸŒŠ์ „์ฒด ํ๋ฆ„ ์ •๋ฆฌ

    FCM ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ชฉ์ ์— ๋Œ€ํ•ด ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ์„ธํƒ์ด ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ธฐ์— ์•Œ๋ฆผ์„ ์ฃผ๊ธฐ ์œ„ํ•จ์ด์—ˆ์–ด์š”.

    ๋”ฐ๋ผ์„œ ์ €๋Š” ์„ธํƒ์ด ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด ์„ธํƒ์ด ์™„๋ฃŒ๋˜๋ฉด ์•„๋ž˜์˜ ์ˆœ์„œ๋กœ ์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ–ˆ์–ด์š”.

     

     

    1๏ธโƒฃNotiModel ํด๋ž˜์Šค ๊ฐ์ฒด ์ƒ์„ฑ

    2๏ธโƒฃPushNotification ํด๋ž˜์Šค ๊ฐ์ฒด ์ƒ์„ฑ

    3๏ธโƒฃ testPush ํ•จ์ˆ˜ ์‹คํ–‰

    4๏ธโƒฃ RetrofitInstance๋ฅผ ํ†ตํ•ด FCM ์„œ๋ฒ„์™€ ํ†ต์‹ 

     

    ์ฝ”๋“œ๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ๊ฒŒ์š”!

     

    0๏ธโƒฃ WasherScreen

    val notiModel = NotiModel("${washer.washerId}๋ฒˆ ์„ธํƒ์ด ์™„๋ฃŒ๋˜์—ˆ์–ด์š”!","\uD83D\uDE0A ์„ธํƒ๋ฌผ์„ ์ฐพ์œผ๋Ÿฌ์™€์ฃผ์„ธ์š” ")
    // TODO: ํ† ํฐ ์ €์žฅ ํ›„ ํ•ด๋‹น ํ† ํฐ์„ ๋„ฃ์–ด์ฃผ๋Š” ๋กœ์ง ์ถ”๊ฐ€ ํ•„์š”
                    
    val pushModel = PushNotification(notiModel)
                   
    testPush(pushModel)

     

    • NotiModel ๊ฐ์ฒด์ธ notiModel์„ ๋งŒ๋“ค์–ด์ค˜์š”.
    • PushNotification ๋ฉ”์†Œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ด notiModel ์„ ๋„˜๊ฒจ์ค˜์š”.

    1๏ธโƒฃNotiModel

    data class NotiModel(
        val title:String="",
        val content:String=""
    )

     

    NotiModel์€ ์œ„์—์„œ ์‚ดํŽด๋ฉด message.data ํ˜•ํƒœ์˜ ํŽ˜์ด๋กœ๋“œ, ์ฆ‰ ๋ฐ์ดํ„ฐ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์˜ˆ์š”.

    • title์€ ์•Œ๋ฆผ์˜ ์ œ๋ชฉ์„, content๋Š” ์•Œ๋ฆผ์˜ ๋‚ด์šฉ์„ ๋‚˜ํƒ€๋‚ด์š”.

    2๏ธโƒฃPushNotification

    class PushNotification(
        val data : NotiModel,
        val to: String
    )

     

    PushNotification๋Š” FCM ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•œ ์ „์ฒด ๋ฉ”์‹œ์ง€ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๋Š” ํด๋ž˜์Šค์˜ˆ์š”.

    • data๋Š” NotiModel ๊ฐ์ฒด
    • to๋Š” FCM์—์„œ ์‚ฌ์šฉ์ž ๊ธฐ๊ธฐ๋ฅผ ์‹๋ณ„ํ•˜๋Š” token๊ฐ’์„ ๋„˜๊ฒจ์ค˜์š”

    3๏ธโƒฃtestPush ํ•จ์ˆ˜

    private fun testPush(notification:PushNotification)= CoroutineScope(Dispatchers.IO).launch {
    
        try {
            val response = RetrofitInstance.api.postNotification(notification)
            if(response.isSuccessful) {
                Log.d("testPush์„ฑ๊ณต","๋ ˆํŠธ๋กœํ•")
    
            }
            else {
                Log.e("์‹คํŒจ","${response.errorBody()?.string()}")
                Log.e("์‹คํŒจ","${response.code()}")
                Log.e("์‹คํŒจ","${response.headers()}")
    
    
            }
        }
        catch (e:Exception){
            e.printStackTrace()
        }
    
    }

     

    testPush ํ•จ์ˆ˜๋Š” RetrofitInstance ์ƒ์„ฑํ•˜์—ฌ retrofit์„ ํ†ตํ•ด FCM ๋ฉ”์‹œ์ง€๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜์˜ˆ์š”.

    ์—ฌ๊ธฐ์„œ Retrofit์€ ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งํ•ด์š”. ์•„๋ž˜ ์ฝ”๋“œ ์„ค๋ช…์€ ์ „์ฒด ํ๋ฆ„์„ ์ดํ•ดํ•œ ํ›„์— ๋ณด๋Š” ๊ฒƒ์„ ์ถ”์ฒœ๋“œ๋ ค์š”!

     

    ์ฝ”๋“œ ์„ค๋ช…

    ๋”๋ณด๊ธฐ

    CoroutineScope(Dispatchers.IO).launch { ... }

    • CoroutineScope๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ด์š”.
    • Dispatchers.IO ๋Š” I/O์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ ํ•ฉํ•œ ๋””์ŠคํŒจ์ฒ˜๋กœ ๋„คํŠธ์›Œํฌ ์ž‘์—…๊ณผ ๊ฐ™์€ I/O์ค‘์‹ฌ์˜ ์ž‘์—…์— ์‚ฌ์šฉ๋˜์–ด์š”.
      • Dispatchers๋ž€ ?
      ์ฝ”๋ฃจํ‹ด์—์„œ ์–ด๋–ค ์Šค๋ ˆ๋“œ๋‚˜ ์Šค๋ ˆ๋“œํ’€์—์„œ ์ฝ”๋“œ ๋ธ”๋ก์„ ์‹คํ–‰ํ•˜๋Š” ์—ญํ• ์„ ํ•ด์š”.
    • ์ฝ”๋ฃจํ‹ด์— ๋Œ€ํ•ด์„œ๋Š” ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ ๋” ์ž์„ธํžˆ ์•Œ๋ ค๋“œ๋ฆด๊ฒŒ์š”!
    • launch๋Š” ๋น„๋™๊ธฐ ์ฝ”๋“œ ๋ธ”๋ก์„ ์‹คํ–‰ํ•˜๋ฉฐ, ์ž‘์—…์ด ์™„๋ฃŒ๋˜๊ธฐ ์ „์— ๋‹ค์Œ ์ฝ”๋“œ๋กœ ์ง„ํ–‰๋˜์ง€ ์•Š์•„์š”.
    • val response = RetrofitInstance.api.postNotification(notification)
      • postNotification์€ Retrofit์— ์ •์˜๋œ API ์ธํ„ฐํŽ˜์ด์Šค ๋ฉ”์„œ๋“œ๋กœ ์„œ๋ฒ„์— POST์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•ด์š”.
      • ์„œ๋ฒ„์˜ ์‘๋‹ต์€ response์— ์ €์žฅ๋ผ์š”.

    4๏ธโƒฃRetrofitInstance

    class RetrofitInstance {
        companion object {
            private val retrofit by lazy {
    
                Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
            }
            val api = retrofit.create(NotiAPI::class.java)
        }
    }

     

    ์ด ํด๋ž˜์Šค๋Š” Retrofit์„ ์ด์šฉํ•˜์—ฌ ์„œ๋ฒ„ ํ†ต์‹ ์„ ์œ„ํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ํด๋ž˜์Šค์˜ˆ์š”.

    • ์ฝ”๋“œ ์„ค๋ช…
    ๋”๋ณด๊ธฐ

    1๏ธโƒฃ companion object ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์œผ๋กœ Retrofit ์ธ์Šคํ„ด์Šค๋ฅผ ๊ด€๋ฆฌํ•ด์š”. ์ด๋Š” ํ†ตํ•ด ์•ฑ ์ „์ฒด์—์„œ ํ•˜๋‚˜์˜ Retrofit ์ธ์Šคํ„ด์Šค๋งŒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

     

    ๐Ÿ’— lazy๋ž€?

    ํ•ด๋‹น ๋ณ€์ˆ˜๊ฐ€ ์ฒ˜์Œ์œผ๋กœ ์‚ฌ์šฉ๋  ๋•Œ๊นŒ์ง€ ์ดˆ๊ธฐํ™”๋ฅผ ์ง€์—ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์š”

    ํ•„์š”ํ•œ ์‹œ์ ์— ๋ณ€์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์–ด ์ž์›์„ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

     

    2๏ธโƒฃretrofit ๋ณ€์ˆ˜

    Retrofit ๋นŒ๋” ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋œ Retrofit ์ธ์Šคํ„ด์Šค๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณ€์ˆ˜์˜ˆ์š”.

    addConverterFactory ๋ฅผ ํ†ตํ•ด Gson ๋ณ€ํ™˜๊ธฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ JSON ๋ฐ์ดํ„ฐ๋ฅผ Kotlin ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ–ˆ์–ด์š”.

    build( ) ๋ฅผ ํ†ตํ•ด ์„ค์ •์ด ์™„๋ฃŒ๋œ Retrofit ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์—ˆ์–ด์š”.

     

    3๏ธโƒฃ api ๋ณ€์ˆ˜

    api ๋ณ€์ˆ˜์—๋Š” ์ƒ์„ฑ๋œ retrofit ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ €์žฅํ–ˆ์–ด์š”

    retrofit.create(NotiAPI::class.java) ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Retrofit์—์„œ ์ƒ์„ฑ๋œ ์ธ์Šคํ„ด์Šค๋กœ๋ถ€ํ„ฐ NotiAPI ๊ตฌํ˜„์ฒด๋ฅผ ์ƒ์„ฑํ•ด์š”.

    retrofit.create()๋ฅผ ํ†ตํ•ด Retrofit์— ์ •์˜๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ–ˆ์–ด์š”.

    ์ด ๋•Œ ๋„˜๊ฒจ์ฃผ๋Š” NotiAPI๋Š” Retrofit์„ ์‚ฌ์šฉํ•˜์—ฌ FCM ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•œ API ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•œ ๊ฒƒ์ด์˜ˆ์š”.

    FCM ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ์—”๋“œํฌ์ธํŠธ ๋ฐ ๋ฉ”์„œ๋“œ๋ฅผ ๋ช…์‹œํ•ด์ค˜์š”

     

    5๏ธโƒฃ NotiAPI ์ธํ„ฐํŽ˜์ด์Šค

    interface NotiAPI {
    // 1 
    	   @Headers("Authorization: key=$SERVER_KEY", "Content-Type:$CONTENT_TYPE")
    // 2    
    		 @POST("/fcm/send")
    // 3     
    		suspend fun postNotification(@Body notification: PushNotification): Response<ResponseBody>
    
    
    }

     

    ์ด์ œ ๋งˆ์ง€๋ง‰์œผ๋กœ NotiAPI ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”.

    ์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” FCM ์„œ๋ฒ„์— ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ HTTP ์š”์ฒญ์„ ์ •์˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.

     

    ์ฝ”๋“œ ์„ค๋ช…

    ๋”๋ณด๊ธฐ

    1๏ธโƒฃ@Header์–ด๋…ธํ…Œ์ด์…˜

    • HTTP ์š”์ฒญ ํ—ค๋” ์„ค์ •
    • "Authorization: key=$SERVER_KEY"
      • FCM ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•œ ์„œ๋ฒ„ํ‚ค๋ฅผ ํ—ค๋”์— ์ถ”๊ฐ€
    • "Content-Type:$CONTENT_TYPE"
      • HTTP ์š”์ฒญ์˜ ์ปจํ…์ธ  ํƒ€์ž… ์„ค์ •

    2๏ธโƒฃ@POST("/fcm/send")

    • POST ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ fcm/send ์—”๋“œํฌ์ธํŠธ์— ์š”์ฒญ์„ ์ „์†กํ•ด์š”
      • FCM์—์„œ๋Š” ํ‘ธ์‹œ์•Œ๋ฆผ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

    โ— ๊ทธ๋ƒฅ fcm/send ๋ผ๊ณ  ํ•ด๋„ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•ด์š”.

    3๏ธโƒฃpostNotification ๋ฉ”์†Œ๋“œ

    • ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ๋น„๋™๊ธฐํ•จ์ˆ˜์˜ˆ์š”
      • suspend ํ‚ค์›Œ๋“œ๋Š” ์ฝ”๋ฃจํ‹ด์—์„œ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ด์š”.

    suspend fun postNotification(@Body notification: PushNotification): Response<ResponseBody>

    • @Body notification : HTTP ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ํ•ด๋‹นํ•˜๋ฉฐ, PushNotification ๊ฐ์ฒด๋ฅผ ์ „์†กํ•ด์š”.
      • ์ด ๊ฐ์ฒด๋Š” ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋‹ด๊ณ  ์žˆ์–ด์š”
    • Response<ResponseBody>
      • Response๋Š” ์„œ๋ฒ„์—์„œ ๋ฐ›์€ HTTP ์‘๋‹ต์„ ๋‚˜ํƒ€๋‚ด๋Š” ํด๋ž˜์Šค์˜ˆ์š”
        • Responces<T>์—์„œ T๋Š” ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต ๋ณธ๋ฌธ์œผ๋กœ ์ „์†กํ•œ ๋ฐ์ดํ„ฐ์˜ ํ˜•ํƒœ๋ฅผ ๋งํ•ด์š”.
        • Response์—๋Š” HTTP ์ƒํƒœ ์ฝ”๋“œ, ์‘๋‹ต ํ—ค๋”, ๋ณธ๋ฌธ ๋“ฑ์ด ํฌํ•จ๋˜์–ด์žˆ์–ด์š”.
      • ResponseBody๋Š” ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์‘๋‹ต์˜ ๋ณธ๋ฌธ์ „์ฒด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํด๋ž˜์Šค์˜ˆ์š”.
        • Response ํด๋ž˜์Šค์˜ body( ) ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ResponseBody ๊ฐ์ฒด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์–ด์š”.

    ์ •๋ฆฌํ•˜๊ธฐ

    ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

    ์ด๋ ‡๊ฒŒ ์„ธํƒ ์™„๋ฃŒ ์•Œ๋ฆผ ๊ธฐ๋Šฅ์„ FCM์œผ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ์—ฌ์ •์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋ฅผ ํ•ด๋ณด์•˜์–ด์š”.

     

    ์ €๋„ FCM์„ ์‹ค์ œ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ ์ „์—๋Š” ์„œ๋ฒ„๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผํ•˜๋Š”๊ฑด์ง€ ์–ด๋–ป๊ฒŒ ํ†ต์‹ ์„ ํ•˜๊ณ  ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด์•ผํ•˜๋Š” ๊ฑด์ธ์ง€ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์› ์–ด์š”. ์ด๋ ‡๊ฒŒ ์‹ค์ œ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๋ฉฐ ๊ฐ์„ ์žก์„ ์ˆ˜ ์žˆ์—ˆ๋‹ต๋‹ˆ๋‹ค ๐Ÿ˜Š

    ์กฐ๊ธˆ์ด๋‚˜๋งˆ ๊ธ€์„ ์ฝ๋Š” ์—ฌ๋Ÿฌ๋ถ„๋“ค์ด FCM์„ ์ดํ•ดํ•˜๋Š”๋ฐ ๋„์›€์ด ๋˜์—ˆ์œผ๋ฉด ์ข‹๊ฒ ๋„ค์š” ใ…Žใ…Ž

     

    ์งˆ๋ฌธ์€ ์–ธ์ œ๋“   ๋Œ“๊ธ€์„ ํ†ตํ•ด ๋‚จ๊ฒจ์ฃผ์„ธ์š”.

    FCM ๊ฐœ๋ฐœ ์—ฌ์ •์€ ์—ฌ๊ธฐ์„œ ๋งˆ๋ฌด๋ฆฌํ•˜๊ณ  ๋‹ค์Œ ํฌ์ŠคํŒ…์œผ๋กœ ์ฐพ์•„์˜ฌ๊ฒŒ์š”! ๐Ÿ™‡

     

    ๊ทธ๋Ÿผ ์ด๋งŒ ์ด์ด ๐Ÿพ

     

     

     

     

    ํ•จ๊ป˜ ๋ณด๋ฉด ์ข‹์„ ์‚ฌ์ดํŠธ

    https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko

     

    Android์—์„œ Firebase ํด๋ผ์šฐ๋“œ ๋ฉ”์‹œ์ง• ํด๋ผ์ด์–ธํŠธ ์•ฑ ์„ค์ •

    Google I/O 2023์—์„œ Firebase์˜ ์ฃผ์š” ์†Œ์‹์„ ํ™•์ธํ•˜์„ธ์š”. ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ ์˜๊ฒฌ ๋ณด๋‚ด๊ธฐ Android์—์„œ Firebase ํด๋ผ์šฐ๋“œ ๋ฉ”์‹œ์ง• ํด๋ผ์ด์–ธํŠธ ์•ฑ ์„ค์ • ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด ์ •๋ฆฌํ•˜๊ธฐ ๋‚ด ํ™˜๊ฒฝ์„ค์ •์„ ๊ธฐ์ค€์œผ๋กœ ์ฝ˜ํ…

    firebase.google.com

     

    728x90