본문 바로가기
React Native

[React Native] Expo Push Notification

by dev수니 2024. 9. 20.
반응형

** 모든 과정은 google play console 과 apple developer 결제 완료 및 project 등록 후 진행한 내용입니다. 

개요

기기 정보와 Firebase Cloud Messaging(FCM) 또는 Apple Push Notification Service(APNs)와의 통신에 대한 모든 것이 백그라운드에서 처리된다.

먼저, 내 기기에서 backend 서버로 알림 요청을 보내면 expo push token 이용하여 Expo backend로 푸시알림을 받는다.

android는 Firebase Cloud Messaging(FCM) ios는 Apple Push Notification Service(APNs)이용하여 알림 전송한다.

 

설정 과정

https://docs.expo.dev/push-notifications/push-notifications-setup/

프론트엔드

  1. 라이브러리 설치
  2. 알림을 처리하는 함수를 구현
  3. Android 및 iOS에 대한 자격 증명을 설정하여 앱을 구성
  4. expo dev 통해서 테스트

1. 라이브러리 설치

$ npx expo install expo-notifications expo-device expo-constants

 

expo-notifications

  • 라이브러리는 사용자의 권한을 요청하고 ExpoPushToken을 가져오는 데 사용. Android 에뮬레이터나 iOS 시뮬레이터에서는 지원되지 않음.

expo-device

  • 앱이 물리적 장치에서 실행되고 있는지 확인하는 데 사용

expo-constants

  • projectId앱 구성에서 값을 가져오는 데 사용

 

2. 함수 구현

import { useState, useEffect, useRef } from 'react';
import { Text, View, Button, Platform } from 'react-native';
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';

// Notification initialize
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

// send 하는 함수
async function sendPushNotification(expoPushToken: string) {
  const message = {
    to: expoPushToken,
    sound: 'default',
    title: 'Original Title',
    body: 'And here is the body!',
    data: { someData: 'goes here' },
  };

  await fetch('https://exp.host/--/api/v2/push/send', {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Accept-encoding': 'gzip, deflate',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(message),
  });
}

function handleRegistrationError(errorMessage: string) {
  alert(errorMessage);
  throw new Error(errorMessage);
}

async function registerForPushNotificationsAsync() {
  if (Platform.OS === 'android') {
    Notifications.setNotificationChannelAsync('default', {
      name: 'default',
      importance: Notifications.AndroidImportance.MAX,
      vibrationPattern: [0, 250, 250, 250],
      lightColor: '#FF231F7C',
    });
  }

  if (Device.isDevice) {
    const { status: existingStatus } = await Notifications.getPermissionsAsync();
    let finalStatus = existingStatus;
    if (existingStatus !== 'granted') {
      const { status } = await Notifications.requestPermissionsAsync();
      finalStatus = status;
    }
    if (finalStatus !== 'granted') {
      handleRegistrationError('Permission not granted to get push token for push notification!');
      return;
    }
    const projectId =
      Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
    if (!projectId) {
      handleRegistrationError('Project ID not found');
    }
    try {
      const pushTokenString = (
        await Notifications.getExpoPushTokenAsync({
          projectId,
        })
      ).data;
      console.log(pushTokenString);
      return pushTokenString;
    } catch (e: unknown) {
      handleRegistrationError(`${e}`);
    }
  } else {
    handleRegistrationError('Must use physical device for push notifications');
  }
}

export default function App() {
  const [expoPushToken, setExpoPushToken] = useState('');
  const [notification, setNotification] = useState<Notifications.Notification | undefined>(
    undefined
  );
  const notificationListener = useRef<Notifications.Subscription>();
  const responseListener = useRef<Notifications.Subscription>();

  useEffect(() => {
    registerForPushNotificationsAsync()
      .then(token => setExpoPushToken(token ?? ''))
      .catch((error: any) => setExpoPushToken(`${error}`));

    notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
      setNotification(notification);
    });

    responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
      console.log(response);
    });

    return () => {
      notificationListener.current &&
        Notifications.removeNotificationSubscription(notificationListener.current);
      responseListener.current &&
        Notifications.removeNotificationSubscription(responseListener.current);
    };
  }, []);

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'space-around' }}>
      <Text>Your Expo push token: {expoPushToken}</Text>
      <View style={{ alignItems: 'center', justifyContent: 'center' }}>
        <Text>Title: {notification && notification.request.content.title} </Text>
        <Text>Body: {notification && notification.request.content.body}</Text>
        <Text>Data: {notification && JSON.stringify(notification.request.content.data)}</Text>
      </View>
      <Button
        title="Press to Send Notification"
        onPress={async () => {
          await sendPushNotification(expoPushToken);
        }}
      />
    </View>
  );
}

3. OS 별 자격 증명 설정

Android

https://docs.expo.dev/push-notifications/fcm-credentials/

  1. Firebase console > Project settings > Service accounts
  2. firbase admin SDK > new key 생성 > download .json file
  3. Upload the JSON file to EAS and configure it for sending Android notifications. This can be done using EAS CLI or in Expo dashboard.
  4. 두가지 방법 중 필자는 cli를 활용하는 방법 채택, 해당 파일을 root directory 에 옮긴 뒤 아래 순서로 실행
    • Run eas credentials
    • Select Android > production > Google Service Account
    • Select Manage your Google Service Account Key for Push Notifications (FCM V1)
    • Select Set up a Google Service Account Key for Push Notifications (FCM V1) > Upload a new service account key
    • If you've previously stored the JSON file in your project directory, the EAS CLI will automatically detect the file and prompt you to select it. Press  to continue. → Y
  5. google-services.json file in your project. Download it from the Firebase Console and place it at the root of your project directory.
  6. In app.json, add expo.android.googleServicesFile with its value as the path of the google-services.json.
{
  "expo": {
    ...
    "android": {
      ... "googleServicesFile": "./path/to/google-services.json"
    }
  }
}

 

iOS

iOS의 경우, eas build 로 서비스키를 생성할 수 있다.

처음으로 개발 빌드를 만들면 푸시 알림을 활성화하라는 메시지가 표시된다. 그러면 EAS CLI에서 다음 질문에 y 로 선택한다.

  • Setup Push Notifications for your project
  • Generating a new Apple Push Notifications service key

 

 

다음에는 백엔드에서 expo push 이용하여 알림 보내는 방법에 대해 포스팅해보겠다.

반응형

댓글