<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko">
	<id>https://smwiki.info/index.php?action=history&amp;feed=atom&amp;title=%ED%94%8C%EB%9F%AC%ED%84%B0%3A%ED%91%B8%EC%8B%9C_%EC%95%8C%EB%9E%8C%28FCM%29</id>
	<title>플러터:푸시 알람(FCM) - 편집 역사</title>
	<link rel="self" type="application/atom+xml" href="https://smwiki.info/index.php?action=history&amp;feed=atom&amp;title=%ED%94%8C%EB%9F%AC%ED%84%B0%3A%ED%91%B8%EC%8B%9C_%EC%95%8C%EB%9E%8C%28FCM%29"/>
	<link rel="alternate" type="text/html" href="https://smwiki.info/index.php?title=%ED%94%8C%EB%9F%AC%ED%84%B0:%ED%91%B8%EC%8B%9C_%EC%95%8C%EB%9E%8C(FCM)&amp;action=history"/>
	<updated>2026-04-26T14:56:33Z</updated>
	<subtitle>이 문서의 편집 역사</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://smwiki.info/index.php?title=%ED%94%8C%EB%9F%AC%ED%84%B0:%ED%91%B8%EC%8B%9C_%EC%95%8C%EB%9E%8C(FCM)&amp;diff=10940&amp;oldid=prev</id>
		<title>Sam: 새 문서: {{플러터}}  == 개요 == FCM(Firebase Cloud Messaging)은 Firebase에서 제공하는 푸시 알림 전송 서비스로, 안드로이드와 iOS를 동시에 지원.  플러터(Flutter) 환경에서는 사실상 표준적인 푸시 알림 수단.  iOS와 안드로이드에서만 사용 가능하다. 브라우저와 이외 OS에선 웹소캣 등 따로 구성해주어야 함.  === 기본 개념 ===  * 서버 키를 통해 알림을 보내는 주체가 관리자임을 인증하...</title>
		<link rel="alternate" type="text/html" href="https://smwiki.info/index.php?title=%ED%94%8C%EB%9F%AC%ED%84%B0:%ED%91%B8%EC%8B%9C_%EC%95%8C%EB%9E%8C(FCM)&amp;diff=10940&amp;oldid=prev"/>
		<updated>2026-01-15T19:16:08Z</updated>

		<summary type="html">&lt;p&gt;새 문서: {{플러터}}  == 개요 == FCM(Firebase Cloud Messaging)은 Firebase에서 제공하는 푸시 알림 전송 서비스로, 안드로이드와 iOS를 동시에 지원.  플러터(Flutter) 환경에서는 사실상 표준적인 푸시 알림 수단.  iOS와 안드로이드에서만 사용 가능하다. 브라우저와 이외 OS에선 웹소캣 등 따로 구성해주어야 함.  === 기본 개념 ===  * 서버 키를 통해 알림을 보내는 주체가 관리자임을 인증하...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;새 문서&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{플러터}}&lt;br /&gt;
&lt;br /&gt;
== 개요 ==&lt;br /&gt;
FCM(Firebase Cloud Messaging)은 Firebase에서 제공하는 푸시 알림 전송 서비스로, 안드로이드와 iOS를 동시에 지원.&lt;br /&gt;
&lt;br /&gt;
플러터(Flutter) 환경에서는 사실상 표준적인 푸시 알림 수단.&lt;br /&gt;
&lt;br /&gt;
iOS와 안드로이드에서만 사용 가능하다. 브라우저와 이외 OS에선 웹소캣 등 따로 구성해주어야 함.&lt;br /&gt;
&lt;br /&gt;
=== 기본 개념 ===&lt;br /&gt;
&lt;br /&gt;
* 서버 키를 통해 알림을 보내는 주체가 관리자임을 인증하고,&lt;br /&gt;
* 기기마다 주어지는 토큰을 통해 어떤 기기로 알림을 보낼지 정한다.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!구분&lt;br /&gt;
!설명&lt;br /&gt;
!비고&lt;br /&gt;
|-&lt;br /&gt;
|FCM 서버 키(Server Key)&lt;br /&gt;
|&lt;br /&gt;
* Firebase 프로젝트 단위로 발급되는 비밀 키 &lt;br /&gt;
* 서버에서 FCM으로 푸시 요청을 보낼 때 사용 &lt;br /&gt;
* 절대 클라이언트(앱)에 포함하면 안 됨&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|FCM 토큰(Registration Token)&lt;br /&gt;
|&lt;br /&gt;
* 앱이 설치된 기기 + 앱 단위로 발급되는 식별자 &lt;br /&gt;
* 푸시 알림의 실제 수신 대상 사용자(기기)&lt;br /&gt;
|서버에서 계정과 매핑&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 전체 구조 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
[사용자 로그인]&lt;br /&gt;
      ↓&lt;br /&gt;
