supergravity

expo push notification 푸시 알림 구현 본문

개발중 기억해야 할만한 것들/엑스포, 리액트 네이티브

expo push notification 푸시 알림 구현

supergravity 2021. 3. 8. 17:54

시작

 

지금 운영하고 있는 앱에서 수익을 창출하기 위해여 1주일에 1번씩 상품을 팔기로 했다. 

1주일에 1번씩 상품을 팔 기 위해서는 푸시 알림이 필수 인것 같다. 

그래서 푸쉬알림을 구현하려 한다. 

 

푸시 알림

 

푸시 알림은 거의 모든 앱에서 사용을 하고 있다.

특히 상품을 정해진 시간에만 판매를 하는 경우에는 무조건(?)적으로 필요한 기능이다.

엑스포에서는 귀찮은 코딩을 최대한 제한하려고 노력을 한 것 같다.

그래서 쉽게 구현이 가능하다. 

안드로이드의 경우 FCM(Firebase Cloud Messaging)을 이용한다고 한다.

 

구현

 

구현은 3가지 단계로 나누어진다. 

 

SetUp: 클라이언트 유저의 엑스포-푸시-토큰을 얻기

Sending :  내가 알림을 하고 싶은 내용과 유저의 토큰을 이용하여 엑스포-푸시-API 함수를 사용하기

Receiving: 앱의 알림에 응답하기( 알림을 클릭했을 때 특정 스크린으로 이동하는 것? )

 

플러스 알파로 Firebase Cloud Messaging 서버 연결해주기(5분이면 된다)

 

자그럼! 위의 3단계를 차분히 클리어해보자. 

 

SetUp

 

클라이언트(앱 사용자) 쪽의 준비를 하기 위해서는 2가지의 중요한 일을 해야 한다. 

 

1. 푸시 알림을 하기 위한 유저의 Permission

2. 유저의 ExpoPushToken ( 엑스포 토큰은 주소이다. 만약 푸시 알림이 메일이면 엑스포 토큰은 유저의 이메일 주소로 생각할 수 있다)

 

NOTE : ExpoPushToken으로 생성된 토큰의 경우 디바이스의 앱당 하나씩 생성이 된다. 만약 앱을 삭제를 하게 된다면 토큰 역시 같이 없어진다. 그렇기 때문에 redux persistens를 이용하여 생성된 토큰을 저장하고 관리하면 편리하다. 

 

두 가지의 SetUp은 expo-notifications 라이브러리로 쉽게 할 수 있다. 

permission의 경우 requestPermissionsAsync를 사용을 할 것이고

ExpoPushToken의 경우는 getExpoPushTokenAsync를 사용할 것이다.

 

registerForPushNotificationsAsync = async () => {
  #Block_1
  if (Constants.isDevice) {
    const { status: existingStatus } = await Notifications.getPermissionsAsync();
    let finalStatus = existingStatus;
    if (existingStatus !== 'granted') {
      const { status } = await Notifications.requestPermissionsAsync();
      finalStatus = status;
    }
    if (finalStatus !== 'granted') {
      alert('Failed to get push token for push notification!');
      return;
    }
    const token = (await Notifications.getExpoPushTokenAsync()).data;
    console.log(token);
    this.setState({ expoPushToken: token });
  } 
  
  
  else {
    alert('Must use physical device for Push Notifications');
  }
  
  
  #Block_2
  if (Platform.OS === 'android') {
    Notifications.setNotificationChannelAsync('default', {
      name: 'default',
      importance: Notifications.AndroidImportance.MAX,
      vibrationPattern: [0, 250, 250, 250],
      lightColor: '#FF231F7C',
    });
  }
  };

 

위의 코드를 천천히 살펴보자.  2가지의 비동기 함수가 있다.

Notifications.getPermissionsAsync와 Notifications.getExpoPushTokenAsync이다.

먼저 Notifications.getPermissionsAsync를 이용하여 현재 permission상태를 받아온다.

그리고 granted(사용자가 허용을 한상태 )가 아니면 permission요청을 한다. 

permission요청이 완료되면  Notifications.getExpoPushTokenAsync을 이용해서 토큰을 생성한다. 

 

NOTE : 토큰은 실제 기기에서 만 생성되는 것 같다. 안드로이드 스튜디오의 가상 환경을 이용했는데 잘 안된다(?)

 

