웹뷰에서 플러터 앱 전환을 하고 있었다. 100% 마이그레이션 프로젝트가 아닌, 2주 스프린트로 페이지 단위 마이그레이션이다보니, 기존엔 웹에서 호출하던 api를 네이티브 앱에서 호출하게 되면서 웹에서 앱과의 통신을 통해 웹으로 값을 받아와야 할 일이 많았음
참고로 webview bridge란, 아래와 같은 구조로 webview와 android, ios와의 통신을 위해 만들어진 js용 interface이다. 웹뷰에서 네이티브 동작(메서드, 즉 네이티브 api)를 직접 호출하는 것이 불가능 하기 때문에 bridge라는 통로를 통해 web에서 네이티브 동작을 호출해야 했다.
script
태그를 사용해 javascript 파일을 로드할 때 해당 스크립트는 기본적으로 window 객체의 컨텍스트에서 실행된다.
따라서 스크립트 내에서 정의된 모든 변수와 함수는 window 객체에 바인딩 된다.
// index.html
<script defer type="text/javascript" src="/js/test.plugin.js"></script>
아래와 같이 window.test에 test객체를 바인딩 하고있다. 그래서 window.test.plugin객체에 정의된 프로퍼티에 접근할 수 있는것.
// test.plugin
const test = {
plugin: { ... }
}
window.test = test;
ui컴포넌트의 핸들러 함수 로직은 아래와 같다.
// Test.tsx
const handleClick = () => {
window.test.plugin.openView();
};
앱에서 정의하는 플러터 함수에 대해서 정의해준다. (앱으로 부터 전달받은 파람을 갖고 함수를 정의해준다.)
// test.plugin.js
// web에서 정의하는 플러그인 함수
function openView() {
const localDb = getLocalDb();
const message = {
command: "openView",
callback: "onReceiveToOpenView",
};
if (localDb) {
// ...생략
const params = {
...message,
};
console.log("message", params);
try {
flutterCallHandler(params);
} catch (error) {
console.error(error);
}
}
}
// app에서 호출하는 콜백 함수
function onReceiveToOpenView(data) {
console.log("onReceiveToOpenView", data);
const detail = getPayload(data);
const event = new CustomEvent("onReceiveToOpenView", {
detail,
});
// 여기에서 이벤트를 문서의 dom트리에 전파
document.dispatchEvent(event);
}
그리고 ui컴포넌트 로직을 아래와 같이 작성해주면 dispatchEvent
로 인해서 해당 핸들러 함수가 동작하게 된다.
// MobileEventHandlerTester.jsx
useEffect(() => {
document.addEventListener("onReceiveToOpenView", handleReceiveToOpenView);
return () => {
document.removeEventListener("onReceiveToOpenView", handleReceiveToOpenView);
};
}, []);
const handleReceiveToOpenView = ({ detail }) => {
const localDb = getLocalDb();
if (localDb) {
try {
setDataToLocalDb({
...
});
} catch (error) {
console.error(error);
return;
}
}
};