모바일 OS는 배터리 절약을 위해 백그라운드 앱을 적극적으로 제한합니다. 올바른 방법을 사용하지 않으면 작업이 중단됩니다.


백그라운드 제약사항

PLAINTEXT
iOS:
- Background App Refresh (OS가 적절한 시점에 실행)
- 위치 추적 (continuous background location)
- 오디오 재생, VOIP
- 명시적으로 Background Modes를 설정해야 함

Android:
- Foreground Service (알림 표시 필수)
- WorkManager (지연 가능한 백그라운드 작업)
- AlarmManager (정확한 시간 실행)
- Doze Mode / App Standby 제한

expo-background-fetch

BASH
npx expo install expo-background-fetch expo-task-manager
TSX
import * as BackgroundFetch from 'expo-background-fetch';
import * as TaskManager from 'expo-task-manager';

const BACKGROUND_FETCH_TASK = 'background-fetch-task';

// 백그라운드 태스크 정의 (최상위 레벨)
TaskManager.defineTask(BACKGROUND_FETCH_TASK, async () => {
  const now = Date.now();
  console.log(`백그라운드 태스크 실행: ${new Date(now).toISOString()}`);

  try {
    // 새 데이터 확인, 동기화 등
    const hasNewData = await checkForNewData();

    if (hasNewData) {
      await syncData();
      // 로컬 알림으로 사용자에게 알림
      await showLocalNotification('새 데이터가 있습니다');
    }

    return hasNewData
      ? BackgroundFetch.BackgroundFetchResult.NewData
      : BackgroundFetch.BackgroundFetchResult.NoData;
  } catch (error) {
    return BackgroundFetch.BackgroundFetchResult.Failed;
  }
});

// 태스크 등록
async function registerBackgroundFetch() {
  await BackgroundFetch.registerTaskAsync(BACKGROUND_FETCH_TASK, {
    minimumInterval: 15 * 60,  // 최소 15분 간격
    stopOnTerminate: false,    // 앱 종료 후에도 실행
    startOnBoot: true,         // 재부팅 후 실행
  });
}

백그라운드 위치 추적

TSX
import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';

const LOCATION_TASK = 'background-location-task';

TaskManager.defineTask(LOCATION_TASK, ({ data, error }) => {
  if (error) {
    console.error('위치 추적 에러:', error);
    return;
  }

  const { locations } = data as { locations: Location.LocationObject[] };
  const latest = locations[0];
  console.log('백그라운드 위치:', latest.coords);

  // 서버에 위치 전송
  sendLocationToServer(latest.coords);
});

async function startBackgroundLocation() {
  const { status: foreground } = await Location.requestForegroundPermissionsAsync();
  const { status: background } = await Location.requestBackgroundPermissionsAsync();

  if (foreground !== 'granted' || background !== 'granted') {
    Alert.alert('위치 권한이 필요합니다');
    return;
  }

  await Location.startLocationUpdatesAsync(LOCATION_TASK, {
    accuracy: Location.Accuracy.Balanced,
    distanceInterval: 50,           // 50m마다 업데이트
    showsBackgroundLocationIndicator: true, // iOS 상태바 표시
    foregroundService: {
      notificationTitle: '위치 추적 중',
      notificationBody: '앱이 위치를 추적하고 있습니다',
    },
  });
}

async function stopBackgroundLocation() {
  await Location.stopLocationUpdatesAsync(LOCATION_TASK);
}

주의사항

  1. 배터리 소모: 백그라운드 작업은 배터리를 빠르게 소모합니다
  2. OS 제한: iOS는 Background Fetch 실행 시점을 OS가 결정합니다
  3. 사용자 신뢰: 백그라운드 위치 추적은 사용자에게 명확히 고지해야 합니다
  4. 스토어 심사: 불필요한 백그라운드 권한은 심사 거절 사유가 됩니다

정리

  • 백그라운드 작업은 OS의 엄격한 제한 을 받으므로 공식 API를 사용하세요
  • Background Fetch 는 OS가 적절한 시점에 실행합니다 — 정확한 타이밍 보장 불가
  • 위치 추적은 배터리 소모가 크므로 distanceInterval을 적절히 설정하세요
  • 사용자에게 백그라운드 활동을 명확히 고지 하세요 — 앱 심사와 사용자 신뢰 모두에 필요합니다
댓글 로딩 중...