플러터 앱에서 동작하는 웹뷰를 개발하는데 푸시메세지 터치시 웹뷰의 특정페이지로 이동하는 기능을 개발해야 했다.
구글링을 하다가 window.postMessage 메서드를 통해 앱과 웹뷰가 통신할 수 있다는 사실을 알게되었고 구현을 시작했다.
MDN에 따르면 window.postMessage() 메서드는 window object 사이에서 안전하게 cross-origin 통신을 할 수 있게 해준다고 나와있다.
targetWindow.postMessage(message, targetOrigin, [transfer]);
- targetWindow: 메세지를 전달 받은 window
- message: 다른 window에 보내질 데이터
- targetOrigin: 다른 window의 origin을 지정. 민감한 정보를 다룰때는 지정해줌으로서 탈취를 막을 수 있다.
- transfer: transfer 객체
이제 코드를 살펴보자
플러터 다트문법은 모르지만 챗지피티에게 어떻게 호출해야하는지 물어봤다.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('WebView with Push Notifications'),
),
body: InAppWebView(
initialUrlRequest: URLRequest(
url: Uri.parse('YOUR_WEBVIEW_URL_HERE'),
),
onWebViewCreated: (controller) {
_webViewController = controller;
},
onLoadStop: (controller, url) {
// 웹뷰가 로드된 후에 JavaScript 코드를 실행하여 웹뷰로 메시지를 전달할 수 있음
controller.evaluateJavascript(
source: 'window.postMessage({ type: "pushNotification", message: "Hello from Flutter" }, "*");',
);
},
),
);
}
우리가 주목해야하는 곳은 onLoadStop 프로퍼티이다.
저 프로퍼티에서 window.postMessage를 사용하여 웹뷰쪽에서 로직을 작성할 수 있도록 데이터들을 넘겨주면 된다.
// App.tsx
useEffect(() => {
window.addEventListener(
"message",
(event: { data }) => {
handlePushNotification();
}
);
return () => {
window.removeEventListener('message', handlePushNotification);
};
}, []);
웹앱의 진입시점에서 푸시메세지 수신 로직을 추가한다.
event객체에는 data프로퍼티가 있고 여기에 앱에서 전달한 데이터들이 들어있다. 그 외에는 origin, source가 있다.
handlePushNotification 함수 안에 페이지 이동 라우팅 로직을 추가하면 우리가 원하는 푸시메세지 클릭시 페이지가 이동하게 만들수 있다!
물론 그 뿐만 아니라 웹뷰에서 처리할 수 있는 다양한 기능들도 추가할 수 있을것이다. (클라이언트 상태 설정 등등)