New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

rnww-plugin-background

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rnww-plugin-background

React Native WebView Background Execution Plugin with Expo support

npmnpm
Version
1.4.1
Version published
Maintainers
1
Created
Source

RNWW Plugin Background

React Native WebView 백그라운드 실행 플러그인 (Expo Native Module)

Headless WebView를 통해 앱 라이프사이클 이벤트 발생 시 JavaScript 콜백을 실행합니다.

설치

npm install rnww-plugin-background

빠른 시작

import { registerBackgroundHandlers } from 'rnww-plugin-background';

registerBackgroundHandlers({
  bridge: yourBridgeImplementation,
  platform: { OS: Platform.OS },
});

핵심 개념

이 플러그인은 Headless WebView에 JavaScript 콜백을 주입하여 앱 라이프사이클 이벤트 발생 시 실행합니다.

트리거 종류

  • 기본 트리거 (init, terminate): 항상 자동 호출됨
  • 라이프사이클 트리거 (app_foreground, app_background): triggers 배열에 포함 시에만 호출
// 콜백 함수가 WebView에 주입되어 트리거 발생 시 실행됨
bridge.call('registerTask', {
  taskId: 'my-task',
  triggers: ['app_foreground', 'app_background'],  // 라이프사이클 트리거 (선택)
  callback: (trigger, data) => {
    // 이 코드는 Headless WebView 내에서 실행됨
    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;           // 필수: 작업 고유 ID
  triggers?: TriggerType[]; // 라이프사이클 트리거 ['app_foreground', 'app_background']
                            // ※ init, terminate는 자동 호출되므로 지정 불필요
  callback?: BackgroundCallback;  // WebView에서 실행될 콜백 (init/terminate 포함)
  onEvent?: TaskCallback;   // 네이티브 이벤트 리스너
  onTerminate?: TaskCallback; // 종료 직전 콜백 (브릿지 레벨)
  callbackId?: string;      // 이벤트 추적용 식별자
  notification?: NotificationConfig; // Android 필수
});

// 결과
// { success: true, taskId: 'my-task' }
// { success: false, error: 'TASK_ALREADY_EXISTS' }

triggers vs 기본 트리거:

  • triggers 배열: app_foreground, app_background만 지정 가능
  • init, terminate: triggers 배열과 무관하게 항상 자동 호출됨

unregisterTask

등록된 작업을 해제합니다.

const result = await bridge.call('unregisterTask', { taskId: 'my-task' });
// { success: true, taskId: 'my-task' }

startTask

작업을 시작합니다. Android에서는 Foreground Service가 시작됩니다.

const result = await bridge.call('startTask', { taskId: 'my-task' });
// { success: true, taskId: 'my-task' }
// { success: false, error: 'NOTIFICATION_PERMISSION_DENIED' }

stopTask

작업을 중지합니다.

const result = await bridge.call('stopTask', { taskId: 'my-task' });
// { success: true, taskId: 'my-task' }

stopAllTasks

모든 작업을 중지합니다.

const result = await bridge.call('stopAllTasks');
// { success: true }

updateNotification

실행 중인 알림 내용을 업데이트합니다. (Android only)

const result = await bridge.call('updateNotification', {
  taskId: 'my-task',
  title: '동기화 중',
  body: '작업 진행 중...',
  silent: true  // 업데이트 시 소리/진동 없음 (기본값: true)
});
// { success: true }

getTaskStatus

특정 작업의 상태를 조회합니다.

const result = await bridge.call('getTaskStatus', { taskId: 'my-task' });
// {
//   success: true,
//   status: {
//     taskId: 'my-task',
//     isRunning: true,
//     mode: 'persistent',
//     startedAt: 1234567890000
//   }
// }

getAllTasksStatus

모든 작업의 상태를 조회합니다.

const result = await bridge.call('getAllTasksStatus');
// {
//   success: true,
//   tasks: [...],
//   isAnyRunning: true
// }

checkBackgroundPermission

백그라운드 권한 상태를 확인합니다.

const result = await bridge.call('checkBackgroundPermission');
// {
//   success: true,
//   canRunBackground: true,
//   batteryOptimizationExempt: true,  // Android
//   notificationPermission: true,     // Android 13+
//   requiredPermissions: [],
//   deniedPermissions: []
// }

requestBackgroundPermission

백그라운드 권한을 요청합니다. (배터리 최적화 예외)

const result = await bridge.call('requestBackgroundPermission');

checkNotificationPermission

알림 권한을 확인합니다. (Android 13+ 필수)

const result = await bridge.call('checkNotificationPermission');
// { success: true, granted: true, canAskAgain: false }

requestNotificationPermission

알림 권한을 요청합니다.

const result = await bridge.call('requestNotificationPermission');
// { success: true, granted: true, canAskAgain: false }

setTaskData

작업별 데이터를 저장합니다. (SharedPreferences/UserDefaults)

const result = await bridge.call('setTaskData', {
  taskId: 'my-task',
  data: { lastSync: Date.now(), count: 5 }
});
// { success: true }

getTaskData

작업별 데이터를 조회합니다.

const result = await bridge.call('getTaskData', { taskId: 'my-task' });
// { success: true, data: { lastSync: 1234567890, count: 5 } }

removeTaskData

작업별 데이터를 삭제합니다.

const result = await bridge.call('removeTaskData', { taskId: 'my-task' });
// { success: true }

disposeBackgroundHandlers

브릿지 핸들러와 리소스를 정리합니다.

await bridge.call('disposeBackgroundHandlers');
// { success: true }

트리거 시스템

트리거 종류

트리거는 기본 트리거와 라이프사이클 트리거로 구분됩니다.

기본 트리거 (자동 호출)

triggers 배열 설정과 무관하게 항상 자동으로 호출됩니다.

트리거호출 시점설명
init태스크 시작 직후콜백 함수가 WebView에 주입 완료된 후 자동 호출. 초기화 로직 실행에 사용
terminate태스크 종료 직전서비스가 종료되기 전 자동 호출. 상태 저장, 리소스 정리 등에 사용

라이프사이클 트리거 (선택적)

triggers 배열에 명시적으로 포함해야 호출됩니다.

트리거호출 시점설명
app_foreground앱이 포그라운드로 전환사용자가 앱으로 돌아올 때 호출. 데이터 동기화, UI 갱신 등에 사용
app_background앱이 백그라운드로 전환사용자가 앱을 떠날 때 호출. 상태 저장, 네트워크 요청 등에 사용

트리거 흐름도

startTask() 호출
    │
    ▼
┌─────────────────────┐
│  콜백 WebView 주입   │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│   init 트리거 발생   │ ◄── 항상 자동 호출
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│    태스크 실행 중    │
│                     │
│  app_foreground ◄───┼── triggers 배열에 포함 시
│  app_background ◄───┼── triggers 배열에 포함 시
│                     │
└─────────────────────┘
    │
    ▼ (stopTask 또는 서비스 종료)
┌─────────────────────┐
│ terminate 트리거 발생│ ◄── 항상 자동 호출
└─────────────────────┘
    │
    ▼
   종료

사용 예시

bridge.call('registerTask', {
  taskId: 'lifecycle-task',
  triggers: ['app_foreground', 'app_background'],  // 라이프사이클 트리거만 지정
  callback: (trigger, data) => {
    console.log(`트리거: ${trigger}, 시간: ${data.timestamp}`);

    switch (trigger) {
      // ═══════════════════════════════════════════════════════════
      // 기본 트리거 (triggers 배열 설정 없이도 항상 호출됨)
      // ═══════════════════════════════════════════════════════════

      case 'init':
        // 태스크 시작 시 초기화
        // - API 연결 설정
        // - 초기 데이터 로드
        // - 타이머/인터벌 설정
        console.log('Task initialized');
        initializeConnections();
        loadInitialData();
        break;

      case 'terminate':
        // 태스크 종료 직전 정리
        // - 상태 저장
        // - 연결 종료
        // - 리소스 해제
        console.log('Task terminating');
        saveCurrentState();
        closeConnections();
        break;

      // ═══════════════════════════════════════════════════════════
      // 라이프사이클 트리거 (triggers 배열에 포함 시에만 호출됨)
      // ═══════════════════════════════════════════════════════════

      case 'app_background':
        // 앱이 백그라운드로 전환될 때
        // - 현재 상태 저장
        // - 서버에 상태 동기화
        console.log('App went to background');
        saveCurrentState();
        syncToServer();
        break;

      case 'app_foreground':
        // 앱이 포그라운드로 돌아올 때
        // - 서버에서 최신 데이터 가져오기
        // - 캐시 갱신
        console.log('App came to foreground');
        fetchLatestData();
        refreshCache();
        break;
    }
  },
  notification: { title: 'Service', body: 'Running...' }
});

TriggerData 구조

모든 트리거 호출 시 전달되는 데이터입니다.

interface TriggerData {
  timestamp: number;  // 트리거 발생 시간 (Unix timestamp, ms)
  taskId: string;     // 작업 ID
}

// 사용 예
callback: (trigger, data) => {
  console.log(`Task: ${data.taskId}`);
  console.log(`Time: ${new Date(data.timestamp).toISOString()}`);
}

콜백 시스템

callback (WebView 콜백)

callback은 Headless WebView 내에서 실행됩니다.

callback: (trigger: TriggerType, data: TriggerData) => void

// TriggerType: 'init' | 'terminate' | 'app_foreground' | 'app_background'

트리거별 호출 조건

트리거호출 조건용도
init항상 자동 호출초기화, 연결 설정, 전역 변수 설정
terminate항상 자동 호출정리, 최종 저장, 연결 종료
app_foregroundtriggers 배열에 포함 시데이터 새로고침, UI 동기화
app_backgroundtriggers 배열에 포함 시상태 저장, 서버 동기화

기본 패턴

callback: (trigger, data) => {
  switch (trigger) {
    case 'init':
      // 초기화 로직 (항상 호출됨)
      break;
    case 'terminate':
      // 정리 로직 (항상 호출됨)
      break;
    case 'app_foreground':
      // 포그라운드 전환 시 (triggers에 포함 필요)
      break;
    case 'app_background':
      // 백그라운드 전환 시 (triggers에 포함 필요)
      break;
  }
}

중요 제한사항: 클로저 사용 불가

// ❌ 작동 안 함 - 외부 변수 참조
const API_URL = 'https://api.example.com';
callback: (trigger, data) => {
  fetch(API_URL);  // API_URL은 WebView에서 undefined!
}

// ✅ 올바른 방법 - 값을 직접 인라인
callback: (trigger, data) => {
  fetch('https://api.example.com');
}

onEvent (네이티브 이벤트)

onEvent는 브릿지 레벨에서 네이티브 이벤트를 수신합니다.

bridge.call('registerTask', {
  taskId: 'my-task',
  onEvent: (event) => {
    switch (event.type) {
      case 'started':
        console.log('작업 시작됨');
        break;
      case 'stopped':
        console.log('작업 중지됨');
        break;
      case 'trigger':
        console.log(`트리거 발생: ${event.trigger}`);
        break;
      case 'terminated':
        console.log('비정상 종료 감지');
        break;
    }
  },
  // ...
});

onTerminate (종료 콜백)

서비스 종료 직전에 실행됩니다.

bridge.call('registerTask', {
  taskId: 'my-task',
  onTerminate: async (event) => {
    // 종료 직전 상태 저장 (약 5초 제한)
    await bridge.call('setTaskData', {
      taskId: event.taskId,
      data: { terminatedAt: Date.now() }
    });
  },
  // ...
});

주의: 프로세스가 즉시 kill되면 호출되지 않을 수 있습니다. 비정상 종료는 다음 앱 실행 시 terminated 이벤트로 감지됩니다.

callbackId

여러 작업의 이벤트를 구분하기 위한 식별자입니다.

bridge.call('registerTask', {
  taskId: 'task-1',
  callbackId: 'sync-callback',
  // ...
});

// 이벤트에서 callbackId로 구분
bridge.on('onTaskEvent', (event) => {
  if (event.callbackId === 'sync-callback') {
    // task-1의 이벤트
  }
});

알림 설정 (Android)

NotificationConfig

interface NotificationConfig {
  taskId?: string;          // updateNotification 시 대상 지정
  title: string;            // 알림 제목
  body: string;             // 알림 본문
  icon?: string;            // Android drawable 리소스명
  color?: string;           // 아이콘 색상 (hex: '#4CAF50')
  priority?: 'min' | 'low' | 'default' | 'high' | 'max';
  ongoing?: boolean;        // 지속 알림 (스와이프 불가, 기본값: true)
  silent?: boolean;         // 무음 알림 (기본값: false, updateNotification 시 true)
  channelId?: string;       // Android 8.0+
  channelName?: string;
  channelDescription?: string;
}

예시

notification: {
  title: '백그라운드 서비스',
  body: '실행 중입니다',
  icon: 'ic_notification',
  color: '#4CAF50',
  priority: 'low',
  ongoing: true,
  silent: false,
  channelId: 'my_channel',
  channelName: 'Background Service'
}

이벤트

TaskEvent 구조

interface TaskEvent {
  taskId: string;
  type: 'started' | 'stopped' | 'trigger' | 'terminating' | 'terminated';
  trigger?: TriggerType;      // type이 'trigger'일 때 (init, terminate, app_foreground, app_background)
  reason?: 'unexpected';      // type이 'terminated'일 때
  lastStartedAt?: number;     // type이 'terminated'일 때
  timestamp: number;
  callbackId?: string;
}

이벤트 타입

타입설명
started작업 시작됨
stopped작업 중지됨
trigger트리거 발생 (WebView callback 호출됨). event.trigger에 트리거 종류 포함
terminating서비스 종료 직전 (best-effort)
terminated비정상 종료 감지 (앱 재시작 시)

이벤트 발생 순서

startTask() 호출
    │
    ▼
┌─────────────────────────────────────────┐
│ type: 'started'                         │
└─────────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────────┐
│ type: 'trigger', trigger: 'init'        │ ◄── 자동
└─────────────────────────────────────────┘
    │
    ▼
   실행 중...
    │
    ▼ (라이프사이클 이벤트 발생 시)
┌─────────────────────────────────────────┐
│ type: 'trigger', trigger: 'app_*'       │ ◄── triggers 배열에 포함 시
└─────────────────────────────────────────┘
    │
    ▼ (stopTask 또는 서비스 종료)
┌─────────────────────────────────────────┐
│ type: 'trigger', trigger: 'terminate'   │ ◄── 자동
└─────────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────────┐
│ type: 'terminating'                     │
└─────────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────────┐
│ type: 'stopped'                         │
└─────────────────────────────────────────┘

에러 타입

type BackgroundError =
  | 'TASK_NOT_FOUND'              // 작업을 찾을 수 없음
  | 'TASK_ALREADY_EXISTS'         // 이미 등록된 작업
  | 'TASK_ALREADY_RUNNING'        // 이미 실행 중
  | 'NOTIFICATION_PERMISSION_DENIED'  // 알림 권한 없음 (Android 13+)
  | 'INVALID_INPUT'               // 잘못된 입력
  | 'UNKNOWN';                    // 알 수 없는 에러

전체 사용 예시

async function setupBackgroundService() {
  // 1. 권한 확인 (Android 13+)
  const notifPerm = await bridge.call('checkNotificationPermission');
  if (!notifPerm.granted) {
    const result = await bridge.call('requestNotificationPermission');
    if (!result.granted) {
      alert('알림 권한이 필요합니다');
      return;
    }
  }

  // 2. 작업 등록
  const registerResult = await bridge.call('registerTask', {
    taskId: 'lifecycle-task',
    triggers: ['app_foreground', 'app_background'],  // 라이프사이클 트리거

    // WebView에서 실행될 콜백
    // init, terminate는 triggers 배열과 무관하게 항상 호출됨
    callback: (trigger, data) => {
      console.log('[WebView] Trigger:', trigger, 'at', data.timestamp);

      switch (trigger) {
        // ═══════════════════════════════════════════════════════════
        // 기본 트리거 (항상 자동 호출)
        // ═══════════════════════════════════════════════════════════

        case 'init':
          // 태스크가 시작되고 콜백이 WebView에 주입된 직후
          console.log('[WebView] Task initialized');

          // 초기화 작업 수행
          // - 전역 변수 설정
          // - API 클라이언트 초기화
          // - WebSocket 연결 등
          window.__taskState = {
            startedAt: data.timestamp,
            syncCount: 0
          };
          break;

        case 'terminate':
          // 서비스가 종료되기 직전
          console.log('[WebView] Task terminating');

          // 정리 작업 수행
          // - 최종 상태 저장
          // - 연결 종료
          // - 리소스 해제
          if (window.__taskState) {
            fetch('https://api.example.com/final-sync', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({
                taskId: data.taskId,
                duration: data.timestamp - window.__taskState.startedAt,
                totalSyncs: window.__taskState.syncCount
              })
            });
          }
          break;

        // ═══════════════════════════════════════════════════════════
        // 라이프사이클 트리거 (triggers 배열에 포함 시에만 호출)
        // ═══════════════════════════════════════════════════════════

        case 'app_background':
          // 앱이 백그라운드로 전환될 때
          console.log('[WebView] App went to background');

          // 백그라운드 진입 시 처리
          // - 현재 상태 서버에 동기화
          // - 알림 업데이트
          window.__taskState.syncCount++;
          fetch('https://api.example.com/sync', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
              event: 'background',
              timestamp: data.timestamp
            })
          });
          break;

        case 'app_foreground':
          // 앱이 포그라운드로 돌아올 때
          console.log('[WebView] App came to foreground');

          // 포그라운드 복귀 시 처리
          // - 최신 데이터 가져오기
          // - 캐시 갱신
          fetch('https://api.example.com/status')
            .then(res => res.json())
            .then(status => {
              console.log('[WebView] Server status:', status);
            });
          break;
      }
    },

    // 네이티브 이벤트 리스너 (브릿지 레벨)
    onEvent: (event) => {
      console.log('[Native] Event:', event.type, event.trigger || '');

      // 네이티브 이벤트 처리
      // - UI 업데이트
      // - 상태 관리
      switch (event.type) {
        case 'started':
          console.log('서비스가 시작되었습니다');
          break;
        case 'stopped':
          console.log('서비스가 중지되었습니다');
          break;
        case 'trigger':
          console.log(`트리거 발생: ${event.trigger}`);
          break;
        case 'terminated':
          console.log('비정상 종료가 감지되었습니다');
          // 복구 로직 실행
          break;
      }
    },

    // 종료 직전 콜백 (브릿지 레벨)
    onTerminate: async (event) => {
      console.log('[Native] Task terminating:', event.taskId);

      // 종료 직전 네이티브 레벨 처리
      // - 로컬 데이터 저장
      // - 로그 기록
      await bridge.call('setTaskData', {
        taskId: event.taskId,
        data: { terminatedAt: Date.now() }
      });
    },

    notification: {
      title: '백그라운드 서비스',
      body: '앱이 백그라운드에서 실행 중입니다',
      icon: 'ic_notification',
      color: '#4CAF50',
      priority: 'low',
      ongoing: true,
      silent: true,
      channelId: 'background_service',
      channelName: 'Background Service',
      channelDescription: '백그라운드 작업 실행 알림'
    }
  });

  if (!registerResult.success) {
    console.error('등록 실패:', registerResult.error);
    return;
  }

  // 3. 작업 시작
  const startResult = await bridge.call('startTask', { taskId: 'lifecycle-task' });
  if (!startResult.success) {
    console.error('시작 실패:', startResult.error);
  }

  // 시작 후 트리거 순서:
  // 1. "started" 이벤트 발생 → onEvent 호출
  // 2. "init" 트리거 발생 → callback 호출
}

