React Native Expo 푸시알림 구현하기 (3) - 푸시알림 설정과 토큰 관리

oversleep·2025년 2월 15일
0

app-development

목록 보기
9/38
post-thumbnail

들어가며

이전 포스팅에서 기본적인 푸시알림 권한 요청과 토큰 관리에 대해 다뤘습니다.
이번에는 사용자가 앱 내에서 푸시알림을 켜고 끌 수 있는 설정 기능과, 로그아웃/회원탈퇴 시의 토큰 관리에 대해 자세히 알아보겠습니다.

구현 과정에서 마주친 문제들

  1. 토큰 관리의 복잡성

    • FCM 토큰은 디바이스 단위로 발급
    • 여러 계정이 한 디바이스를 사용할 수 있음
    • 로그아웃/회원탈퇴 시 토큰 처리 방식이 달라야 함
  2. 상태 유지의 어려움

    • 앱 재실행 시 알림 설정 상태가 초기화되는 문제
    • 시스템 권한과 앱 내 설정의 동기화 필요
    • AsyncStorage를 활용한 상태 관리 필요
  3. 에러 처리의 중요성

    • 이미 등록된 토큰에 대한 409 에러
    • 존재하지 않는 토큰 삭제 시도 시 404 에러
    • 적절한 에러 핸들링으로 UX 개선

주요 구현 내용

  1. 알림 설정 모달
const NotificationSettingsModal = ({ isVisible, onClose }: TNotificationSettingsModal) => {
  const [isEnabled, setIsEnabled] = useState(false);

  useEffect(() => {
    checkNotificationStatus();
  }, []);

  const checkNotificationStatus = async () => {
    try {
      const { status } = await Notifications.getPermissionsAsync();
      const savedSettings = await AsyncStorage.getItem("notificationSettings");
      setIsEnabled(status === "granted" && savedSettings === "true");
    } catch (error) {
      console.error("Failed to check notification status:", error);
    }
  };
  
  // ... 토글 로직
};
  1. 토큰 등록/삭제 처리
const toggleNotifications = async () => {
  try {
    if (!isEnabled) {
      // 알림 활성화 로직
      const { status } = await Notifications.requestPermissionsAsync();
      if (status === "granted") {
        const token = await getExpoPushToken();
        await registerDeviceToken(token);
        await saveNotificationSettings(true);
      }
    } else {
      // 알림 비활성화 로직
      const token = await getExpoPushToken();
      await unregisterDeviceToken(token);
      await saveNotificationSettings(false);
    }
  } catch (error) {
    handleToggleError(error);
  }
};
  1. 회원 탈퇴 시 처리
const handleWithdrawal = async () => {
  try {
    await withdrawMembership(userId);
    // 푸시 알림 관련 설정 초기화
    await AsyncStorage.multiRemove([
      "pushPermissionShown",
      "notificationSettings"
    ]);
    handleLogout();
  } catch (error) {
    console.error("회원 탈퇴 중 오류 발생", error);
  }
};

개선된 에러 처리

const handleToggleError = async (error: any) => {
  if (error.response?.status === 409) {
    // 이미 등록된 토큰
    await AsyncStorage.setItem("notificationSettings", "true");
    setIsEnabled(true);
  } else if (error.response?.status === 404) {
    // 이미 삭제된 토큰
    await AsyncStorage.setItem("notificationSettings", "false");
    setIsEnabled(false);
  } else {
    Alert.alert("알림 설정 실패", "다시 시도해주세요.");
  }
};

구현 시 주요 고려사항

  1. 디바이스 vs 계정

    • 푸시알림 토큰은 디바이스 단위
    • 로그아웃 시에는 토큰 유지 (다른 계정 사용 가능)
    • 회원탈퇴 시에는 토큰 및 설정 초기화
  2. 상태 동기화

    • 시스템 권한과 앱 내 설정 동기화
    • AsyncStorage를 통한 설정 유지
    • 앱 재실행 시 상태 복원
  3. 사용자 경험

    • 직관적인 설정 UI
    • 적절한 에러 메시지
    • 부드러운 상태 전환
profile
궁금한 것, 했던 것, 시행착오 그리고 기억하고 싶은 것들을 기록합니다.

0개의 댓글