Firebase FCM(Firebase Cloud Message) 사용해 보기

Firebase Cloud Message Documentation

firebase_core | Flutter Package
firebase_messaging | Flutter Package
http | Dart Package
permission_handler | Flutter Package

Firebase 세팅하기 - Flutter 3.0 이후
Firebase 세팅하기 - Flutter 3.0 이전

🔔 Local Notifications 사용해 보기

Local Notifications 1편(설정)
Local Notifications 2편(사용방법)
Local Notifications 3편(리스너)

IOS > 시뮬레이터로 Remote Push 테스트 하기
Remote Push 수신시 앱 아이콘 뱃지 관리해 보기

이번에는 Firebase의 유명하고 강력한 서비스인 FCM(Firebase Cloud Message)에 대해서 살펴보도록 하겠다.

FCM은 플랫폼에 종속되지 않고 Push를 보내주는 서비스이다. 플랫폼에 종속되지 않는다는 말이 이해되지 않을 수 있다. Firebase의 FCM을 사용하지 않으면 우리의 서비스는 APNs(Apple Push Notification service), GCM(Google Cloud Messaging) 각 플랫폼 별 메시지 전송 서버에 접속하여 실시간으로 Push를 수신 받을 수 있도록 처리를 해주어야 한다.
이렇게 되면 디바이스의 메모리, 배터리, 네트워크 환경 등의 리소스 낭비를 발생시킬 수 있다.
Firebase에서는 FCM 기능을 사용하여 Cloud Message 서버를 디바이스와 각 플랫폼 서버(APNs/GCM)의 중간에 배치함으로써, 디바이스의 네트워크 환경만 제공된다면 Push를 전송받을 수 있게 해주는 서비스이다,

Push는 서비스하는 플랫폼의 마케팅, 활성 사용자 수 증가 등의 효과를 일으키기 위해 사용되기도 하고, 앱을 설치한 유저의 삭제 상태를 알기 위한 Silent Push에도 활용되고 있는 서비스이다.

우리가 다양한 앱을 사용해보면 Push 알림을 보내지 않는 서비스는 거의 없다고 볼 수 있다. 한 번 개발해 보면서 더 자세히 FCM에 대해 알아보자.

Firebase

Firebase 프로젝트에서 Messaging 탭을 클릭하여 대시보드로 진입하자.

첫 번째 캠페인 만들기를 클릭하여 캠페인을 생성해 보도록 하자. 캠페인은 단일 Push Message를 등록하는 거라고 생각하면 된다.

Firebase 알림 메시지 와 Firebase 인앱 메시지가 있는데, 우선 알림 메시지로 만들어보자.

Push 메시지 캠페인을 생성하는 화면이 나올 것인데, 우선 아무것도 세팅하지 않은 상태에서 보내보자.

먼저 알림 제목과 알림 텍스트는 필수로 입력되어야 하는 값이고, 기기 미리보기를 통해서 어떻게 보여지는지 확인할 수 있다.
알림 이미지를 사용하여 이미지를 보여줄 수도 있고, 알림 이름을 통해 캠페인을 구분 짓는데 사용할 수도 있다.

알림 제목, 텍스트를 입력하고 테스트 메시지 전송을 눌러보면, FCM 등록 토큰을 추가하라고 나온다.

Test

우선 테스트를 먼저 진행해보기 위해 Flutter 프로젝트로 돌아와 토큰을 발급받아 보자.

dependencies

dependencies:
	firebase_core: ^2.7.0
	firebase_messaging: ^14.3.0

getToken

아래 코드를 입력하면 FCM Token을 발급 받을 수 있다. 토큰 발급 방법은 간단하다.

String? _fcmToken = await FirebaseMessaging.instance.getToken();
logger.e(_fcmToken);

발급 받은 토큰을 등록하고 등록한 토큰을 선택한 뒤 테스트를 클릭해 보자.

디바이스에 푸시 메시지가 전송된 걸 확인할 수 있다. 물론 Android에서만 메시지가 정상적으로 수신되고, IOS는 아무 반응이 없다.

Android에서도 메시지가 오지 않았더라도 걱정 안하셔도 된다. 아직 우린 아무것도 설정한게 없기 때문에 오지 않을 수도 있다.

IOS

