Expo 프로젝트 푸시 알림에 대해

oversleep·2025년 2월 8일
0

app-development

목록 보기
2/38
post-thumbnail

Expo 프로젝트 푸시 알림 구현: FCM vs Expo Notifications

푸시 알림 구현 시행착오

1️⃣ 첫 번째 시도: FCM 직접 구현

npm install @react-native-firebase/messaging

서비스 회원가입 완료 후 알림 수신 동의를 위해 FCM 구현 시도.
Firebase는 많이 사용되는 서비스라 FCM을 설치

➡️ 결과:

Error: Native module RNFBAppModule not found. 
Re-check module install, linking, configuration, build and install steps.

Expo managed workflow에서는 네이티브 모듈을 직접 설치할 수 없음.
FCM은 네이티브 설정이 필요한 모듈이라 managed workflow에서는 사용 불가능.

2️⃣ 최종 선택: Expo Notifications

npx expo install expo-notifications

Expo에서 제공하는 공식 알림 API를 발견.
FCM과 iOS, Android 푸시 알림을 모두 지원하고 설정도 훨씬 간단함.
iOS는 APNS(Apple Push Notification Service), Android는 FCM(Firebase Cloud Messaging)을 Expo가 중간에서 알아서 처리함.

구현 예시 코드

1. 알림 권한 요청 & 토큰 받기

사용자에게 알림 권한을 요청하고, 푸시 알림을 보내기 위한 고유 토큰을 받아오는 과정.
이 토큰을 서버에 저장해두면 나중에 이 사용자에게 알림을 보낼 수 있음.

import * as Notifications from 'expo-notifications';

const requestNotificationPermission = async () => {
  try {
    const { status: existingStatus } = await Notifications.getPermissionsAsync();
    let finalStatus = existingStatus;
    
    // 권한이 없으면 요청
    if (existingStatus !== 'granted') {
      const { status } = await Notifications.requestPermissionsAsync();
      finalStatus = status;
    }
    
    // 권한이 거부된 경우
    if (finalStatus !== 'granted') {
      Alert.alert('알림 권한이 필요합니다');
      return;
    }

    // 토큰 얻기
    const token = (await Notifications.getExpoPushTokenAsync()).data;
    console.log('Expo push token:', token);
    
    // 토큰을 서버에 전송
    await sendTokenToServer(token);

  } catch (error) {
    console.error('알림 권한 요청 실패:', error);
  }
};

2. 알림 핸들러 설정

앱이 실행 중일 때와 백그라운드일 때 알림을 어떻게 처리할지 정의함.
알림을 탭했을 때 특정 화면으로 이동하게 하는 등의 동작을 추가할 수 있음.

// App.tsx나 적절한 상위 컴포넌트에서
useEffect(() => {
  // 앱이 포그라운드 상태일 때 알림 처리
  const foregroundSubscription = Notifications.addNotificationReceivedListener(notification => {
    console.log('알림 수신:', notification);
  });

  // 알림 클릭 처리
  const responseSubscription = Notifications.addNotificationResponseReceivedListener(response => {
    console.log('알림 응답:', response);
    // 여기서 알림 클릭 시 원하는 화면으로 이동 등의 처리
  });

  return () => {
    foregroundSubscription.remove();
    responseSubscription.remove();
  };
}, []);

3. 회원가입 완료 후 알림 권한 요청

회원가입이 완료되면 사용자에게 알림 수신 동의를 받음.
동의하면 토큰을 서버에 저장하는 흐름을 구현함.

const handleSignupComplete = async (data: TSignupForm) => {
  try {
    const result = await handleSignup(data);

    if (result.success) {
      // 회원가입 성공 후 알림 권한 요청
      await requestNotificationPermission();
      
      // 로그인 화면으로 이동
      navigation.reset({
        index: 0,
        routes: [{ name: 'Login' }]
      });
    }
  } catch (error) {
    console.error("회원가입 실패:", error);
    Alert.alert('오류 발생', '잠시 후 다시 시도해주세요.');
  }
};

4. 알림 설정

알림이 왔을 때 소리를 낼지, 화면에 표시할지 등의 기본적인 동작을 정의함.
앱의 알림 기본 설정을 구성하는 부분.

// 알림 동작 설정
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: true,
  }),
});

FCM vs Expo Notifications 차이점

Expo Notifications 장점

  • 위 코드처럼 간단한 설정으로 바로 사용 가능
  • FCM과 APNS를 Expo가 자동으로 처리
  • 크로스 플랫폼 지원이 간편

FCM 직접 구현 시 필요 사항

  • 프로젝트 eject
  • google-services.json, GoogleService-Info.plist 설정
  • iOS/Android 각각의 네이티브 설정
  • FCM 초기화 코드 작성

결론

  • 단순히 회원가입 후 알림 동의 받기가 목적
  • FCM의 고급 기능까지는 필요 없었음
  • 기본적인 푸시 알림 기능은 Expo Notifications로 충분
  • 설정도 간단하고, 크로스 플랫폼 지원도 잘 됨
  • FCM의 고급 기능이 필요한 경우만 eject 고려
  • 개발 생산성과 유지보수를 고려하면 Expo Notifications가 좋은 선택
profile
궁금한 것, 했던 것, 시행착오 그리고 기억하고 싶은 것들을 기록합니다.

0개의 댓글