{"id":11663,"date":"2026-05-06T15:29:19","date_gmt":"2026-05-06T06:29:19","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=11663"},"modified":"2026-05-06T16:08:10","modified_gmt":"2026-05-06T07:08:10","slug":"firebase-cloud-messagingfcm%ec%9c%bc%eb%a1%9c-%ec%95%88%eb%93%9c%eb%a1%9c%ec%9d%b4%eb%93%9c-%ec%95%b1%ec%97%90-%ed%91%b8%ec%8b%9c-%ec%95%8c%eb%a6%bc-%eb%b3%b4%eb%82%b4%ea%b8%b0","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=11663","title":{"rendered":"Firebase Cloud Messaging(FCM)\uc73c\ub85c \uc548\ub4dc\ub85c\uc774\ub4dc \uc571\uc5d0 \ud478\uc2dc \uc54c\ub9bc \ubcf4\ub0b4\uae30"},"content":{"rendered":"<h1>Firebase Cloud Messaging(FCM)\uc73c\ub85c \uc548\ub4dc\ub85c\uc774\ub4dc \uc571\uc5d0 \ud478\uc2dc \uc54c\ub9bc \ubcf4\ub0b4\uae30<\/h1>\n<p>Firebase Cloud Messaging(FCM)\uc744 \uc774\uc6a9\ud574 \ud2b9\uc815 \ud1a0\ud53d(Topic)\uc744 \uad6c\ub3c5\ud55c \uc548\ub4dc\ub85c\uc774\ub4dc \uae30\uae30\uc5d0 \ud478\uc2dc \uc54c\ub9bc\uc744 \uc804\uc1a1\ud558\ub294 \ubc29\ubc95\uc744 \ub2e8\uacc4\ubcc4\ub85c \uc815\ub9ac\ud569\ub2c8\ub2e4.<\/p>\n<blockquote>\n<p>\ubaa8\ub4e0 \uae30\ub2a5\uc774 \ub098\uc5f4\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.<br \/>\n\uc218\uc2e0\ub41c \ud478\uc2dc \ub85c\uceec \uc800\uc7a5, \uc0dd\uba85\uc8fc\uae30\uc5d0 \ub530\ub978 \uba54\ubaa8\ub9ac \ub204\uc218 \ubc29\uc9c0 \ucf54\ub4dc \ub4f1 \ud544\uc694\ud55c \ucf54\ub4dc\ub97c \ucd94\uac00\ud574\uc57c \uc815\uc0c1\uc791\ub3d9\ud569\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<hr \/>\n<h2>1. Firebase \ud504\ub85c\uc81d\ud2b8 \uc124\uc815<\/h2>\n<h3>1-1. Firebase \ud504\ub85c\uc81d\ud2b8 \uc0dd\uc131<\/h3>\n<ol>\n<li><a href=\"https:\/\/console.firebase.google.com\/\">Firebase \ucf58\uc194<\/a>\uc5d0 \uc811\uc18d\ud569\ub2c8\ub2e4.<\/li>\n<li><strong>\uc0c8 Firebase \ud504\ub85c\uc81d\ud2b8 \ub9cc\ub4e4\uae30<\/strong> \ubc84\ud2bc\uc744 \ud074\ub9ad\ud569\ub2c8\ub2e4.<\/li>\n<li>\ud504\ub85c\uc81d\ud2b8 \uc774\ub984\uc744 \uc785\ub825\ud558\uace0 Google Analytics \uc0ac\uc6a9 \uc5ec\ubd80\ub97c \uc120\ud0dd\ud55c \ub4a4 <strong>\ud504\ub85c\uc81d\ud2b8 \ub9cc\ub4e4\uae30<\/strong>\ub97c \ud074\ub9ad\ud569\ub2c8\ub2e4.<br \/>\n(\uc601\ubb38 \ubc0f \uc22b\uc790\ub9cc \ud5c8\uc6a9)<\/li>\n<\/ol>\n<h3>1-2. \uc548\ub4dc\ub85c\uc774\ub4dc \uc571 \ub4f1\ub85d<\/h3>\n<ol>\n<li>\ud504\ub85c\uc81d\ud2b8 \uac1c\uc694 \ud398\uc774\uc9c0\uc5d0\uc11c <strong>\uc571\ucd94\uac00 &gt; Android \uc544\uc774\ucf58<\/strong>\uc744 \ud074\ub9ad\ud569\ub2c8\ub2e4.<\/li>\n<li>\uc548\ub4dc\ub85c\uc774\ub4dc \uc571\uc758 \ud328\ud0a4\uc9c0 \uc774\ub984\uc744 \uc785\ub825\ud569\ub2c8\ub2e4. (\uc608: <code>com.example.myapp<\/code>)<\/li>\n<li><code>google-services.json<\/code> \ud30c\uc77c\uc744 \ub2e4\uc6b4\ub85c\ub4dc\ud569\ub2c8\ub2e4.<\/li>\n<li>\ub2e4\uc6b4\ub85c\ub4dc\ud55c <code>google-services.json<\/code>\uc744 \uc548\ub4dc\ub85c\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\uc758 <code>app\/<\/code> \ud3f4\ub354\uc5d0 \ubcf5\uc0ac\ud569\ub2c8\ub2e4.<\/li>\n<\/ol>\n<h3>1-3. \uc11c\ube44\uc2a4 \uacc4\uc815 \ud0a4 \ubc1c\uae09 (\uc11c\ubc84\uc6a9)<\/h3>\n<p>Python \uc11c\ubc84\uc5d0\uc11c FCM \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud558\ub824\uba74 \uc11c\ube44\uc2a4 \uacc4\uc815 \ud0a4\uac00 \ud544\uc694\ud569\ub2c8\ub2e4.<\/p>\n<ol>\n<li>Firebase \ucf58\uc194 \u2192 <strong>com.example.myapp<\/strong> \u2192 <strong>\ud504\ub85c\uc81d\ud2b8 \uc124\uc815<\/strong> \u2192 <strong>\uc11c\ube44\uc2a4 \uacc4\uc815<\/strong> \ud0ed\uc73c\ub85c \uc774\ub3d9\ud569\ub2c8\ub2e4.<\/li>\n<li><strong>\uc0c8 \ube44\uacf5\uac1c \ud0a4 \uc0dd\uc131<\/strong> \ubc84\ud2bc\uc744 \ud074\ub9ad\ud569\ub2c8\ub2e4.<\/li>\n<li>\ub2e4\uc6b4\ub85c\ub4dc\ub41c JSON \ud30c\uc77c(\uc608: <code>serviceAccountKey.json<\/code>)\uc744 \uc548\uc804\ud55c \uc704\uce58\uc5d0 \ubcf4\uad00\ud569\ub2c8\ub2e4.<br \/>\n(\ud504\ub85c\uc81d\ud2b8\uba85-\ub79c\ub364\ubb38\uc790\uc5f4-firebase-adminsdk-fbsvc-\ub79c\ub364\ubb38\uc790\uc5f4.json \ud615\uc2dd)<\/li>\n<\/ol>\n<blockquote>\n<p><strong>\uc8fc\uc758<\/strong>: \uc11c\ube44\uc2a4 \uacc4\uc815 \ud0a4\ub294 \uc808\ub300 \uc678\ubd80\uc5d0 \ub178\ucd9c\ud558\uac70\ub098 GitHub\uc5d0 \ucee4\ubc0b\ud558\uc9c0 \ub9c8\uc138\uc694.<\/p>\n<\/blockquote>\n<h3>1-4. \uc548\ub4dc\ub85c\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\uc5d0 Firebase \uc758\uc874\uc131 \ucd94\uac00<\/h3>\n<h4>Groovy DSL (<code>build.gradle<\/code>)<\/h4>\n<p><strong>\ud504\ub85c\uc81d\ud2b8 \uc218\uc900 <code>build.gradle<\/code><\/strong><\/p>\n<pre><code class=\"language-gradle\">\/\/ build.gradle (Project level)\nbuildscript {\n    dependencies {\n        classpath &#039;com.google.gms:google-services:4.4.1&#039;\n    }\n}<\/code><\/pre>\n<p>\ub610\ub294 <code>settings.gradle<\/code>\uc5d0 \ud50c\ub7ec\uadf8\uc778 \uad00\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0:<\/p>\n<pre><code class=\"language-gradle\">\/\/ settings.gradle\npluginManagement {\n    plugins {\n        id &#039;com.google.gms.google-services&#039; version &#039;4.4.1&#039; apply false\n    }\n}<\/code><\/pre>\n<p><strong>\uc571 \uc218\uc900 <code>build.gradle<\/code><\/strong><\/p>\n<pre><code class=\"language-gradle\">\/\/ build.gradle (App level)\nplugins {\n    id &#039;com.android.application&#039;\n    id &#039;com.google.gms.google-services&#039;\n}\n\ndependencies {\n    \/\/ Firebase BOM\uc73c\ub85c \ubc84\uc804 \uc77c\uad04 \uad00\ub9ac\n    implementation platform(&#039;com.google.firebase:firebase-bom:33.1.0&#039;)\n    implementation &#039;com.google.firebase:firebase-messaging&#039;\n}<\/code><\/pre>\n<h4>Kotlin DSL (<code>build.gradle.kts<\/code>)<\/h4>\n<p>Android Studio Giraffe(2022.3.1) \uc774\uc0c1\uc758 \uc2e0\uaddc \ud504\ub85c\uc81d\ud2b8\ub294 \uae30\ubcf8\uc801\uc73c\ub85c Kotlin DSL\uc744 \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<p><strong>\ud504\ub85c\uc81d\ud2b8 \uc218\uc900 <code>build.gradle.kts<\/code><\/strong><\/p>\n<pre><code class=\"language-kotlin\">\/\/ build.gradle.kts (Project level)\nbuildscript {\n    dependencies {\n        classpath(&quot;com.google.gms:google-services:4.4.1&quot;)\n    }\n}<\/code><\/pre>\n<p>\ub610\ub294 <code>settings.gradle.kts<\/code>\uc5d0 \ud50c\ub7ec\uadf8\uc778 \uad00\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0:<\/p>\n<pre><code class=\"language-kotlin\">\/\/ settings.gradle.kts\npluginManagement {\n    plugins {\n        id(&quot;com.google.gms.google-services&quot;) version &quot;4.4.1&quot; apply false\n    }\n}<\/code><\/pre>\n<p><strong>\uc571 \uc218\uc900 <code>build.gradle.kts<\/code><\/strong><\/p>\n<pre><code class=\"language-kotlin\">\/\/ build.gradle.kts (App level)\nplugins {\n    id(&quot;com.android.application&quot;)\n    id(&quot;com.google.gms.google-services&quot;)\n}\n\ndependencies {\n    \/\/ Firebase BOM\uc73c\ub85c \ubc84\uc804 \uc77c\uad04 \uad00\ub9ac\n    implementation(platform(&quot;com.google.firebase:firebase-bom:33.1.0&quot;))\n    implementation(&quot;com.google.firebase:firebase-messaging&quot;)\n}<\/code><\/pre>\n<blockquote>\n<p><strong>\ucc38\uace0<\/strong>: Groovy DSL\uacfc\uc758 \uc8fc\uc694 \ucc28\uc774\uc810\uc740 \ubb38\uc790\uc5f4\uc744 <code>&#039;\uc791\uc740\ub530\uc634\ud45c&#039;<\/code> \ub300\uc2e0 <code>&quot;\ud070\ub530\uc634\ud45c&quot;<\/code>\ub85c \uac10\uc2f8\uace0, \ud568\uc218 \ud638\ucd9c \uc2dc \uad04\ud638 <code>()<\/code>\ub97c \uc0dd\ub7b5\ud560 \uc218 \uc5c6\ub2e4\ub294 \uc810\uc785\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<h4>Version Catalog + Kotlin DSL (\uad8c\uc7a5)<\/h4>\n<p>Android Studio Hedgehog(2023.1.1) \uc774\uc0c1 \uc2e0\uaddc \ud504\ub85c\uc81d\ud2b8\uc758 \uae30\ubcf8 \ubc29\uc2dd\uc785\ub2c8\ub2e4. \ubc84\uc804 \uc815\ubcf4\ub97c <code>gradle\/libs.versions.toml<\/code> \ud55c \uacf3\uc5d0\uc11c \uc911\uc559 \uad00\ub9ac\ud558\ubbc0\ub85c, \uba40\ud2f0 \ubaa8\ub4c8 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \ud2b9\ud788 \uc720\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<p><strong><code>gradle\/libs.versions.toml<\/code><\/strong><\/p>\n<pre><code class=\"language-toml\">[versions]\ngoogleServices = &quot;4.4.1&quot;\nfirebaseBom    = &quot;33.1.0&quot;\n\n[libraries]\nfirebase-bom       = { group = &quot;com.google.firebase&quot;, name = &quot;firebase-bom&quot;,       version.ref = &quot;firebaseBom&quot; }\nfirebase-messaging = { group = &quot;com.google.firebase&quot;, name = &quot;firebase-messaging&quot; }\n# firebase-messaging = { group = &quot;com.google.firebase&quot;, name = &quot;firebase-messaging-ktx&quot; }\n\n[plugins]\ngoogle-services = { id = &quot;com.google.gms.google-services&quot;, version.ref = &quot;googleServices&quot; }<\/code><\/pre>\n<p><strong>\ud504\ub85c\uc81d\ud2b8 \uc218\uc900 <code>build.gradle.kts<\/code><\/strong><\/p>\n<pre><code class=\"language-kotlin\">\/\/ build.gradle.kts (Project level)\nplugins {\n    alias(libs.plugins.android.application) apply false\n    alias(libs.plugins.google.services)     apply false\n    \/\/ \uae30\ud0c0 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ud50c\ub7ec\uadf8\uc778 ...\n}<\/code><\/pre>\n<p><strong>\uc571 \uc218\uc900 <code>build.gradle.kts<\/code><\/strong><\/p>\n<pre><code class=\"language-kotlin\">\/\/ build.gradle.kts (App level)\nplugins {\n    alias(libs.plugins.android.application)\n    alias(libs.plugins.google.services)\n}\n\ndependencies {\n    \/\/ toml\uc5d0 \uc815\uc758\ub41c \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c alias\ub85c \ucc38\uc870\n    implementation(platform(libs.firebase.bom))\n    implementation(libs.firebase.messaging)\n}<\/code><\/pre>\n<blockquote>\n<p><strong>\ucc38\uace0<\/strong>: <code>libs.plugins.android.application<\/code> \ucc98\ub7fc <code>.<\/code>\uc73c\ub85c \uc5f0\uacb0\ub41c alias\ub294 toml\uc758 <code>-<\/code>\ub97c <code>.<\/code>\uc73c\ub85c \ubcc0\ud658\ud55c \uac83\uc785\ub2c8\ub2e4. (\uc608: <code>android-application<\/code> \u2192 <code>libs.plugins.android.application<\/code>)<\/p>\n<\/blockquote>\n<p>Gradle Sync\ub97c \uc2e4\ud589\ud558\uba74 \uc124\uc815\uc774 \uc644\ub8cc\ub429\ub2c8\ub2e4.<\/p>\n<hr \/>\n<h2>2. Python \uc571\uc73c\ub85c \ud1a0\ud53d \ud478\uc2dc \ubc1c\uc1a1<\/h2>\n<p>Firebase Admin SDK\ub97c \uc0ac\uc6a9\ud574 \ud2b9\uc815 \ud1a0\ud53d\uc744 \uad6c\ub3c5 \uc911\uc778 \ubaa8\ub4e0 \uae30\uae30\uc5d0 \ud478\uc2dc\ub97c \uc804\uc1a1\ud569\ub2c8\ub2e4.<\/p>\n<h3>2-1. \ud328\ud0a4\uc9c0 \uc124\uce58<\/h3>\n<pre><code class=\"language-bash\">pip install firebase-admin<\/code><\/pre>\n<h3>2-2. \uae30\ubcf8 \ud1a0\ud53d \uba54\uc2dc\uc9c0 \uc804\uc1a1<\/h3>\n<pre><code class=\"language-python\"># send_push.py\nimport firebase_admin\nfrom firebase_admin import credentials, messaging\n\n# \uc11c\ube44\uc2a4 \uacc4\uc815 \ud0a4\ub85c Firebase \ucd08\uae30\ud654 (\ucd5c\ucd08 1\ud68c\ub9cc \uc2e4\ud589)\ncred = credentials.Certificate(&quot;serviceAccountKey.json&quot;)\nfirebase_admin.initialize_app(cred)\n\ndef send_topic_message(topic: str, title: str, body: str, data: dict = None):\n    &quot;&quot;&quot;\n    \ud2b9\uc815 \ud1a0\ud53d\uc744 \uad6c\ub3c5\ud55c \ubaa8\ub4e0 \uae30\uae30\uc5d0 \ud478\uc2dc \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud569\ub2c8\ub2e4.\n\n    :param topic: \uad6c\ub3c5 \ud1a0\ud53d \uc774\ub984 (\uc608: &quot;news&quot;, &quot;alerts&quot;)\n    :param title: \uc54c\ub9bc \uc81c\ubaa9\n    :param body:  \uc54c\ub9bc \ubcf8\ubb38\n    :param data:  \ucee4\uc2a4\ud140 \ub370\uc774\ud130 \ud398\uc774\ub85c\ub4dc (\uc120\ud0dd \uc0ac\ud56d)\n    &quot;&quot;&quot;\n    message = messaging.Message(\n        notification=messaging.Notification(\n            title=title,\n            body=body,\n        ),\n        data=data or {},\n        topic=topic,\n    )\n\n    response = messaging.send(message)\n    print(f&quot;[\uc131\uacf5] \uba54\uc2dc\uc9c0 ID: {response}&quot;)\n    return response\n\nif __name__ == &quot;__main__&quot;:\n    send_topic_message(\n        topic=&quot;news&quot;,\n        title=&quot;\uc624\ub298\uc758 \ub274\uc2a4 \ud83d\udcf0&quot;,\n        body=&quot;\uc0c8\ub85c\uc6b4 \uae30\uc0ac\uac00 \ub4f1\ub85d\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \uc9c0\uae08 \ud655\uc778\ud574\ubcf4\uc138\uc694!&quot;,\n        data={&quot;article_id&quot;: &quot;12345&quot;, &quot;category&quot;: &quot;tech&quot;},\n    )<\/code><\/pre>\n<h3>2-3. \uc548\ub4dc\ub85c\uc774\ub4dc \uc804\uc6a9 \uc635\uc158 \ucd94\uac00<\/h3>\n<p>\uc548\ub4dc\ub85c\uc774\ub4dc \uae30\uae30\uc5d0\uc11c \uc54c\ub9bc \ucc44\ub110, \uc544\uc774\ucf58, \uc6b0\uc120\uc21c\uc704 \ub4f1\uc744 \uc138\ubc00\ud558\uac8c \uc81c\uc5b4\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-python\">import firebase_admin\nfrom firebase_admin import credentials, messaging\n\ncred = credentials.Certificate(&quot;serviceAccountKey.json&quot;)\nfirebase_admin.initialize_app(cred)\n\ndef send_topic_message_android(topic: str, title: str, body: str):\n    message = messaging.Message(\n        notification=messaging.Notification(\n            title=title,\n            body=body,\n        ),\n        android=messaging.AndroidConfig(\n            priority=&quot;high&quot;,                    # \uba54\uc2dc\uc9c0 \uc6b0\uc120\uc21c\uc704 (normal \/ high)\n            notification=messaging.AndroidNotification(\n                title=title,\n                body=body,\n                icon=&quot;ic_notification&quot;,         # res\/drawable \uc544\uc774\ucf58 \uc774\ub984\n                color=&quot;#FF5722&quot;,                # \uc544\uc774\ucf58 \uc0c9\uc0c1 (Hex)\n                channel_id=&quot;default_channel&quot;,   # \uc548\ub4dc\ub85c\uc774\ub4dc \uc54c\ub9bc \ucc44\ub110 ID\n                sound=&quot;default&quot;,\n                click_action=&quot;OPEN_MAIN_ACTIVITY&quot;,  # \uc54c\ub9bc \ud074\ub9ad \uc2dc \uc2e4\ud589\ud560 \uc778\ud150\ud2b8 \uc561\uc158\n            ),\n        ),\n        data={\n            &quot;type&quot;: &quot;NEWS&quot;,\n            &quot;target_id&quot;: &quot;42&quot;,\n        },\n        topic=topic,\n    )\n\n    response = messaging.send(message)\n    print(f&quot;[\uc131\uacf5] \uba54\uc2dc\uc9c0 ID: {response}&quot;)\n    return response\n\nif __name__ == &quot;__main__&quot;:\n    send_topic_message_android(\n        topic=&quot;mytopic&quot;,\n        title=&quot;\uc18d\ubcf4 \ud83d\udea8&quot;,\n        body=&quot;\uc911\uc694\ud55c \ub274\uc2a4\uac00 \ub3c4\ucc29\ud588\uc2b5\ub2c8\ub2e4!&quot;,\n    )<\/code><\/pre>\n<h3>2-4. \uc2e4\ud589<\/h3>\n<pre><code class=\"language-bash\">python send_push.py<\/code><\/pre>\n<p>\uc131\uacf5 \uc2dc \uc544\ub798\uc640 \uac19\uc774 \uba54\uc2dc\uc9c0 ID\uac00 \ucd9c\ub825\ub429\ub2c8\ub2e4.<\/p>\n<pre><code>[\uc131\uacf5] \uba54\uc2dc\uc9c0 ID: projects\/your-project-id\/messages\/0:1234567890abcdef<\/code><\/pre>\n<hr \/>\n<h2>3. \uc548\ub4dc\ub85c\uc774\ub4dc \uc571\uc5d0\uc11c \ud1a0\ud53d \uc218\uc2e0<\/h2>\n<h3>3-1. FirebaseMessagingService \uad6c\ud604<\/h3>\n<p><code>app\/src\/main\/java\/...\/MyFirebaseMessagingService.kt<\/code> \ud30c\uc77c\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-kotlin\">\/\/ MyFirebaseMessagingService.kt\npackage com.example.myapp\n\nimport android.app.NotificationChannel\nimport android.app.NotificationManager\nimport android.app.PendingIntent\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Build\nimport androidx.core.app.NotificationCompat\nimport com.google.firebase.messaging.FirebaseMessagingService\nimport com.google.firebase.messaging.RemoteMessage\n\nclass MyFirebaseMessagingService : FirebaseMessagingService() {\n\n    companion object {\n        private const val CHANNEL_ID = &quot;default_channel&quot;\n        private const val CHANNEL_NAME = &quot;\uae30\ubcf8 \uc54c\ub9bc&quot;\n    }\n\n    \/**\n     * FCM \ud1a0\ud070\uc774 \uc0c8\ub85c \ubc1c\uae09\ub418\uac70\ub098 \uac31\uc2e0\ub420 \ub54c \ud638\ucd9c\ub429\ub2c8\ub2e4.\n     * \uc11c\ubc84\uc5d0 \ucd5c\uc2e0 \ud1a0\ud070\uc744 \uc800\uc7a5\ud558\ub824\uba74 \uc5ec\uae30\uc11c \uc5c5\ub85c\ub4dc \ub85c\uc9c1\uc744 \ucd94\uac00\ud558\uc138\uc694.\n     *\/\n    override fun onNewToken(token: String) {\n        super.onNewToken(token)\n        \/\/ TODO: \uc11c\ubc84\ub85c \ud1a0\ud070 \uc804\uc1a1\n        val topic = &quot;mytopic&quot;\n        if (topic != null) {\n            FirebaseMessaging.getInstance().subscribeToTopic(topic)\n        }\n    }\n\n    \/**\n     * \ud3ec\uadf8\ub77c\uc6b4\ub4dc \uc0c1\ud0dc\uc5d0\uc11c FCM \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud560 \ub54c \ud638\ucd9c\ub429\ub2c8\ub2e4.\n     * \ubc31\uadf8\ub77c\uc6b4\ub4dc\/\uc885\ub8cc \uc0c1\ud0dc\uc5d0\uc11c\ub294 \uc2dc\uc2a4\ud15c\uc774 \uc790\ub3d9\uc73c\ub85c \uc54c\ub9bc\uc744 \ud45c\uc2dc\ud569\ub2c8\ub2e4.\n     *\/\n    override fun onMessageReceived(remoteMessage: RemoteMessage) {\n        super.onMessageReceived(remoteMessage)\n\n        val title = remoteMessage.notification?.title ?: &quot;\uc0c8 \uc54c\ub9bc&quot;\n        val body  = remoteMessage.notification?.body  ?: &quot;&quot;\n        val data  = remoteMessage.data  \/\/ \ucee4\uc2a4\ud140 \ub370\uc774\ud130 Map\n\n        \/\/ \ucee4\uc2a4\ud140 \ub370\uc774\ud130 \ucc98\ub9ac \uc608\uc2dc\n        val articleId = data[&quot;article_id&quot;]\n        val type      = data[&quot;type&quot;]\n\n        showNotification(title, body)\n    }\n\n    private fun showNotification(title: String, body: String) {\n        val notificationManager =\n            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager\n\n        \/\/ Android 8.0 (Oreo) \uc774\uc0c1\uc740 \uc54c\ub9bc \ucc44\ub110\uc774 \ud544\uc218\n        if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {\n            val channel = NotificationChannel(\n                CHANNEL_ID,\n                CHANNEL_NAME,\n                NotificationManager.IMPORTANCE_HIGH\n            )\n            notificationManager.createNotificationChannel(channel)\n        }\n\n        val intent = Intent(this, MainActivity::class.java).apply {\n            flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP\n        }\n        val pendingIntent = PendingIntent.getActivity(\n            this, 0, intent,\n            PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val notification = NotificationCompat.Builder(this, CHANNEL_ID)\n            .setSmallIcon(R.drawable.ic_notification)\n            .setContentTitle(title)\n            .setContentText(body)\n            .setAutoCancel(true)\n            .setPriority(NotificationCompat.PRIORITY_HIGH)\n            .setContentIntent(pendingIntent)\n            .build()\n\n        notificationManager.notify(System.currentTimeMillis().toInt(), notification)\n    }\n}<\/code><\/pre>\n<h3>3-2. AndroidManifest.xml \ub4f1\ub85d<\/h3>\n<pre><code class=\"language-xml\">&lt;!-- AndroidManifest.xml --&gt;\n&lt;application ... &gt;\n\n    &lt;!-- FCM \uc11c\ube44\uc2a4 \ub4f1\ub85d --&gt;\n    &lt;service\n        android:name=&quot;.MyFirebaseMessagingService&quot;\n        android:exported=&quot;false&quot;&gt;\n        &lt;intent-filter&gt;\n            &lt;action android:name=&quot;com.google.firebase.MESSAGING_EVENT&quot; \/&gt;\n        &lt;\/intent-filter&gt;\n    &lt;\/service&gt;\n\n    &lt;!-- \uae30\ubcf8 \uc54c\ub9bc \ucc44\ub110 ID \uc124\uc815 (\ubc31\uadf8\ub77c\uc6b4\ub4dc \uc218\uc2e0 \uc2dc \uc0ac\uc6a9) --&gt;\n    &lt;meta-data\n        android:name=&quot;com.google.firebase.messaging.default_notification_channel_id&quot;\n        android:value=&quot;default_channel&quot; \/&gt;\n\n    &lt;!-- \uae30\ubcf8 \uc54c\ub9bc \uc544\uc774\ucf58 \uc124\uc815 --&gt;\n    &lt;meta-data\n        android:name=&quot;com.google.firebase.messaging.default_notification_icon&quot;\n        android:resource=&quot;@drawable\/ic_notification&quot; \/&gt;\n\n&lt;\/application&gt;<\/code><\/pre>\n<h3>3-3. \ud1a0\ud53d \uad6c\ub3c5 \ubc0f \uad6c\ub3c5 \ud574\uc81c<\/h3>\n<p>\uc571\uc774 \uc2e4\ud589\ub420 \ub54c \uc6d0\ud558\ub294 \ud1a0\ud53d\uc744 \uad6c\ub3c5\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-kotlin\">\/\/ MainActivity.kt\nimport com.google.firebase.messaging.FirebaseMessaging\n\nclass MainActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n\n        subscribeToTopic(&quot;news&quot;)\n    }\n\n    \/** \ud2b9\uc815 \ud1a0\ud53d \uad6c\ub3c5 *\/\n    private fun subscribeToTopic(topic: String) {\n        FirebaseMessaging.getInstance().subscribeToTopic(topic)\n            .addOnCompleteListener { task -&gt;\n                if (task.isSuccessful) {\n                    \/\/ \uad6c\ub3c5 \uc131\uacf5\n                } else {\n                    \/\/ \uad6c\ub3c5 \uc2e4\ud328\n                }\n            }\n    }\n\n    \/** \ud2b9\uc815 \ud1a0\ud53d \uad6c\ub3c5 \ud574\uc81c *\/\n    private fun unsubscribeFromTopic(topic: String) {\n        FirebaseMessaging.getInstance().unsubscribeFromTopic(topic)\n            .addOnCompleteListener { task -&gt;\n                if (task.isSuccessful) {\n                    \/\/ \uad6c\ub3c5 \ud574\uc81c \uc131\uacf5\n                }\n            }\n    }\n}<\/code><\/pre>\n<h3>3-4. \ud3ec\uadf8\ub77c\uc6b4\ub4dc \/ \ubc31\uadf8\ub77c\uc6b4\ub4dc \ub3d9\uc791 \ucc28\uc774<\/h3>\n<table>\n<thead>\n<tr>\n<th>\uc0c1\ud0dc<\/th>\n<th>\ub3d9\uc791<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>\ud3ec\uadf8\ub77c\uc6b4\ub4dc<\/strong><\/td>\n<td><code>onMessageReceived()<\/code> \ud638\ucd9c \u2192 \uac1c\ubc1c\uc790\uac00 \uc9c1\uc811 \uc54c\ub9bc\uc744 \ud45c\uc2dc\ud574\uc57c \ud568<\/td>\n<\/tr>\n<tr>\n<td><strong>\ubc31\uadf8\ub77c\uc6b4\ub4dc<\/strong><\/td>\n<td>\uc2dc\uc2a4\ud15c\uc774 <code>notification<\/code> \ud398\uc774\ub85c\ub4dc\ub97c \uc790\ub3d9\uc73c\ub85c \uc0c1\ud0dc \ubc14\uc5d0 \ud45c\uc2dc<\/td>\n<\/tr>\n<tr>\n<td><strong>\uc571 \uc885\ub8cc<\/strong><\/td>\n<td>\uc2dc\uc2a4\ud15c\uc774 <code>notification<\/code> \ud398\uc774\ub85c\ub4dc\ub97c \uc790\ub3d9\uc73c\ub85c \uc0c1\ud0dc \ubc14\uc5d0 \ud45c\uc2dc<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<blockquote>\n<p>\ud83d\udca1 <strong>\ud301<\/strong>: \ud3ec\uadf8\ub77c\uc6b4\ub4dc\uc5d0\uc11c\ub3c4 \uc54c\ub9bc\uc744 \uc790\ub3d9\uc73c\ub85c \ud45c\uc2dc\ud558\ub824\uba74 <code>onMessageReceived()<\/code> \uc548\uc5d0\uc11c \uc9c1\uc811 <code>NotificationManager<\/code>\ub97c \ud638\ucd9c\ud574\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<hr \/>\n<h2>\uc804\uccb4 \ud750\ub984 \uc694\uc57d<\/h2>\n<pre><code>[Python \uc11c\ubc84]\n    \u2502\n    \u2502  Firebase Admin SDK\ub85c\n    \u2502  &quot;news&quot; \ud1a0\ud53d\uc5d0 \uba54\uc2dc\uc9c0 \uc804\uc1a1\n    \u25bc\n[Firebase FCM \uc11c\ubc84]\n    \u2502\n    \u2502  &quot;news&quot; \ud1a0\ud53d\uc744 \uad6c\ub3c5\ud55c\n    \u2502  \ubaa8\ub4e0 \uae30\uae30\uc5d0 \uba54\uc2dc\uc9c0 \uc804\ub2ec\n    \u25bc\n[\uc548\ub4dc\ub85c\uc774\ub4dc \uc571]\n    \u251c\u2500 \ud3ec\uadf8\ub77c\uc6b4\ub4dc: onMessageReceived() \u2192 \ucee4\uc2a4\ud140 \uc54c\ub9bc \ud45c\uc2dc\n    \u2514\u2500 \ubc31\uadf8\ub77c\uc6b4\ub4dc\/\uc885\ub8cc: \uc2dc\uc2a4\ud15c\uc774 \uc54c\ub9bc \uc790\ub3d9 \ud45c\uc2dc<\/code><\/pre>\n<hr \/>\n<h2>\ucc38\uace0 \uc790\ub8cc<\/h2>\n<ul>\n<li><a href=\"https:\/\/firebase.google.com\/docs\/cloud-messaging\">Firebase Cloud Messaging \uacf5\uc2dd \ubb38\uc11c<\/a><\/li>\n<li><a href=\"https:\/\/firebase.google.com\/docs\/admin\/setup#python\">Firebase Admin Python SDK<\/a><\/li>\n<li><a href=\"https:\/\/firebase.google.com\/docs\/cloud-messaging\/android\/receive\">Android\uc5d0\uc11c FCM \uba54\uc2dc\uc9c0 \uc218\uc2e0<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Firebase Cloud Messaging(FCM)\uc73c\ub85c \uc548\ub4dc\ub85c\uc774\ub4dc \uc571\uc5d0 \ud478\uc2dc \uc54c\ub9bc \ubcf4\ub0b4\uae30 Firebase Cloud Messaging(FCM)\uc744 \uc774\uc6a9\ud574 \ud2b9\uc815 \ud1a0\ud53d(Topic)\uc744 \uad6c\ub3c5\ud55c \uc548\ub4dc\ub85c\uc774\ub4dc \uae30\uae30\uc5d0 \ud478\uc2dc \uc54c\ub9bc\uc744 \uc804\uc1a1\ud558\ub294 \ubc29\ubc95\uc744 \ub2e8\uacc4\ubcc4\ub85c \uc815\ub9ac\ud569\ub2c8\ub2e4. \ubaa8\ub4e0 \uae30\ub2a5\uc774 \ub098\uc5f4\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc218\uc2e0\ub41c \ud478\uc2dc \ub85c\uceec \uc800\uc7a5, \uc0dd\uba85\uc8fc\uae30\uc5d0 \ub530\ub978 \uba54\ubaa8\ub9ac \ub204\uc218 \ubc29\uc9c0 \ucf54\ub4dc \ub4f1 \ud544\uc694\ud55c \ucf54\ub4dc\ub97c \ucd94\uac00\ud574\uc57c \uc815\uc0c1\uc791\ub3d9\ud569\ub2c8\ub2e4. 1. Firebase \ud504\ub85c\uc81d\ud2b8 \uc124\uc815 1-1. Firebase \ud504\ub85c\uc81d\ud2b8 \uc0dd\uc131 Firebase \ucf58\uc194\uc5d0 \uc811\uc18d\ud569\ub2c8\ub2e4. \uc0c8\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=11663\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[],"class_list":["post-11663","post","type-post","status-publish","format-standard","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/11663","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11663"}],"version-history":[{"count":5,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/11663\/revisions"}],"predecessor-version":[{"id":11668,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/11663\/revisions\/11668"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11663"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11663"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11663"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}