자 이제 많은 분들이 복잡하고 어려워하는 IOS 설정을 먼저 진행해보자. IOS에서는 APNs에 접속 가능한 인증서 또는 인증키가 필요하기에 발급 받아 Firebase에 등록을 해주어야 사용이 가능하다.

Apple Developer 계정이 없으면 진행이 불가능 하다.

Firebase FCM에서는 인증서와 인증키 2개의 방식을 모두 지원해 주지만, 권고 사항은 인증키 방식이다.
인증서는 1년 마다 갱신해 주어야하지만, 인증키는 갱신이 필요 없다.
여기서는 인증키 방식으로 진행하도록 하겠다.

애플 개발자 센터에 접속하여 로그인을 진행하면 아래 이미지와 같은 페이지가 보일 것인데, 여기서 인증서, 식별자 및 프로파일에서 아래 키를 클릭해 보자.

이제 키를 생성하도록 하자. 추가 버튼을 클릭하자.

키 생성시 해당하는 키로 APNs를 클릭하고 자유롭게 Key Name을 넣어준 뒤 계속 버튼을 클릭하자.

키가 정상적으로 생성이 되었고, 여기서 중요한 점이 Key ID를 꼭 기억해야 하고, 다운로드 버튼을 클릭하여 인증키를 다운 받아야 하는데, 인증키(p8) 다운로드는 딱 한번만 가능하기에 절대 잃어버리시면 안됩니다 !

Identifiers로 넘어와 식별자를 추가해보도록 하자.

App IDs를 선택하자.

App을 선택해주면 된다.

Description에 설명을 자유롭게 넣어주고, Bundle ID를 입력해 주면되는데, Bundle ID를 모르시면 XCode를 프로젝트 수준에서 접속하면 Bundle ID를 찾을 수 있다.

여기서 스크롤을 아래로 내려 Push Notifications을 선택해 주자. 계속을 눌러 식별자 등록을 마무리 하면 애플 개발자 센터에서 설정은 드디어 끝이났다.

이제 XCode를 열어주고, Signing & Capabilities 탭에서 Capability를 추가하도록 하자.

Push Notifications를 선택하여 추가해주자.

Background Modes에서 Background fetch / Reomote Notifications 부분을 모두 선택해 준다.

마지막으로 Firebase 설정을 진행하도록 하자.

Firebase 설정으로 들어와서 클라우드 메시징 탭을 클릭하여 위에서 발급 받은 인증키를 넣어주도록 하자.

인증키 업로드를 진행해 주면 되는데, 다운받은 인증키를 등록해주고 인증키 발급시 같이 발급 받은 키 ID를 넣어준다. 팀 ID도 넣어주어야 하는데, 팀 ID는 Apple Developer/Store Connect에서 확인 가능하다.

Android

안드로이드 설정을 진행하자. 안드로이드는 IOS에 비하면 너무 간편하게 설정이 가능하다.

Push 메시지의 중요도가 높다고 등록해 주어야 Push를 정상적으로 수신하는 것이 가능하다. 디바이스에서 푸시를 전송하는 우선순위가 있기 때문에 우선순위가 더 높은 서비스의 푸시를 우선적으로 전송하는 문제 때문에 아래 태그를 추가해주어야 한다.

추가하지 않는다고 해서 Push 메시지를 받지 못하는 것은 아닌데, 중요도가 낮기 때문에 높은 서비스에서 Push를 같이 전송하게 되면 받지 못할 수도 있다.

<meta-data
	 android:name="com.google.firebase.messaging.default_notification_channel_id"
	 android:value="high_importance_channel" />

위의 태그는 application 태그 안에 등록하셔야 합니다.

<application
        android:label="flutter_velog_sample"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:requestLegacyExternalStorage="true" 
        android:usesCleartextTraffic="true">

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="high_importance_channel" />
  
  		...
  		...

이번엔 Push 메시지를 클릭하여 앱에 진입할 때에 메시지 안에 담겨있는 정보를 받기 위해 추가하여야 하는 태그이다. 해당 태그는 반드시 추가햐셔야 합니다.

<intent-filter>
	<action android:name="FLUTTER_NOTIFICATION_CLICK" />
	<category android:name="android.intent.category.DEFAULT" />
</intent-filter>

최상단 activity안에 추가하시면 됩니다.

<activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"/>
          ...
		  ...
          <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
          </intent-filter>    
        </activity>