마자막으로 디바이스의 플랫폼을 확인하고 안드로이드면 Notications.setNotificationsChannelAsync함수를 이용하여 채널설정을 마친다. 

 

 

Firebase cloud messaging 설정

 

Firebase cloud messaging(FCM)은 안드로 이용이다. IOS에서는 다른 방식으로 구성해주어야 한다. 

Firebase Console

접속 후 프로젝트를 만들고 나의 클라이언트와 연결시켜 주어야 한다. 

google-services.json파일을 다운로드 후 프로젝트의 Root폴더에 넣고 app.json파일에 아래의 코드처럼 추가를

하면 된다. 참쉽닿!

{
  ...
  "android": {
    "googleServicesFile": "./google-services.json",
    ...
  }
}

 

NOTE : 참고로 공식문서를 읽다 보면 credentials라는 용어가 지속적으로 등장한다. 

 

생성한 firebase프로젝트에서 클라우드 메시지 키를 복사해야 한다. 

 

위의 이미지에 나와있는 톱니바퀴를 누르고 프로젝트 설정으로  들어가자.

그럼 클라이드 메시지 탭이 보일 것이다. 클라우드 메시지 탭을 누루고 토큰을 복사하자

 

그리고 나서 아래의 두 명령어를 터미널에 입력하자
expo install expo-notifications
expo push:android:upload --api-key <너의토큰>

위의 설치와 설정이 끝나면 아래의 코드와 같이 app.json을 수정해주자
{
  "expo": {
    ...
    "android": {
      ...
      "useNextNotificationsApi": true,
    }
  }
}

Sending

사용자에 저장된 토큰을(주소)를 이용하여 push알람을 보낼 수 있다. 아래의 그림을 보면 쉽게 이해가 가능할 것이다. 

그러면 Sending 하는 과정을 상세히 살펴보자. 

1. 먼저 사용자가 사용하는 디바이스(핸드폰)에 토큰(주소)을 생성하는 코드를 구현한다. 그리고 내가 개인적으로 가지고 있는

서버에 토큰 정보를 전송한다(POST형식으로 전송). 

2. 개인 서버에서는 전송된 토큰을 저장한다. 저장된 토큰을 EXPO 서버에 보낼 메시지와 데이터를 함께 전송한다.

3. 엑스포 서버는 전송받은 토큰과 데이터를 구글 파이어 베이스 서버로 전송한다. 

 

NOTE : 2번 과정에서 엑스포 서버가 데이터를 잘 받았는지를 나타내는 데이터를 전송한다. 데이터는 PUSH TICKETS라고 정의되어 있고 JSON형식이다. 3번 과정에서는 구글 파이어 베이스 서버에서 expo 서버로 이를 다시 나의 서버로 잘 받았는지를 나타내는 데이터를 전송하는데 이를 PUSH RECEIPTS라고 한다. PUSH TICKETS은 결국 메시지가 사용자들에게 전송되었는지를 우리에게 알려주지 못한다. 

 

 

Sending 구현

 

나의 경우 Django 서버를 이용하고 있다. 그래서 Expo Doc에서 제시된 expo-server-sdk-python를 사용하였다. 

아래의 경우 나의 예시이다. 

class SearchHistoryAdmin(admin.ModelAdmin):
    list_display = ['name', 'searchkey', 'created_date', 'id']
    ordering = ("-created_date",)
    fields = ['name', 'searchkey', ]
    search_fields = ('searchkey',)

    def changelist_view(self, request, extra_context=None):
        send_form = SendHistoryForm()
        if request.method == 'POST':
            # title = request.POST.getlist('title')[0]
            message = request.POST.getlist('message')[0]
            send_push_message(message)
            return super().changelist_view(request,extra_context=extra_context)
        return super().changelist_view(request, extra_context=None)

위의 코드는 장고 Admin에서 사용자들에게 push 알림의 메시지와 타이틀을 설정하고 보낼 수 있는 코드이다. send_push_message() 함수는 expo서버로 토큰과 데이터를 보내는 역할을 한다.  메시지와 타이틀 말고 많은 데이터를 전송할 수 있다.

예를 들면 소리? 이미지 등등

이 내용을 확인하기 위해서는 여기를 클릭하자.

Comments