React Native에서 WebView postMessage 타이밍 이슈 해결
문제 상황
레거시 웹 서비스를 React Native로 감싸는 하이브리드 앱을 개발하던 중, WebView에서 Native로 보내는 postMessage가 간헐적으로 유실되는 현상이 발생했다. 특히 Android에서 재현율이 높았다.
// WebView 내부 (웹)
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'LOGIN_SUCCESS',
token: 'xxx'
}));
원인 분석
WebView가 로드되자마자 postMessage를 호출하면, Native 쪽 이벤트 리스너가 아직 준비되지 않은 상태였다. onLoadEnd가 호출되어도 JavaScript 컨텍스트가 완전히 초기화되지 않은 경우가 있었다.
해결 방법
injectedJavaScript를 사용해 Native가 준비되었음을 WebView에 알리는 방식으로 변경했다.
<WebView
source={{ uri: webUrl }}
injectedJavaScript={`
window.isReactNativeReady = true;
window.dispatchEvent(new Event('reactNativeReady'));
true;
`}
onMessage={(event) => {
const data = JSON.parse(event.nativeEvent.data);
handleMessage(data);
}}
/>
웹 쪽에서는 이벤트를 기다린 후 메시지를 전송하도록 수정했다.
// 웹 쪽 코드
function sendToNative(data) {
if (window.isReactNativeReady) {
window.ReactNativeWebView.postMessage(JSON.stringify(data));
} else {
window.addEventListener('reactNativeReady', () => {
window.ReactNativeWebView.postMessage(JSON.stringify(data));
}, { once: true });
}
}
결과
메시지 유실 문제가 완전히 해결되었다. 양방향 통신이 필요한 경우 handshake 패턴을 구현하는 것이 안전하다는 것을 배웠다.