> For the complete documentation index, see [llms.txt](https://document.wisetracker.co.kr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://document.wisetracker.co.kr/v2-developer/push/undefined/react-native/push_message.md).

# ReactNative 푸시메세지 설정

### 푸시알림 권한 확인 <a href="#reactnative_permission" id="reactnative_permission"></a>

사용자의 푸시알림 권한에 대한 확인을 거친 후 사용자의 푸시토큰을 수집 합니다.

아래의 예제는 사용자의 푸시알림 권한을 확인하는 방법으로 안드로이드의 경우 내장된 react-native PermissionAndroid를 사용하였으며, ios의 경우 React Native Firebase iOS permission API를 사용하였습니다. &#x20;

{% hint style="danger" %}
푸시알림 권한 확인 절차에 대한 예제일 뿐, <mark style="color:red;">**앱의 특성이나 상황에 따라 권한을 확인 및 요청하는 위치는 달라질 수 있습니다.**</mark>&#x20;

예제에서 사용한 권한 확인 방식은 다음과 같으며, 자세한 내용은 사용된 API의 도큐먼트를 확인 해 주세요.

* android : react-native PermissionAndroid API 사용
* ios의 경우 React Native Firebase iOS permission API 사용
  {% endhint %}

> ```
> iOS permission 요청시 확인되는 authorizationStatus 값.
> -1 = NOT_DETERMINED: 애플리케이션에 대한 권한이 아직 요청되지 않았습니다
> 0  = DENIED: 사용자가 알림 권한을 거부했습니다
> 1  = AUTHORIZED: 사용자가 권한을 수락했고 활성화되었습니다.
> 2  = PROVISIONAL: 임시 권한이 부여되었습니다.
> 3  = EPHEMERAL: 앱이 제한된 시간 동안 알림을 만들 수 있는 권한이 있습니다. 앱 클립에 사용됩니다.
> ```

{% tabs %}
{% tab title="Notification permission Check 예제" %}

```tsx
import messaging from '@react-native-firebase/messaging';
import {Platform, NativeModules, PermissionsAndroid} from 'react-native';

const Main = () => {
const firebaseMessaging = messaging();

 useEffect(() => {
    Platform.OS === 'android'
      ? androidRequestPermission()
      : iosRequestPermission();
  }, []);
  
  // ios 사용자에게 알림권한 요청
  const iosRequestPermission = async () => {
    try {
      const authorizationStatus = await messaging().requestPermission();
      // 알림 권한이 허용되면 authorizationStatus 값에 대한 안내는 상단에 작성되어 있습니다.
      // authorizationStatus 값이 AUTHORIZED 일 때, 
      if (authorizationStatus === 1) {
        const apnsToken = await firebaseMessaging.getAPNSToken();
        // APNs 토큰이 등록되어 있지 않으면 getToken() 함수가 실패합니다.
        // FCM토큰을 가져오기 전에 APNs 토큰이 등록되어있는지 먼저 확인합니다.
        if (apnsToken) {
          const fcmToken = await firebaseMessaging.getToken();
          // 와이즈트래커 SDK가 토큰을 수집합니다.
          NativeModules.DotReactBridge.setPushToken(fcmToken);
        }
      } else {
        console.log('알림권한 비 활성화:');
      }
    } catch (error) {
      console.log('ios error::', error);
    }
  };

  // Android 사용자에게 알림권한 요청
  const androidRequestPermission = async () => {
    const authorizationStatus = await messaging().requestPermission();
    console.log('authorizationStatus:', authorizationStatus);
    try {
      const fcmToken = await firebaseMessaging.getToken();
      if (Platform.OS === 'android') {
        console.log('get android FCM Token:', fcmToken);
        if (Platform.Version >= 33) {
          const granted = await PermissionsAndroid.request(
            PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS,
            /*
             * 알림허용이 denied 일때, 알림 허용에 대한 재안내와 
             * 알림수신에 대한 요청을 다시 할 수 있는 내용 작성가능.
             * */
          );
          if (granted === PermissionsAndroid.RESULTS.GRANTED) {
            console.log('Android 13이상 , 알림권한 허용.');
            if (fcmToken) {
              //토큰 수집
              NativeModules.DotReactBridge.setPushToken(fcmToken);
            }
          }
        }
        // API 레벨 32 이하일 때
        try {
          if (fcmToken) {
            //토큰 수집
            NativeModules.DotReactBridge.setPushToken(fcmToken);
          }
        } catch (e) {
          console.log('android token API level 32 이하 error:', e);
        }
      }
    } catch (error) {
      console.log('Android error:', error);
    }
  };
...
}
```

{% endtab %}
{% endtabs %}

### Device Token 수집 <a href="#reactnative_get_token_" id="reactnative_get_token_"></a>

알림 권한 허용에 대한 확인 여부를 진행했다면, 사용자의 푸시토큰을 수집해야 합니다.

OS 모두 Firebase messaging 서비스를 기반으로 동작하기 때문에, **`getToken`** 호출을 통해 Token을 확인할 수 있습니다. 로그를 통해 수집된 token이 확인된다면, `setPushToken` 호출을 통해 와이즈트래커 SDK가 토큰을 수집할 수 있도록 코드를 추가 해 주세요.

{% tabs %}
{% tab title="푸시토큰 수집 예제" %}

<pre class="language-jsx"><code class="lang-jsx">import messaging from '@react-native-firebase/messaging';
import {Platform, NativeModules, PermissionsAndroid} from 'react-native';

const Main = () => {
const firebaseMessaging = messaging();

if (Platform.OS === 'android') {
  const fcmToken = await firebaseMessaging.getToken();
     // 와이즈트래커 SDK가 토큰을 수집합니다.
     NativeModules.DotReactBridge.setPushToken(fcmToken);
} else {
 // iOS의 경우 APNs 토큰이 등록되어 있지 않으면 getToken() 함수가 실패합니다.
 // FCM토큰을 가져오기 전에 APNs 토큰이 등록되어있는지 먼저 확인합니다.
<strong>  const apnsToken = await firebaseMessaging.getAPNSToken();
</strong>   if (apnsToken) {
      const fcmToken = await firebaseMessaging.getToken();
      // 와이즈트래커 SDK가 토큰을 수집합니다.
      NativeModules.DotReactBridge.setPushToken(fcmToken);
    }      
};
</code></pre>

{% endtab %}
{% endtabs %}

### 푸시메시지 클릭 측정 <a href="#rn_push_appstatus" id="rn_push_appstatus"></a>

앱의 상태는 총 3가지로 나눌 수 있습니다.&#x20;

* <mark style="color:red;">**Foreground**</mark> 상태 :  앱이 켜져있고, 앱을 사용하고 있는 상태 > 이벤트 핸들러의 `onMessage`를 이용해 핸들링 할 수 있습니다.
* <mark style="color:red;">**Background**</mark> : Background는 앱이 꺼져있거나, 홈버튼을 눌러 앱을 빠져나온 경우입니다 >  이벤트 핸들러의 `setBackgroundMessageHandler`를 이용할 수 있습니다.
* <mark style="color:red;">**Quit**</mark> :  Quit는 앱이 종료된 상태를 나타냅니다 > Background와 동일하게 이벤트 핸들러의 `setBackgroundMessageHandler`를 이용할 수 있습니다.

앱의 상태에 따라, 발송된 푸시메세지가 도착하여 <mark style="background-color:green;">유저가 메세지를 클릭하는 것을 측정</mark>하기 위해서 <mark style="color:red;">**앱에 진입하는 시점**</mark>에`"NativeModules.`<mark style="color:blue;">`DotReactBridge.setPushClick`</mark>`"` 을 호출하는 로직을 작성해야 합니다.

유의 해 주셔야 할점은 앱이 Foreground 상태일때 알림메시지 수신에 대한 구현 방식에 따라서, 유저가 Foreground 상태에서 알림을 받아 , 해당 알림을 클릭한 시점에 setPushClick을 호출해주셔야 한다는 점 입니다.&#x20;

만약 Foreground 상태일때 알림메세지에 대한 구현부가 없으나,  `NativeModules.DotReactBridge.setPushClick` 을 호출한다면, 아래의 이미지 처럼 유저가 알림을 클릭하지 않았음에도, 대시보드에서 다이렉트 오픈이 카운팅될 수 있습니다.&#x20;

<figure><img src="/files/ETCejFWxO4xz7q6G0OzE" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}
와이즈트래커 대시보드에서 푸시메세지 테스트 발송시와 Firebase 콘솔에서 푸시 메세지 테스트 발송시 확인되는 메세지에는 다른점이 있습니다. 와이즈트래커 대시보드에서 메시지 발송시에는<mark style="color:red;">`'RW_push_payload_WP'`</mark>객체 확인이 가능하나, Firebase 콘솔에서 메시지 발송 테스트 시에는  <mark style="color:red;">`RW_push_payload_WP`</mark> 객체정보는 확인되지 않습니다.&#x20;

(아래에서 예제 확인 해 주세요)

<mark style="color:red;">`'RW_push_payload_WP'`</mark> 객체가 들어있는 정보만 setPushClick을 통해 전달하며, JsonString의 parsing을 통해 Direct오픈 여부등을 체크하기에, 다음과 같이 대시보드에서 발송시에만 setPushClick함수가 호출될 수 있도록 제어 해 주세요.
{% endhint %}

<details>

<summary><mark style="color:blue;">와이즈트래커 대시보드 발송과 Firebase console 에서 발송되는 메시지 payload 비교</mark></summary>

```
1. 와이즈트래커 대시보드에서 메시지 전송시 수신되는 remoteMessage 원본:  
{
   "data":{
      "RW_push_payload_WP":
      "{\"RW_push_payload_CK\":\"0000\",\"RW_push_payload_SK\":\"00000000\",
         \"RW_push_payload_TT\":\"ios test\",\"RW_push_payload_EXPIRED\":\"1672498800000\",
         \"RW_push_payload_PR\":\"7\",\"RW_push_payload_BD\":\"ios test\"
      }"
   },
   "from":"0000000000000",
   "messageId":"0000000000000000",
   "notification":{
      "body":"ios test",
      "title":"ios test"
   }
}

2. firebase console 발송 테스트시 수신되는 remoteMessage 원본 : 
{
   "data":{},
   "from":"0000000000000",
   "messageId":"0000000000000000",
   "mutableContent":true,
   "notification":{
      "body":"fcm test",
      "title":"fcm test"
   },
   "sentTime":"0000000000"
}
```

</details>

앱 진입시점은 앱마다 다를 수 있으며 아래의 예제는 App.js 를 진입시점으로 예제가 작성되었습니다.

{% tabs %}
{% tab title="App.js(Function component)" %}

```tsx
import React, {useEffect} from 'react';
import messaging from '@react-native-firebase/messaging';
import {NativeModules} from 'react-native';

const App = () => {
  ...
  // 포그라운드 상태에서 FCM 메시지를 받았을 때
  useEffect(() => {
    const foregroundMessage = messaging().onMessage(async remoteMessage => {
      // 메시지를 처리하는 로직은 필요에따라 별도 구현 해 주세요.
      // 별도 구현 후 대시보드에서 유저가 알림을 클릭하여 캠페인 정보를 
      // 확인하고자 할때 DotReactBridge의 setPushClick함수를 호출합니다.
      if (JSON.stringify(remoteMessage).includes('RW_push_payload_WP')) {
        NativeModules.DotReactBridge.setPushClick(remoteMessage.data["RW_push_payload_WP"]);
      }
    });
    return foregroundMessage;
  }, []);
  
  useEffect(() => {
    //사용자가 FCM을 통해 표시된 알림을 누르면 앱이 백그라운드 상태에서 열린 경우 호출
    const backgroundMessage = messaging().onNotificationOpenedApp(
      remoteMessage => {
        // 메시지를 처리하는 로직은 필요에따라 별도 구현 해 주세요.
        // 와이즈트래커 SDK와 통신하여 푸시메세지 클릭을 처리.
        if (JSON.stringify(remoteMessage).includes('RW_push_payload_WP')) {
          // NativeModules.DotReactBridge.setPushClick(remoteMessage.data.RW_push_payload_WP);
          NativeModules.DotReactBridge.setPushClick(remoteMessage.data["RW_push_payload_WP"]);
        }
      },
    );

    /* Android의 경우 사용자가 FCM을 통해 표시된 알림을 앱이 종료된 상태에서 알림을 클릭한 경우
    앱이 처음 시작될 때 실행됩니다. 메시지가 없으면 null을 반환합니다.*/
    messaging()
      .getInitialNotification()
      .then(remoteMessage => {
        if (remoteMessage) {
          console.log('앱이 종료 상태에서 알림클릭으로 앱이 오픈되었을때:', remoteMessage);
          // 메시지를 처리하는 로직은 필요에따라 별도 구현 해 주세요.
          // 와이즈트래커 SDK와 통신하여 푸시메세지 클릭을 처리.
          if (JSON.stringify(remoteMessage).includes('RW_push_payload_WP')) {
            NativeModules.DotReactBridge.setPushClick(remoteMessage.data["RW_push_payload_WP"]);
          }
        }
      });
    return backgroundMessage;
  },[]);
  ...
  ...
};
```

{% endtab %}
{% endtabs %}

### 푸시 수신동의

푸시발송은 기본 적용에서는 "수신거부"입니다. 아래 링크를 참조하여 화면에서 수신동의/거부를 진행 후 해당 데이터를 "태깅"작업을 통해 남겨주세요.

{% embed url="<https://document.wisetracker.co.kr/v2-developer/in-app-event/event-list/messaging#push_noti_authorized>" %}

### 🎉 축하합니다!

ReactNative 앱의 푸시메세지 발송을 위한 모든 준비가 끝났습니다!&#x20;

푸시메세지 발송 테스트를 통해 메시지 수신이 잘 이루어지는지 체크 해 주세요!

{% embed url="<https://document.wisetracker.co.kr/marketing-action/marketing-message>" %}
푸시메세지 테스트 방법
{% endembed %}