// 작업 중지
async function stopService() {
  // 중지 시 트리거 순서:
  // 1. "terminate" 트리거 발생 → callback 호출
  // 2. "terminating" 이벤트 발생 → onTerminate 호출
  // 3. "stopped" 이벤트 발생 → onEvent 호출
  await bridge.call('stopTask', { taskId: 'lifecycle-task' });
}

플랫폼별 설정

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" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Android 13+ (API 33):

  • POST_NOTIFICATIONS 런타임 권한 필수
  • 권한 없이 startTask 호출 시 NOTIFICATION_PERMISSION_DENIED 에러

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>

실행 플로우

Task 시작 플로우

1. registerTask() - 태스크 등록 (TaskManager에 저장)
2. startTask() - 태스크 시작
   │
   ├─ Android: Foreground Service 시작
   ├─ HeadlessWebView 초기화
   └─ callback 함수 WebView에 주입
       │
       ▼
3. "started" 이벤트 발생 (네이티브 → 브릿지)
4. "init" 트리거 발생 (WebView 콜백 실행) ◄── 자동
5. 태스크 실행 중...

라이프사이클 트리거 플로우

1. 앱 포그라운드/백그라운드 전환 감지
   - Android: OnActivityEntersForeground/OnActivityEntersBackground
   - iOS: willEnterForegroundNotification/didEnterBackgroundNotification