각 플랫폼 푸시 설정이 끝났지만, IOS, Android 13버전에서는 여전히 푸시 수신이 불가능 할 것이다. 권한과 관련된 문제이기에 Flutter에서 권한을 추가해 주면 된다.

Flutter

이제 FCM 사용을 위해서 Flutter 코드를 작성하면서 살펴보도록 하겠다.

먼저 Push를 수신 받는 환경에 대해서 알고 있어야 한다. App Life Cycle(생명주기)은 크게 세 가지의 상태가 있다. 앱이 실행 중인 상태와 앱을 백그라운드로 넘긴 상태, 그리고 앱을 완전히 종료한 상태이다.

Push 수신 상태에서는 각각 Foregroud/Backgroud/Terminate 상태라 말한다. 각 상태에 따라 푸시를 터치하여 앱으로 진입시 데이터를 수신받는 코드와 앱의 구조가 다르게 작동이 되는데, 하나씩 천천히 살펴보도록 하자.

앱의 파일 구조가 다르기에 각 프로젝트에 맞는 적절한 위치에서 수신을 하셔야 합니다. 보통은 앱의 시작점에서 받는 경우가 많고 저는 주로 상태관리 최상단에 Push/Deeplink 등의 알림 상태를 따로 관리하여 수신하고 있습니다.

Permission

먼저 Push 메시지 수신을 위한 권한을 받도록 하자. 권한은 Android 13버전 이하인 경우를 제외하고는 요청하여야 한다.
Andorid도 원래 Notification 관련 권한이 허용된 상태 였지만, 13버전 부터 권한을 요청해야 하는 상태로 변경되었다. IOS는 기존에도 Notification 권한 없이는 사용이 불가능 하다.

먼저 firebase_messaging 라이브러리에서 Permission을 지원하고 있어 해당 권한을 사용하여도 된다.

 FirebaseMessaging.instance.requestPermission(
                  badge: true,
                  alert: true,
                  sound: true,
                );

우리가 앱을 개발할 때 권한을 알림만 받을 것은 아니기에 permission_handler 라이브러리를 사용하여 요청 권한을 허용 받는 방법에 대해서도 살펴보자.

IOS

ios > Podfile로 이동하여 아래 코드를 추가한다. 이미 추가되있는 경우는 "PERMISSION_NOTIFICATIONS=1" 주석만 해제하여 사용하면 된다.

config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',

        ## dart: PermissionGroup.calendar
        # 'PERMISSION_EVENTS=1',

        ## dart: PermissionGroup.reminders
        # 'PERMISSION_REMINDERS=1',

        ## dart: PermissionGroup.contacts
        # 'PERMISSION_CONTACTS=1',

        ## dart: PermissionGroup.camera
        # 'PERMISSION_CAMERA=1',

        ## dart: PermissionGroup.microphone
        # 'PERMISSION_MICROPHONE=1',

        ## dart: PermissionGroup.speech
        # 'PERMISSION_SPEECH_RECOGNIZER=1',

        ## dart: PermissionGroup.photos
        'PERMISSION_PHOTOS=1',

        ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
        # 'PERMISSION_LOCATION=1',

        ## dart: PermissionGroup.notification
        # 'PERMISSION_NOTIFICATIONS=1',

        ## dart: PermissionGroup.mediaLibrary
        # 'PERMISSION_MEDIA_LIBRARY=1',

        ## dart: PermissionGroup.sensors
        # 'PERMISSION_SENSORS=1',   

        ## dart: PermissionGroup.bluetooth
        # 'PERMISSION_BLUETOOTH=1',

        ## dart: PermissionGroup.appTrackingTransparency
        # 'PERMISSION_APP_TRACKING_TRANSPARENCY=1',

        ## dart: PermissionGroup.criticalAlerts
        # 'PERMISSION_CRITICAL_ALERTS=1'
      ]

주석을 해제하자.

 ## dart: PermissionGroup.notification
         'PERMISSION_NOTIFICATIONS=1',

Android

android > app > src > main > AndroidManifest.xml 경로로 이동하면 상단에 디폴트로 등록된 user-permission이 있는데, 그 아래에 해당 태그를 추가해 주자.

<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>

권한을 요청하면 된다. 간단하다.

if (await Permission.notification.isDenied) {
	await Permission.notification.request();
}

