네이티브 앱과 웹앱 간 양방향 통신 구현
Vue/React/Angular 웹앱
↓ (JavaScript)
WebBridge.request()
↓
Bridge Channel
↓
네이티브 앱
↓
Native 기능
↓
응답 반환
↓
Promise resolve
↓
웹앱 수신
// JavaScript에서 Native로 메시지 전송
const bridge = new WebBridge();
// 위치 요청
const location = await bridge.getLocation();
console.log(location); // { lat: 37.123, lng: 127.456 }
// 1. 요청 ID 생성
const requestId = generateId();
// 2. Promise 생성 및 저장
const promise = new Promise((resolve, reject) => {
pendingRequests[requestId] = { resolve, reject };
});
// 3. Native로 메시지 전송
window.NativeBridge.postMessage(JSON.stringify({
action: 'GET_LOCATION',
payload: { requestId }
}));
// 4. Promise 반환 (응답 대기)
return promise;
async request(action, payload = {}) {
const requestId = this.generateId();
return new Promise((resolve, reject) => {
// 타임아웃 설정
const timeout = setTimeout(() => {
delete this.pendingRequests[requestId];
reject(new Error('Request timeout'));
}, this.timeout);
// 요청 저장
this.pendingRequests[requestId] = {
resolve,
reject,
timeout
};
// Native로 전송
this.sendToNative(action, { ...payload, requestId });
});
}
handleResponse(requestId, status, data) {
const request = this.pendingRequests[requestId];
if (!request) return;
clearTimeout(request.timeout);
delete this.pendingRequests[requestId];
if (status === 'SUCCESS') {
request.resolve(data);
} else {
request.reject(new Error(data.message));
}
}
try {
const location = await bridge.getLocation();
} catch (error) {
if (error.message === 'Request timeout') {
console.log('요청 시간 초과');
}
}
try {
const location = await bridge.getLocation();
} catch (error) {
if (error.message.includes('permission')) {
console.log('위치 권한이 필요합니다');
}
}
<script setup>
import { ref } from 'vue';
import WebBridge from './bridge';
const bridge = new WebBridge();
const location = ref(null);
const error = ref(null);
async function getLocation() {
try {
location.value = await bridge.getLocation();
} catch (err) {
error.value = err.message;
}
}
</script>
import { useState } from 'react';
import WebBridge from './bridge';
const bridge = new WebBridge();
function App() {
const [location, setLocation] = useState(null);
const getLocation = async () => {
try {
const loc = await bridge.getLocation();
setLocation(loc);
} catch (error) {
console.error(error);
}
};
return <button onClick={getLocation}>위치</button>;
}
{
"action": "GET_LOCATION",
"payload": {
"requestId": "req_1234567890",
// 기타 파라미터
}
}
{
"requestId": "req_1234567890",
"status": "SUCCESS",
"data": {
"lat": 37.123,
"lng": 127.456,
"accuracy": 10
}
}