[FCM 토큰 발급 (앱)]&lt;br /&gt;
      ↓&lt;br /&gt;
[서버로 토큰 전송]&lt;br /&gt;
      ↓&lt;br /&gt;
[서버 DB: 계정 ↔ FCM 토큰 저장]&lt;br /&gt;
      ↓&lt;br /&gt;
[알림 발생]&lt;br /&gt;
      ↓&lt;br /&gt;
[FCM 서버 → 기기]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;FCM은 알림을 전달할 뿐, 어떤 사용자에게 보낼지는 서버가 결정한다.&lt;br /&gt;
&lt;br /&gt;
= 예시 프로젝트 =&lt;br /&gt;
&lt;br /&gt;
=== 사전 준비 ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!과정&lt;br /&gt;
!설명&lt;br /&gt;
!비고&lt;br /&gt;
|-&lt;br /&gt;
|Firebase 프로젝트 생성&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Android / iOS 앱 등록&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&amp;lt;code&amp;gt;google-services.json&amp;lt;/code&amp;gt; 또는 &amp;lt;code&amp;gt;GoogleService-Info.plist&amp;lt;/code&amp;gt; 설정 완료&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Flutter 설정&lt;br /&gt;
|&lt;br /&gt;
=== pubspec.yaml ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
dependencies:&lt;br /&gt;
  flutter:&lt;br /&gt;
    sdk: flutter&lt;br /&gt;
  firebase_core: ^2.24.2&lt;br /&gt;
  firebase_messaging: ^14.7.10&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|flutter pub get&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 예시 코드 ===&lt;br /&gt;