Foground

앱 실행 중 환경에서 Push를 수신 받는 코드이다. Stream으로 데이터가 수신되며, Foreground 환경에서는 Push가 노출되지 않기에, flutter_local_notifications 라이브러리를 사용해서 Push를 로컬에서 노출시켜 주거나, 앱 자체에서 스낵바를 노출시키는 경우도 있다.

여기서는 FCM 사용 방법에 대해서 알아보고 있기에, 위에 공유한 로컬 푸시에 대해 작성한 내용을 참고하길 바란다.

FirebaseMessaging.onMessage.listen((RemoteMessage? message) {
      if (message != null) {
        if (message.notification != null) {
        	logger.e(message.notification!.title);
            logger.e(message.notification!.body);
            logger.e(message.data["click_action"]);
        }
      }
    });

Background

이번에는 Background 환경에서 푸시 메시지 데이터를 가져오는 코드이다. 앱의 시작점에서 코드를 넣어주면 된다.

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage? message) {
      if (message != null) {
        if (message.notification != null) {
            logger.e(message.notification!.title);
            logger.e(message.notification!.body);
            logger.e(message.data["click_action"]);
        }
      }
    });

Terminate

앱 종료 상태에서 푸시 터치시 데이터를 가져오는 방법이다.

FirebaseMessaging.instance
        .getInitialMessage()
        .then((RemoteMessage? message) {
      if (message != null) {
        if (message.notification != null) {
          	logger.e(message.notification!.title);
            logger.e(message.notification!.body);
            logger.e(message.data["click_action"]);
        }
      }
    });

Topic

이번에는 Topic에 대해서 알아보자. 토픽은 구독이라고 이해하면 쉽다. FCM Token은 변경 가능하고 만료 기간이 있다. Token 값을 서버에서 관리하고 있기에 Token을 통해서 관리하여도 되지만, SNS 프로덕트 개발 경험상 Topic을 주로 사용하였다.

서비스 전체 사용자에게 보내는 Push 또는 특정 사용자에게만 보내는 Push는 Token을 통해서 보내지만, 개인화 Push는 토픽을 사용해서 관리하는 편이 좋다.

토픽은 토큰이 없이 해당 토픽을 구독하는 사용자에게 보내는 Push 메시지인데, 아직은 어렵다고 생각할 수 있지만 구현은 간단하다. 물론 토픽을 설계하는 부분은 난이도가 좀 있는 작업이 될 것이다.

예를 들어보자 SNS 서비스에서 A가 B를 팔로우 했다고 가정하자. 이제 A는 B 게시물에 대한 구독이 생긴거다. 이럴 경우 B가 게시물을 올리거나 업데이트 할때마다 A의 토큰을 가져와 푸시를 전송할 것인가 ? 물론 이렇게 해도 된다. 하지만 토픽으로 관리하는게 더 좋은 방법이라고 생각한다.

B 게시물에 대한 토픽을 "feed_{B유저의 고유 ID}"이렇게 토픽을 만들어 놓으면, B를 팔로우하는 유저에게 생성한 토픽을 구독하게만 해주면 되고, B의 게시물이 업로드 될 때마다 해당 토픽으로 푸시를 전송하면 된다. 반대로 B를 언팔로우 하는 유저에게는 해당 토픽 구독을 취소만 해주면 되는 것이다.

이 부분은 여러 계정과 디바이스를 두고 테스트해보면 토큰으로 보내는 것보다 토픽으로 관리하는게 더 편하다는 것을 알 수 있을 것이다.

subscribe

FCM Topic을 구독하는 방법이다. 이게 끝이다. 해당 토픽으로 푸시를 전송해보면 정상적으로 수신 되는 것을 확인할 수 있다.

FirebaseMessaging.instance.subscribeToTopic("user_$uid");

unsubscribe

토픽 구독을 취소하고 싶을 때에 반드시 구독 취소를 진행하여야 한다. 취소를 해주지 않으면 푸시가 계속 전송되기 때문에 구독 취소를 잊어버리지 않아야 한다.

FirebaseMessaging.instance.unsubscribeFromTopic("user_$uid");

Notification Listener

이번에는 firebase_messaging 라이브러리에서 지원하는 푸시가 왔을 때 백그라운드에서 푸시 데이터를 수신하게 해주는 기능이다. 해당 기능은 익명함수로 등록하면 안되고, 최상위 탑 레벨에서 작동되어야 한다고 한다.

