[Flutter] Android에서 FCM 연동(3) - Topic으로 알림 수신 개별 설정하기

구현 목표

모든 사용자들에게 동일하게 전송되는 알림이 있는데,

설정 화면에서 각각의 알림을 개별적으로 On/Off 할 수 있도록 구현해 보았다.

 

Token과 Topic의 차이점

FCM(Firebase Cloud Messaging)을 통해 사용자가 알림을 수신하는 방식에는 대표적으로 두 가지가 있다.

  • Token 방식: 특정 사용자에게만 알림을 보낼 때 사용
  • Topic 방식: 다수의 사용자에게 동일한 알림을 보낼 때 사용

 

항목 Token Topic
대상 단일 기기 (1:1) 여러 기기 (그룹)
사용 목적 사용자마다 다른 알림 전송 동일한 알림을 다수에게 전송
사용 예시 1:1 메시지, 주문 상태 등 이벤트, 공지 등
전송 방식 개별 토큰으로 전송 topic으로 전송
유지 조건 앱 삭제·재설치 시 토큰 변경될 수 있음 구독 취소 전까지 유지됨

 

Token 등록 예시

{
  token:"APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ",
  notification: {
    title: "새 메시지",
    body: "친구가 메시지를 보냈어요"
  }
}

예시: 사용자가 새 메시지를 받음
→ 해당 사용자의 FCM 토큰을 알아야만 알림을 보낼 수 있다.

 

토큰은 앱을 재설치하거나 장시간 미사용 시 만료될 수 있기 때문에,
토큰을 최신 상태로 유지하기 위한 별도의 로직이 필요하다.

 

Topic 구독 예시

{
  topic: "event",
  notification: {
    title: "특가 이벤트",
    body: "오늘부터 이벤트가 진행됩니다."
  }
}

예시: 모든 사용자에게 이벤트 알림을 전송

 

await FirebaseMessaging.instance.subscribeToTopic('event'); // 구독
await FirebaseMessaging.instance.unsubscribeFromTopic('event'); // 구독 해제

  "event" 알림을 구독한 사용자들에게만 알림이 전송된다.

 

서버에서 Topic으로 메시지 전송하기 (Node.js)

// The topic name can be optionally prefixed with "/topics/".
const topic = 'highScores';

const message = {
  data: {
    score: '850',
    time: '2:45'
  },
  topic: topic
};

// Send a message to devices subscribed to the provided topic.
getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

메시지에 topic을 지정하면, 해당 토픽을 구독한 기기에만 알림이 전송된다.

 

클라이언트에서 주제 구독하기 (Flutter)

앱 첫 실행 시 모든 알림 구독

// main.dart
Future<void> subscribeToAllTopicsOnFirstLaunch() async {
  final prefs = await SharedPreferences.getInstance();
  final alreadySubscribed = prefs.getBool('fcmSubscribed') ?? false;

  if (!alreadySubscribed) {
    await FirebaseMessaging.instance.subscribeToTopic('all'); // 모든 주제 구독
    await prefs.setBool('fcmSubscribed', true);
  }
}

 

알림 개별 수신 설정

// 알림 토픽 상수 정의
class FcmTopics {
  static const String pointExists = "pointExists";
  static const String pointLink = "pointLink";
  static const String pointUseReminder = "pointUseReminder";
}

// 알림 설정 스위치 토글 시 알림 구독 또는 구독 해제
Future<void> _onSwitchChanged(String topic, bool value) async {
    final prefs = await SharedPreferences.getInstance();
    prefs.setBool(topic, value);

    if (value) {
      await FirebaseMessaging.instance.subscribeToTopic(topic);
    } else {
      await FirebaseMessaging.instance.unsubscribeFromTopic(topic);
    }
}

사용자는 `Switch` 위젯을 통해 각 알림 항목을 구독 또는 구독 해제할 수 있다.

 

플러터 FCM 연동 시리즈

 

참고 문서