본문 바로가기
React/ReactNative

React Native에서 딥링크 처리 및 푸시 알림 최적화하기

by lumayi 2024. 5. 28.

이 글에선

React Native에서 딥링크 처리와 푸시 알림 기능을 최적화하는 방법에 대해 알아볼 것입니다. 특히, Firebase의 Messaging과 Notifee를 함께 사용한 이유에 대해서도 다루고 있습니다. 딥링크 설정, 푸시 알림 설정, 그리고 최적화된 코드 구조를 통해 효율적인 리액트 네이티브 link routing과 푸시 알림을 구축하는 방법을 설명해보겠습니다.

 

1. 딥링크 처리하기

딥링크는 사용자에게 특정 콘텐츠를 제공하기 위해 앱의 특정 화면으로 직접 이동할 수 있도록 도와줍니다. React Native에서 딥링크를 처리하려면 @react-navigation/native의 LinkingOptions를 설정하고, 앱이 열릴 때 해당 URL을 처리하도록 구성해야 합니다.

 

우선, 딥링크를 설정하기 위해 필요한 상수와 설정을 정의합니다. 이 설정은 앱이 열릴 때 특정 경로로 이동하도록 도와주는데 MoA 프로젝트 코드의 예시를 들어 설명하겠습니다.

import * as React from 'react';

// Deeplink 정의
const DEEPLINK_PREFIX_URL = ['giftMoA://', 'https://giftmoa.page.link'];
const deepLinksConfig = {
  initialRouteName: 'Home',
  screens: {
    FundDetailScreen: 'FundDetail/:id',
    MyFundingScreen: 'MyFunding',
    MyInquiries: 'MyInquiries',
    MyOrderDetailScreen: 'MyOrder/:id',
  },
};

const linking: LinkingOptions<RootStackParamList> = {
  prefixes: DEEPLINK_PREFIX_URL,
  config: deepLinksConfig,
  async getInitialURL() {
    const url = await Linking.getInitialURL();
    if (url != null) {
      return url;
    }
  }, // 구독해주기
  subscribe(listener) {
    const onReceiveURL = ({ url }) => listener(url);

    // dynamic links - 현재 Deprecated🥲
    const unsubscribeDynamicLinks = dynamicLinks().onLink(handleDynamicLink);

    // 일반적인 Linking
    const linkingSubscription = Linking.addEventListener('url', onReceiveURL);

    return () => {
      linkingSubscription.remove();
      unsubscribeDynamicLinks();
    };
  },
};


dynamicLinks().onLink(handleDynamicLink)와 Linking.addEventListener('url', onReceiveURL)은 모두 React Native에서 딥링크를 처리하기 위한 방법이지만, 그 목적과 사용 방식에 차이가 있습니다.

 

dynamicLinks().onLink(handleDynamicLink)는 Firebase Dynamic Links를 처리하기 위한 것입니다. Firebase Dynamic Links는 특정 URL을 사용하여 앱의 특정 콘텐츠로 사용자를 유도할 수 있는 라이브러리이지만 현재는 지원이 중단되었습니다🥲 이 메서드는 Firebase Dynamic Links SDK를 통해 앱이 열릴 때 실행되는 콜백 함수를 설정하면 되고, 마케팅 캠페인 링크, 이메일 링크 등에서 사용자가 앱을 열 때 주로 사용합니다. 그리고 앱이 없을 경우, 자동으로 앱스토어로 리다이렉트합니다.

 

Linking.addEventListener('url', onReceiveURL)는 일반적인 딥링크를 처리하기 위한 것입니다. 이 메서드는 앱이 열릴 때 URL을 수신하고 처리하는 콜백 함수를 설정합니다. 이 경우, Firebase Dynamic Links와는 상관없이 모든 URL을 처리할 수 있습니다. 일반적인 딥링크, 웹사이트 링크, QR 코드 등에서 사용자가 앱을 열 때 사용할 수 있습니다. 저는 펀딩을 참여한 친구에게 메세지를 공유할 때, 일반 딥링크로 처리했습니다.

 

2. 푸시 알림 설정

푸시 알림은 사용자가 앱을 사용하지 않을 때, 사용할 때, 백그라운드 상태일 때를 구분하여 설정해야합니다. 그리고 Firebase Messaging과 Notifee를 사용하여 푸시 알림을 설정하는 방법을 설명하겠습니다.

앱이 Foreground 상태일 때

앱이 foreground 상태일 때는 알림이 자동으로 사용자에게 표시되지 않습니다. 그래서 앱 내에서 직접 처리해야만 사용자에게 배너 형식의 알림을 표시할 수 있습니다. 이에 대한 자세한 코드는 아래에서 소개하겠습니다.

앱이 백그라운드 상태일 때

앱이 백그라운드 상태일 때는 Firebase가 자동으로 알림을 표시합니다. 이 경우 별도의 처리가 필요하지 않습니다.

앱이 종료 상태일 때

앱이 종료 상태일 때도 Firebase가 자동으로 알림을 표시해주고, 사용자가 알림을 클릭하면 앱이 열리면서 getInitialNotification 메서드를 통해 알림 데이터를 처리할 수 있습니다.

import messaging from '@react-native-firebase/messaging';

const checkInitialNotification = async () => {
  const initialNotification = await messaging().getInitialNotification();
  if (initialNotification) {
    const { title, body } = initialNotification.notification;
    handleNotificationOpen(title, body);
  }
};

const handleNotificationOpen = (title, body) => {
  // 알림 클릭 시 처리할 로직
  console.log('Notification 클릭되고 열림!', title, body);
};