아래와 같이 사용하면 되고, Remote Push가 전송됬을 때에 앱의 아이콘 뱃지를 컨트롤 할 수 있고, 재정의 해서 로컬 푸시로 노출시켜도 된다.

Future<void> _onBackgroundMessage(RemoteMessage message) async {
  ...
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  FirebaseMessaging.onBackgroundMessage(_onBackgroundMessage);
  runApp(const App());
}

Send Message

Push를 전송하는 방법에 대해서 추가적으로 살펴보자. Firebase Messaging 대시보드를 통해서 전송할 수도 있고, API를 통해서 전송할 수 있다.

실질적으로 서비스하는 앱에서는 대체적으로 푸시 전송 서버를 따로 두고 서버에서 전송을 하기에 앱에서 전송을 하는 경우는 거의 없다.

그래도 방법은 공유하도록 하겠다.

Firebase

대시보드에서 푸시를 전송할 수 있는데, 위에서는 테스트 메시지까지만 보내봤지만, 다음을 클릭하여 타겟으로 넘어와 타겟을 설정하면 된다.

여기서 타겟에 해당하는 앱을 선택하고, 다음을 클릭하자.

예약 탭에서 맞춤 시간을 설정할 수 있다.

추가 옵션 부분에서 맞춤 데이터로 앱에 전달할 데이터를 key-value 타입으로 넣어줄 수 있고, 배지 수를 선택할 수 있다.

Android 경우에는 앱 뱃지 카운트를 시스템이 알아서 관리를 해주는데, IOS는 직접 관리하여야 한다.
검토를 클릭하고 전송을 보내보자.

HTTP v1

이번엔 API를 통해서 푸시를 전송하는 방법이다. 기존 HTTP 방식은 더 이상 지원하지 않고 v1 방법으로 진행하여야 한다.

조금 어려울 수 있으니 천천히 해보시길 바란다.

GCP (Google Cloud Platform)

먼저 GCP에서 Key를 발급받아야 한다. 설정에서 클라우드 메시징 탭으로 들어오자.
Firebase Cloud Messaging API(V1) 서비스 계정 관리를 클릭하면 GCP로 이동한다.

GCP로 이동해보면 Firebase Admin SDK가 보이는데, 아직 키 발급을 하지 않아서 아마 키 관련된 부분은 아무런 값도 없을 것이다.

클릭해서 들어와서 키 탭으로 이동한 다음 키 추가를 진행하자.

JSON을 선택하고 만들기를 누르면 키가 정상적으로 발급되는 것을 확인할 수 있다.

키가 저장된 다음 자동으로 컴퓨터에 저장을 한다.

이제 아래의 OAuth 2.0 Playground에 접속해보자. 여기서 accessToken을 발급받아야 한다.

OAuth 2.0 Playground

좌측에 있는 구글 API에서 Firebase Cloud Messaging API v1을 선택한 뒤 Authorize APIs를 클릭한다.

구글 계정에서 플레이 그라운드를 허용하면 되는데, 여기서 중요한 부분이 Firebase 구글 계정과 동일하여야 한다.

Exchange authorization code for tokens를 클릭하여 토큰을 발급받자.

정상적으로 발급이 되면 200 코드와 함께 아래 access_token이 나오는데, 해당 토큰 값을 복사해 주면 된다.

Flutter

이제 Flutter 또는 Postman을 통해서 푸시를 테스트해 볼 수 있다.

우선 body 부분에 token 또는 위에서 살펴본 topic 둘 중 하나로 전송을 할 수 있으며, android/ios에 맞는 payload를 넣어줄 수 있다.

IOS는 "content-available": 1 반드시 포함되어 있어야 백그라운드에서 푸시가 전송이 된다.

Future<String?> _postMessage(String fcmToken) async {
    try {
      String _accessToken = {your_access_token};
      http.Response _response = await http.post(
          Uri.parse(
            "https://fcm.googleapis.com/v1/projects/{your_project_id}/messages:send",
          ),
          headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer $_accessToken',
          },
          body: json.encode({
            "message": {
              "token": fcmToken,
             // "topic": "user_uid",

              "notification": {
                "title": "FCM Test Title",
                "body": "FCM Test Body",
              },
              "data": {
                "click_action": "FCM Test Click Action",
              },
              "android": {
                "notification": {
                  "click_action": "Android Click Action",
                }
              },
              "apns": {
                "payload": {
                  "aps": {
                    "category": "Message Category",
                    "content-available": 1
                  }
                }
              }
            }
          }));
      if (_response.statusCode == 200) {
        return null;
      } else {
        return "Faliure";
      }
    } on HttpException catch (error) {
      return error.message;
    }
  }