2. 실행 중인 태스크 확인

3. triggers 배열에 해당 트리거가 포함되어 있는지 확인
   │
   ├─ 포함됨 → HeadlessWebView에서 callback 실행
   │            "trigger" 이벤트 발생
   │
   └─ 포함 안 됨 → 무시

※ init/terminate는 triggers 배열과 무관하게 항상 호출됨

종료 플로우

1. stopTask() 호출 또는 시스템에 의한 종료
   │
   ▼
2. "terminate" 트리거 발생 (WebView 콜백 실행) ◄── 자동
   │
   ▼
3. "terminating" 이벤트 발생 (네이티브 → 브릿지, best-effort)
   │
   ▼
4. HeadlessWebView 정리
   │
   ▼
5. "stopped" 이벤트 발생

비정상 종료 감지

1. 앱이 강제 종료됨
   - isRunning=true 상태로 저장됨
   - terminate 트리거 호출되지 않음 (프로세스 즉시 kill)

2. 앱 재시작 시
   │
   ▼
3. TaskManager가 이전 상태 복원
   │
   ▼
4. isRunning=true인 태스크 감지
   │
   ▼
5. "terminated" 이벤트 발생
   - type: 'terminated'
   - reason: 'unexpected'
   - lastStartedAt: 이전 시작 시간

※ 비정상 종료 시에는 terminate 트리거가 호출되지 않으므로
   중요한 데이터는 app_background 트리거에서 저장하는 것을 권장

제한사항

1. 클로저 변수 사용 불가

callback 함수는 toString()으로 변환되어 WebView에 주입됩니다. 외부 스코프 변수는 WebView에서 접근할 수 없습니다.

// ❌ 작동 안 함
const config = { url: 'https://api.com' };
callback: (trigger, data) => {
  fetch(config.url);  // config is undefined
}

// ✅ 올바른 방법
callback: (trigger, data) => {
  fetch('https://api.com');
}

2. TypeScript 지원

TypeScript 타입 어노테이션은 컴파일 시 제거되므로 정상 작동합니다.

// ✅ 정상 작동
callback: (trigger: TriggerType, data: TriggerData) => {
  // ...
}

3. 비동기 콜백

async/await 사용 가능합니다.

// ✅ 정상 작동
callback: async (trigger, data) => {
  const response = await fetch('https://api.com');
  // ...
}

4. 네트워크 요청

Headless WebView에서 fetch, XMLHttpRequest, WebSocket 사용 가능합니다.

라이선스

MIT

Keywords

react-native

FAQs

Package last updated on 04 Feb 2026

Related posts