RNWW Plugin Background
React Native WebView 백그라운드 실행 플러그인 (Expo Native Module)
앱 라이프사이클 이벤트 발생 시 메인 WebView에서 JavaScript 콜백을 실행합니다. appBridge 등 앱의 전역 객체에 접근할 수 있습니다.
설치
npm install rnww-plugin-background
빠른 시작
import { registerBackgroundHandlers } from 'rnww-plugin-background';
registerBackgroundHandlers({
bridge: yourBridgeImplementation,
platform: { OS: Platform.OS },
});
const API_URL = 'https://api.example.com';
await bridge.call('registerTask', {
taskId: 'my-task',
triggers: ['app_foreground', 'app_background'],
callback: (trigger, data) => {
fetch(API_URL + '/sync', {
method: 'POST',
body: JSON.stringify({ event: trigger })
});
appBridge.call('api:sync', { event: trigger });
},
notification: {
title: '백그라운드 실행 중',
body: '서비스가 실행 중입니다'
}
});
await bridge.call('startTask', { taskId: 'my-task' });
핵심 개념
이 플러그인은 메인 WebView에서 JavaScript 콜백을 실행합니다. startTask 호출 시 WebView가 자동으로 감지되어 연결됩니다.
트리거 종류
- 기본 트리거 (
init, terminate): 항상 자동 호출됨
- 라이프사이클 트리거 (
app_foreground, app_background): triggers 배열에 포함 시에만 호출
bridge.call('registerTask', {
taskId: 'my-task',
triggers: ['app_foreground', 'app_background'],
callback: (trigger, data) => {
switch (trigger) {
case 'init':
console.log('Task initialized');
break;
case 'terminate':
console.log('Task terminating');
break;
case 'app_background':
saveCurrentState();
break;
case 'app_foreground':
syncData();
break;
}
},
notification: {
title: '백그라운드 실행 중',
body: '서비스가 실행 중입니다'
}
});
Bridge Handlers
registerTask
백그라운드 작업을 등록합니다.
const result = await bridge.call('registerTask', {
taskId: string;
triggers?: TriggerType[];
callback?: BackgroundCallback;
notification?: NotificationConfig;
});
unregisterTask
등록된 작업을 해제합니다.
const result = await bridge.call('unregisterTask', { taskId: 'my-task' });
startTask
작업을 시작합니다. WebView가 자동으로 감지되어 연결됩니다.
const result = await bridge.call('startTask', { taskId: 'my-task' });
stopTask
작업을 중지합니다.
const result = await bridge.call('stopTask', { taskId: 'my-task' });
stopAllTasks
모든 작업을 중지합니다.
const result = await bridge.call('stopAllTasks');
updateNotification
실행 중인 알림 내용을 업데이트합니다. (Android only)
const result = await bridge.call('updateNotification', {
taskId: 'my-task',
title: '동기화 중',
body: '작업 진행 중...',
silent: true
});
getTaskStatus / getAllTasksStatus
작업 상태를 조회합니다.
const result = await bridge.call('getTaskStatus', { taskId: 'my-task' });
const allResult = await bridge.call('getAllTasksStatus');
권한 관련
await bridge.call('checkBackgroundPermission');
await bridge.call('requestBackgroundPermission');
await bridge.call('checkNotificationPermission');
await bridge.call('requestNotificationPermission');
태스크 데이터
await bridge.call('setTaskData', {
taskId: 'my-task',
data: { lastSync: Date.now() }
});
const result = await bridge.call('getTaskData', { taskId: 'my-task' });
await bridge.call('removeTaskData', { taskId: 'my-task' });
evaluateInMainWebView
메인 WebView에서 JavaScript를 직접 실행합니다.
const result = await bridge.call('evaluateInMainWebView', {
script: 'window.myApp.getState()'
});
트리거 시스템
기본 트리거 (자동 호출)
init | 태스크 시작 직후 | 초기화 로직 실행 |
terminate | 태스크 종료 직전 | 상태 저장, 리소스 정리 |
라이프사이클 트리거 (선택적)
triggers 배열에 명시적으로 포함해야 호출됩니다.
app_foreground | 앱이 포그라운드로 전환 | 데이터 동기화, UI 갱신 |
app_background | 앱이 백그라운드로 전환 | 상태 저장, 네트워크 요청 |
콜백 시스템
callback (WebView 콜백)
메인 WebView에서 실행됩니다. 백그라운드에서도 동작합니다. 외부 변수와 앱 전역 객체에 접근할 수 있습니다.
const API_URL = 'https://api.example.com';
callback: (trigger, data) => {
switch (trigger) {
case 'init':
window.__taskStartedAt = Date.now();
break;
case 'terminate':
fetch(API_URL + '/final', {
method: 'POST',
body: JSON.stringify({ duration: Date.now() - window.__taskStartedAt })
});
break;
case 'app_background':
appBridge.call('saveState', { timestamp: data.timestamp });
break;
case 'app_foreground':
appBridge.call('syncData');
break;
}
}
알림 설정 (Android)
interface NotificationConfig {
title: string;
body: string;
icon?: string;
color?: string;
priority?: 'min' | 'low' | 'default' | 'high' | 'max';
ongoing?: boolean;
silent?: boolean;
channelId?: string;
channelName?: string;
channelDescription?: string;
}
에러 타입
type BackgroundError =
| 'TASK_NOT_FOUND'
| 'TASK_ALREADY_EXISTS'
| 'TASK_ALREADY_RUNNING'
| 'NOTIFICATION_PERMISSION_DENIED'
| 'WEBVIEW_NOT_FOUND'
| 'INVALID_INPUT'
| 'UNKNOWN';
플랫폼별 설정
Android
AndroidManifest.xml에 자동 추가:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
Android 13+ (API 33): POST_NOTIFICATIONS 런타임 권한 필수
iOS
Info.plist에 추가:
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
</array>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>expo.modules.custombackground.refresh</string>
</array>
고급: WebView 연결
자동 연결
startTask 호출 시 WebView가 자동으로 감지되어 연결됩니다. Activity 재생성 (화면 회전 등) 시에도 앱이 포그라운드로 전환될 때 자동으로 재연결됩니다.
수동 연결
여러 WebView가 있는 경우 특정 WebView를 지정할 수 있습니다:
<WebView
nativeID="123"
source={{ uri: 'https://...' }}
/>
await bridge.call('attachWebView', { viewTag: 123 });
await bridge.call('detachWebView');
라이선스
MIT