Firebase에서 project_id를 얻는 위치입니다.

사용량

Firebase Messaging에서 사용량을 확인할 수 있다. 보고서 탭으로 이동하면 된다.

전송 : 사용자에게 전송된 알림 및 데이터 메시지의 개수입니다
수신됨 : 사용자가 수신한 알림/데이터 메시지의 개수입니다(Android에서만 지원 및 Apple은 부분적으로 지원)
노출 : 사용자에게 표시된 알림 메시지의 개수이며 Android에만 제공됩니다
열림 : 사용자가 연 알림 메시지의 개수입니다

마무리

FCM 사용을 위한 Android / IOS 설정 부터 사용 방법 및 테스트할 수 있는 방법까지 알아보았다. 혹시 아직 FCM을 사용해본 적이 없으시다면 꼭 한 번 해보시길 바란다. FCM을 사용하지 않는 서비스는 없기 때문에 직접 구현해서 여러가지 테스트를 해보시길 추천합니다.

혹시라도 안되시는 부분 있다면 댓글 남겨주세요

profile
Flutter Developer

24개의 댓글

comment-user-thumbnail
2023년 9월 27일

안녕하세요 좋은 글 잘 보고 연동 중 입니다. 토큰이 1시간이 제한 이던데 이 부분은 어떻게 할 수가 없는건가요?
개발환경은 flutter입니다.

1개의 답글
comment-user-thumbnail
2023년 10월 13일

안녕하세요, 남겨주신 좋은 글 보고 Flutter 및 FCM으로 푸시알람까지는 성공했습니다.
OAuth 2.0 Playground로 accessToken을 생성하면, 약 1시간 뒤에 토큰이 만료됩니다.
이를 주기적으로 갱신할 방법을 찾아보던 중, 클라이언트의 사용자 자격 인증을 통해 갱신하는 방법과 FirebaseAdmin SDK를 통해 갱신하는 방법을 찾았습니다.
하지만 클라이언트의 사용자 자격 인증은 Google 로그인 등의 OAuth를 이미 사용하는 어플에 한하여 자격증명이 완료되고, Request할 수 있다는 것을 알았습니다.
제 어플은 간단히 이메일 로그인만으로 FirebaseAuthentication에 등록되어 사용하는 어플인데, 이로 자격 증명은 혹시 할 수 없을까요?
만약 위 방법으로 자격 증명이 안 된다면, 서버를 구축하여 서버 자체에서 주기적으로 갱신해주어야하는데, 해당 방법은 전혀 감히 잡히질 않아서 도움을 부탁드리고싶습니다..!

1개의 답글
comment-user-thumbnail
2024년 2월 29일

안녕하세요 위에 내용 잘 따라하여 v1 방식으로 메시지 보내기는 성공했습니다.
그런데 oauth access token 갱신을 위해 refresh를 시도해봤지만 계속해서 invalid_client Unauthorized 에러를 겪고 있습니다. 플러터에서 http 통신을 통해 access token 갱신을 할 수는 없는건가요?
POST 방식으로 "https://oauth2.googleapis.com/token"에 헤더는 'Content-Type': 'application/x-www-form-urlencoded'를 추가하고
바디는 refresh token과 client_id, client_secret, grant_type을 json 방식 없이 사용 중입니다.
client_id와 secret이 google iam 및 관리자의 서비스 계정에 있는 oauth ID와 키를 사용하는게 아닌지 궁금하네요...

2개의 답글
comment-user-thumbnail
2024년 3월 10일

안녕하세요. 글 잘 읽었습니다. 감사합니다.
글을 읽고 background, terminate 상태에서 특정 상대에게 Push를 성공하였습니다.
이해가 가지 않는게 많아서 답답한 마음에 글을 남깁니다.