Firebase Messaging과 Notifee

Firebase Messaging은 푸시 알림을 전송하는 데 사용되고, Notifee는 이러한 알림을 사용자에게 보여주는 데 사용됩니다. 두 가지를 함께 사용하는 이유는 Firebase Messaging이 알림 전송을 담당하지만, 더 정교하고 커스터마이징된 알림을 위해 Notifee를 사용하는 것이 좋기 때문입니다. 아래는 Foreground 상태일 때의 코드 예시입니다.

const setupForegroundMessageHandler = async () => {
  const foreGroundMessage = async (title, body) => {
    await notifee.requestPermission(); // 알림 권한 요청
    const channelId = await notifee.createChannel({ //android에서 필요한 설정
      id: 'MoA',
      name: '모아',
      importance: AndroidImportance.HIGH, // High로 해야 팝업처럼 배너 형식 알림이 보이게 됩니다
    });
    await notifee.displayNotification({ // Foreground 상태 알림 보여주기
      title,
      body,
      android: {
        channelId,
        pressAction: {
          id: 'MoA',
        },
      },
    });
  };

  const unsubscribe = messaging().onMessage(async remoteMessage => {
    const { notification: { body, title } } = remoteMessage;
    foreGroundMessage(title, body);
  });

  return unsubscribe;
};

 

 

3. 앱 초기화 및 최적화

앱이 초기화될 때, 메시지 핸들러를 설정하는 로직을 작성합니다.

export const App = () => {
  const { handleError } = useApiError();
  const { reset } = useQueryErrorResetBoundary();

  useEffect(() => {
    const initApp = async () => {
      SplashScreen.hide();
      updateAppVersion();
      const unsubscribe = await setupForegroundMessageHandler(); // 아래에 설명
      await checkInitialNotification();
      return unsubscribe;
    };
    const unsubscribe = initApp();
    return () => unsubscribe;
  }, []);

  return (
    <QueryClientProvider client={queryClient}>
      <NavigationContainer linking={linking}>
        <ErrorBoundary onReset={reset} FallbackComponent={FallbackUI}>
          <AuthRouter />
        </ErrorBoundary>
      </NavigationContainer>
      <Toast />
    </QueryClientProvider>
  );
};

 

setupForegroundMessageHandler는 위에서 Firebase와 notifee에서 소개한 메서드입니다. 이를 호출해주는 이유는 앱이 foreground 상태일 때(즉, 사용자가 현재 앱을 사용 중일 때) 수신된 푸시 알림을 처리하기 위해서입니다. 기본적으로, Firebase Cloud Messaging(FCM)은 앱이 백그라운드나 종료 상태일 때는 알림을 자동으로 처리하여 사용자에게 표시합니다. 그러나 앱이 foreground 상태일 때는 알림을 자동으로 표시하지 않습니다. 따라서, foreground 상태에서는 직접 알림을 처리하고 사용자에게 표시해야 합니다. 이 메서드를 통해 메시지를 수신하는 이벤트 리스너를 등록하여, 알림이 수신되었을 때 특정 동작을 수행하도록 할 수 있습니다.

 

그리고 백그라운드 및 종료 상태에서는 사용자가 알림을 클릭하면 앱이 열리고, getInitialNotification과 onNotificationOpenedApp 메서드를 통해 알림 데이터를 처리할 수 있습니다.

import messaging from '@react-native-firebase/messaging';

const checkInitialNotification = async (navigation) => {
  const initialNotification = await messaging().getInitialNotification();
  if (initialNotification) {
    const { title, body } = initialNotification.notification;
    handleNotificationOpen(navigation, title, body);
  }
};

const handleNotificationOpen = (navigation, title, body) => {
  // 알림 클릭 시 처리할 로직
  if (body.includes('FundDetail')) {
    const id = body.split('FundDetail/')[1];
    navigation.navigate('FundDetailScreen', { id });
  } else if (body.includes('MyFunding')) {
    navigation.navigate('MyFundingScreen');
  } else if (body.includes('MyInquiries')) {
    navigation.navigate('MyInquiriesScreen');
  } else if (body.includes('MyOrder')) {
    const id = body.split('MyOrder/')[1];
    navigation.navigate('MyOrderDetailScreen', { id });
  }
};

 

 

추가적으로 이렇게 파싱작업을 해준다면 푸시알림을 눌렀을 때에도 원하는 페이지로 라우팅 처리를 해줄 수 있습니다.

 

결론

이번 기회를 통해 딥링크, 다이내믹 링크, 그리고 푸시 알림에 대해 많은 것을 배울 수 있었습니다. 특히, 이러한 기능들을 구현하는 데 예상보다 많은 공수가 든다는 것을 깨달았습니다🥲 React Native에서 딥링크 처리와 푸시 알림을 최적화하는 방법에 대해 알 수 있었고, 앱의 상태에 따라 푸시 알림을 다르게 처리함으로써 사용자에게 더 나은 경험을 제공할 수 있었습니다. 특히 Firebase Messaging과 Notifee를 함께 사용하여 푸시 알림을 효율적으로 관리할 수 있었습니다. 딥링크를 통해 사용자는 특정 페이지로 쉽게 이동할 수 있고, 푸시 알림을 통해 중요한 정보를 놓치지 않도록 할 수 있습니다. 구글의 다이나믹링크가 개인적으로 굉장히 매력적인 기능으로 느껴졌는데, 지원이 종료되어 굉장히 아쉬웠습니다!

반응형