📚 Reference


📜 Chapter


Next.js와 통신


방향 설명 주요 코드
RN → Web (송신) React Native에서 Next.js 웹으로 데이터 전송 webViewRef.current.postMessage(JSON.stringify(data))
Web → RN (송신) Next.js 웹에서 React Native로 데이터 전송 window.ReactNativeWebView.postMessage(JSON.stringify(data))
RN 수신 onMessage 이벤트로 웹에서 보낸 데이터 수신 onMessage={(e) => handle(JSON.parse(e.nativeEvent.data))}
Web 수신 window.addEventListener('message', handler) 로 RN이 보낸 데이터 수신 event.data로 접근

RN(WebView) 쪽 코드


// React Native (Expo도 동일)
import React, { useRef, useCallback } from 'react';
import { View } from 'react-native';
import { WebView, WebViewMessageEvent } from 'react-native-webview';

type BusMsg = { type: string; payload?: any };

export default function MyWebView() {
  const webRef = useRef<WebView>(null);

  // Web -> RN
  const onMessage = useCallback((e: WebViewMessageEvent) => {
    try {
      const msg = JSON.parse(e.nativeEvent.data) as BusMsg;
      switch (msg.type) {
        case 'HELLO_FROM_WEB':
          console.log('웹이 보낸 메시지:', msg.payload);
          // 필요시 네이티브 로직 실행 후 웹에 응답
          sendToWeb({ type: 'PONG', payload: { ok: true } });
          break;
        case 'OPEN_BOTTOM_SHEET':
          // 예: 바텀시트 열기
          break;
      }
    } catch {
      // 문자열이 JSON이 아닐 수도 있으니 방어
      console.warn('Invalid message from web:', e.nativeEvent.data);
    }
  }, []);

  // RN -> Web
  const sendToWeb = useCallback((msg: BusMsg) => {
    // 방법 A) postMessage (권장, 지원되는 버전이라면)
    webRef.current?.postMessage(JSON.stringify(msg));

    // 방법 B) injectJavaScript 로 message 이벤트 디스패치
    // webRef.current?.injectJavaScript(`
    //   window.dispatchEvent(new MessageEvent('message', { data: ${JSON.stringify(JSON.stringify(msg))} }));
    //   true;
    // `);
  }, []);

  // 최초 핸드셰이크(웹 DOM 준비 후에 받도록 약간 지연)
  const onLoadEnd = () => {
    sendToWeb({ type: 'PING', payload: { platform: 'react-native' } });
  };

  return (
    <View style={{ flex: 1 }}>
      <WebView
        ref={webRef}
        source={{ uri: '<https://your-next-app.example.com/mobile>' }}
        onMessage={onMessage}
        onLoadEnd={onLoadEnd}
        // 인증/쿠키 관련 옵션들
        sharedCookiesEnabled
        thirdPartyCookiesEnabled
        // (선택) 외부 링크 열기, 특정 URL 인터셉트 등
        // onShouldStartLoadWithRequest={(req) => { ...; return true; }}
      />
    </View>
  );
}