첫째로, HTTP v1 섹션의 "클릭해서 들어와서 키 탭으로 이동한 다음 키 추가를 진행하자." 이 부분입니다!
해당 키가 어디서 사용되는지 아직 모르겠습니다ㅠㅠ

둘째로, https://console.cloud.google.com/apis/credentials?project={project_id} 에서 새로운 IOS OAuth 2.0 Client IDs가 생겼습니다. 어떤 부분에서 생겼는지 몰라 다시 처음부터 해보았는데 안생기는것을 확인하였습니다. 해당 블로그를 따라하다가 생겼다고 생각했는데 맞나요?

셋째로, oauth 2.0 access token 을 재발급 받고 싶어서 알아본 결과, 만료되기 직전 또는 만료되고 난 후에 새로운 요청(refresh token)을 해 새로운 토큰을 발급받으라는 내용이 있었습니다.
대략적인 header 와 body 는 이렇습니다.
headers: {
'Content-Type': 'application/json',
},
body: {
'grant_type': 'refresh_token',
'refresh_token': 'REFRESH_TOKEN_VALUE',
'client_id': 'YOUR_CLIENT_ID',
'client_secret': 'YOUR_CLIENT_SECRET',
},

하지만 여기서 client_id 와 client_secret 이 감이 잡히질 않습니다...
어떤 client_id 인지, client_id 가 한두개가 아니라 아직 계속 정보를 찾아보고 있습니다.
또한, client_secret 의 경우 처음에 한번만 볼 수(또는 다운) 있다 라고 보았는데 OAuth client ID 를 새로 만들어도 파일에는 client_secret 이 들어있지 않아서 계속 헤매고 있습니다.

도움좀 주실 수 있나요?
감사합니다.

1개의 답글
comment-user-thumbnail
2024년 6월 27일

좋은 글 감사합니다. FCM 구현하는데 많은 도움이 되었습니다 :)
궁금한 점이 있어서 질문을 올립니다.
[상황]
같은 Firebase 프로젝트를 사용하는 App1, App2 가 있습니다.
이때 App1 과 App2는 같은 사용자 정보를 갖습니다.
이때 같은 계정 및 기기에 로그인을 했다면, 특정 이벤트에 대해 같은 FCM 메시지가 나타나게 될 것으로 예상이 됩니다. 이때 Firebase 프로젝트를 생성하지 않고, FirebaseMessaging.instance.subscribeToTopic 을 이용하여 각각의 앱에 대한 FCM 메시지를 사용자에게 선택적으로 보낼 수 있을까요?
다른 좋은 방법이 있는지도 궁금합니다.
좋은글 감사합니다.

2개의 답글
comment-user-thumbnail
2024년 7월 19일

안녕하세요. 다들 다 성공하시는데, 저는 실패하네요....
저는 flutter web push 해보려하는데요.
firebase 홈페이지에서 메시지 알림 테스트는 성공하는데,
google oauth 2.0 playground에서 400 에러가 발생하는데 이유를 모르겠네요. ㅠㅠ

1개의 답글
comment-user-thumbnail
2024년 10월 7일

안녕하세요 덕분에 너무 좋은 글 참고했습니다! 감사드립니다.
토픽 관련하여 설정하다가 궁금한 게 있어 질문 드립니다 ㅠㅠ

  1. 로그인, 로그아웃 될 때 토픽 관련 처리는 클라이언트(플러터)에서 어떻게 하시나요?
    로그인하면 서버에 저장해둔 토픽 가져와서 Subscribe, 로그아웃하면서 토픽 Unsubscribe로 해뒀는데 토픽이 여러 개일 수 있다 보니 그 과정의 로딩이 오래 걸리더라구요 ..

  2. 토큰만 삭제하면 로그아웃도 금방 되고 푸시가 안오긴 하는데 문제는 같은 디바이스에서 다른 B계정으로 로그인 시 이전의 A계정 토픽을 그대로 이어받아서 문제가 되어 1번을 차용했으나 로직이 오래 걸리는 문제를 가지고 있습니다. ㅠㅠ (멀티쓰레드로 구독 해제를 고민하긴 했는데 이게 맞나 싶습니다..)

물어 볼 주변 사람도 없고 검색해도 잘 안 나와서 ㅠ
혹시나 클라이언트에서 이 부분을 어떻게 처리하는지 여쭙고 싶어 글 남깁니다... 감사합니다!

1개의 답글