&lt;br /&gt;
* onMessage, onMessageOpenedApp, getInitialMessage 이들을 이해하는 게 핵심.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;dart&amp;quot;&amp;gt;&lt;br /&gt;
import &amp;#039;package:flutter/material.dart&amp;#039;;&lt;br /&gt;
import &amp;#039;package:firebase_core/firebase_core.dart&amp;#039;;&lt;br /&gt;
import &amp;#039;package:firebase_messaging/firebase_messaging.dart&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
/// 🔹 백그라운드 메시지 핸들러 (top-level 필수)&lt;br /&gt;
Future&amp;lt;void&amp;gt; firebaseMessagingBackgroundHandler(&lt;br /&gt;
    RemoteMessage message) async {&lt;br /&gt;
  await Firebase.initializeApp();&lt;br /&gt;
  // UI 접근 불가, 필요하면 로그/저장만&lt;br /&gt;
  debugPrint(&amp;#039;백그라운드 메시지 수신: ${message.messageId}&amp;#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Future&amp;lt;void&amp;gt; main() async {&lt;br /&gt;
  WidgetsFlutterBinding.ensureInitialized();&lt;br /&gt;
  await Firebase.initializeApp();&lt;br /&gt;
&lt;br /&gt;
  // 백그라운드 핸들러 등록&lt;br /&gt;
  FirebaseMessaging.onBackgroundMessage(&lt;br /&gt;
    firebaseMessagingBackgroundHandler,&lt;br /&gt;
  );&lt;br /&gt;
&lt;br /&gt;
  runApp(const MyApp());&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class MyApp extends StatefulWidget {&lt;br /&gt;
  const MyApp({super.key});&lt;br /&gt;
&lt;br /&gt;
  @override&lt;br /&gt;
  State&amp;lt;MyApp&amp;gt; createState() =&amp;gt; _MyAppState();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class _MyAppState extends State&amp;lt;MyApp&amp;gt; {&lt;br /&gt;
  String? fcmToken;&lt;br /&gt;
  final List&amp;lt;String&amp;gt; messages = [];&lt;br /&gt;
&lt;br /&gt;
  @override&lt;br /&gt;
  void initState() {&lt;br /&gt;
    super.initState();&lt;br /&gt;
    _initFCM();&lt;br /&gt;
    _setupMessageHandlers();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /// FCM 초기 설정 + 토큰 발급&lt;br /&gt;
  Future&amp;lt;void&amp;gt; _initFCM() async {&lt;br /&gt;
    // iOS 권한 요청 (Android에서는 무시됨)&lt;br /&gt;
    await FirebaseMessaging.instance.requestPermission();&lt;br /&gt;
&lt;br /&gt;
    final token = await FirebaseMessaging.instance.getToken();&lt;br /&gt;
    setState(() {&lt;br /&gt;
      fcmToken = token;&lt;br /&gt;
    });&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /// 메시지 수신 / 클릭 처리&lt;br /&gt;
  void _setupMessageHandlers() {&lt;br /&gt;
    // 1️⃣ 포그라운드 수신&lt;br /&gt;
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {&lt;br /&gt;
      final title = message.notification?.title ?? &amp;#039;(no title)&amp;#039;;&lt;br /&gt;
      final body = message.notification?.body ?? &amp;#039;(no body)&amp;#039;;&lt;br /&gt;
      setState(() {&lt;br /&gt;
        messages.add(&amp;#039;[FOREGROUND] $title - $body&amp;#039;);&lt;br /&gt;
      });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 2️⃣ 백그라운드 상태에서 알림 클릭&lt;br /&gt;
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {&lt;br /&gt;
      final title = message.notification?.title ?? &amp;#039;(no title)&amp;#039;;&lt;br /&gt;
      setState(() {&lt;br /&gt;
        messages.add(&amp;#039;[CLICK - BG] $title&amp;#039;);&lt;br /&gt;
      });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 3️⃣ 종료 상태에서 알림 클릭&lt;br /&gt;
    FirebaseMessaging.instance.getInitialMessage().then((message) {&lt;br /&gt;
      if (message != null) {&lt;br /&gt;
        final title = message.notification?.title ?? &amp;#039;(no title)&amp;#039;;&lt;br /&gt;
        setState(() {&lt;br /&gt;
          messages.add(&amp;#039;[CLICK - TERMINATED] $title&amp;#039;);&lt;br /&gt;
        });&lt;br /&gt;
      }&lt;br /&gt;
    });&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @override&lt;br /&gt;
  Widget build(BuildContext context) {&lt;br /&gt;
    return MaterialApp(&lt;br /&gt;
      home: Scaffold(&lt;br /&gt;
        appBar: AppBar(title: const Text(&amp;#039;FCM 단일 파일 예제&amp;#039;)),&lt;br /&gt;
        body: Padding(&lt;br /&gt;
          padding: const EdgeInsets.all(16),&lt;br /&gt;
          child: Column(&lt;br /&gt;
            crossAxisAlignment: CrossAxisAlignment.start,&lt;br /&gt;
            children: [&lt;br /&gt;
              const Text(&lt;br /&gt;
                &amp;#039;FCM Token&amp;#039;,&lt;br /&gt;
                style: TextStyle(fontWeight: FontWeight.bold),&lt;br /&gt;
              ),&lt;br /&gt;
              SelectableText(&lt;br /&gt;
                fcmToken ?? &amp;#039;토큰 불러오는 중...&amp;#039;,&lt;br /&gt;
                style: const TextStyle(fontSize: 12),&lt;br /&gt;
              ),&lt;br /&gt;
              const SizedBox(height: 16),&lt;br /&gt;
              const Text(&lt;br /&gt;
                &amp;#039;수신 / 클릭 메시지&amp;#039;,&lt;br /&gt;
                style: TextStyle(fontWeight: FontWeight.bold),&lt;br /&gt;
              ),&lt;br /&gt;
              const SizedBox(height: 8),&lt;br /&gt;
              Expanded(&lt;br /&gt;
                child: ListView.builder(&lt;br /&gt;
                  itemCount: messages.length,&lt;br /&gt;
                  itemBuilder: (context, index) {&lt;br /&gt;
                    return ListTile(&lt;br /&gt;
                      title: Text(messages[index]),&lt;br /&gt;
                    );&lt;br /&gt;
                  },&lt;br /&gt;
                ),&lt;br /&gt;
              ),&lt;br /&gt;
            ],&lt;br /&gt;
          ),&lt;br /&gt;
        ),&lt;br /&gt;
      ),&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 푸시 알림 수신 ==&lt;br /&gt;
&lt;br /&gt;
=== 권한 요청 (iOS 필수) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;dart&amp;quot;&amp;gt;&lt;br /&gt;
await FirebaseMessaging.instance.requestPermission(&lt;br /&gt;
  alert: true,&lt;br /&gt;
  badge: true,&lt;br /&gt;
  sound: true,&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 포그라운드 수신 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;dart&amp;quot;&amp;gt;&lt;br /&gt;
FirebaseMessaging.onMessage.listen((RemoteMessage message) {&lt;br /&gt;
  print(&amp;#039;푸시 수신: ${message.notification?.title}&amp;#039;);&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 백그라운드 수신 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;dart&amp;quot;&amp;gt;&lt;br /&gt;
Future&amp;lt;void&amp;gt; firebaseMessagingBackgroundHandler(&lt;br /&gt;
    RemoteMessage message) async {&lt;br /&gt;
  await Firebase.initializeApp();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;dart&amp;quot;&amp;gt;&lt;br /&gt;
FirebaseMessaging.onBackgroundMessage(&lt;br /&gt;
  firebaseMessagingBackgroundHandler,&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 서버 측 (예시) ==&lt;br /&gt;
&lt;br /&gt;
=== Device Token 테이블 구조 ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!필드명&lt;br /&gt;
!설명&lt;br /&gt;
|-&lt;br /&gt;
|user_id&lt;br /&gt;
|사용자 ID&lt;br /&gt;
|-&lt;br /&gt;
|fcm_token&lt;br /&gt;
|기기 토큰&lt;br /&gt;
|-&lt;br /&gt;
|platform&lt;br /&gt;
|android / ios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 푸시 전송 (JSON 예시) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;to&amp;quot;: &amp;quot;FCM_TOKEN&amp;quot;,&lt;br /&gt;
  &amp;quot;notification&amp;quot;: {&lt;br /&gt;
    &amp;quot;title&amp;quot;: &amp;quot;테스트 알림&amp;quot;,&lt;br /&gt;
    &amp;quot;body&amp;quot;: &amp;quot;푸시 알림이 도착했습니다&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 로그인 시 처리 ==&lt;br /&gt;
&lt;br /&gt;
=== 클라이언트(Flutter) ===&lt;br /&gt;
앱 실행 후 FCM 토큰을 발급받는다.&amp;lt;syntaxhighlight lang=&amp;quot;dart&amp;quot;&amp;gt;&lt;br /&gt;
FirebaseMessaging messaging = FirebaseMessaging.instance;&lt;br /&gt;
String? token = await messaging.getToken();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;로그인 성공 시, 해당 토큰을 서버로 전송한다.&lt;br /&gt;
&lt;br /&gt;
=== 서버 ===&lt;br /&gt;
서버는 사용자 계정과 FCM 토큰을 매핑하여 저장한다.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!user_id&lt;br /&gt;
!fcm_token&lt;br /&gt;
!platform&lt;br /&gt;
|-&lt;br /&gt;
|123&lt;br /&gt;
|token_A&lt;br /&gt;
|android&lt;br /&gt;
|-&lt;br /&gt;
|123&lt;br /&gt;
|token_B&lt;br /&gt;
|ios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* 하나의 계정은 여러 기기를 가질 수 있다.&lt;br /&gt;
* FCM 토큰은 &amp;#039;&amp;#039;&amp;#039;기기 단위&amp;#039;&amp;#039;&amp;#039;로 관리한다.&lt;br /&gt;
&lt;br /&gt;
== 로그아웃 / 계정 삭제 처리 ==&lt;br /&gt;
&lt;br /&gt;
=== 로그아웃 ===&lt;br /&gt;
&lt;br /&gt;
* 현재 기기의 FCM 토큰만 삭제&lt;br /&gt;
* 다른 기기 로그인은 유지&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
DELETE FROM device_token&lt;br /&gt;
WHERE user_id = 123&lt;br /&gt;
  AND fcm_token = &amp;#039;token_A&amp;#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 계정 삭제(탈퇴) ===&lt;br /&gt;
&lt;br /&gt;
* 해당 계정에 연결된 모든 FCM 토큰 삭제&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
DELETE FROM device_token&lt;br /&gt;
WHERE user_id = 123;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 토큰 변경 및 예외 처리 ==&lt;br /&gt;
&lt;br /&gt;
=== 토큰 갱신 ===&lt;br /&gt;
다음과 같은 경우 FCM 토큰이 변경될 수 있다.&lt;br /&gt;
&lt;br /&gt;
* 앱 재설치&lt;br /&gt;
* 기기 변경&lt;br /&gt;
* OS 업데이트&lt;br /&gt;
* Firebase 정책 변경&lt;br /&gt;
&lt;br /&gt;
Flutter에서는 토큰 변경 이벤트를 수신하여 서버에 반영해야 한다.&amp;lt;syntaxhighlight lang=&amp;quot;dart&amp;quot;&amp;gt;&lt;br /&gt;
FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {&lt;br /&gt;
  // 서버로 새 토큰 전송&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 앱 삭제 ===&lt;br /&gt;
&lt;br /&gt;
* 서버는 앱 삭제 여부를 직접 알 수 없음&lt;br /&gt;
* 푸시 전송 시 FCM에서 에러 반환&lt;br /&gt;
&lt;br /&gt;
대표적인 에러:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;NotRegistered&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;InvalidRegistration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
이 경우 서버에서 해당 토큰을 삭제해야 한다.&lt;br /&gt;
&lt;br /&gt;
== 푸시 전송 ==&lt;br /&gt;
&lt;br /&gt;
=== 서버 → FCM ===&lt;br /&gt;
서버는 FCM 서버 키를 사용하여 푸시 요청을 전송한다.&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;to&amp;quot;: &amp;quot;fcm_token&amp;quot;,&lt;br /&gt;
  &amp;quot;notification&amp;quot;: {&lt;br /&gt;
    &amp;quot;title&amp;quot;: &amp;quot;새 메시지&amp;quot;,&lt;br /&gt;
    &amp;quot;body&amp;quot;: &amp;quot;홍길동: 안녕하세요&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 중요 사항 ===&lt;br /&gt;
&lt;br /&gt;
* FCM 서버 키는 서버에서만 사용&lt;br /&gt;
* 클라이언트에 노출 금지&lt;br /&gt;
&lt;br /&gt;
== 핵심 정리 ==&lt;br /&gt;
&lt;br /&gt;
* FCM은 &amp;#039;&amp;#039;&amp;#039;전달자&amp;#039;&amp;#039;&amp;#039; 역할만 수행한다.&lt;br /&gt;
* 사용자와 기기의 연결은 &amp;#039;&amp;#039;&amp;#039;서버에서 직접 관리&amp;#039;&amp;#039;&amp;#039;해야 한다.&lt;br /&gt;
* 로그인 = 기기 등록&lt;br /&gt;
* 로그아웃 = 기기 해제&lt;br /&gt;
* 탈퇴 = 모든 기기 해제&lt;br /&gt;
&lt;br /&gt;
== 체크리스트 ==&lt;br /&gt;
&lt;br /&gt;
* 로그인 시 FCM 토큰 등록&lt;br /&gt;
* 로그아웃 시 해당 토큰 삭제&lt;br /&gt;
* 탈퇴 시 전체 토큰 삭제&lt;br /&gt;
* 토큰 갱신 처리&lt;br /&gt;
* FCM 에러 발생 시 토큰 정리&lt;/div&gt;</summary>
		<author><name>Sam</name></author>
	</entry>
</feed>