브릿지란?
정의:서로 다른 기술 스택 또는 실행 환경에서 동작하는 코드들이 데이터를 주고받을 수 있게 해주는 연결 계층
- react-native는 자바스크립트 엔진과 네이티브 사이에 통신을 하는데 이러한 방식을 브릿지라고 말한다.
- 마찬가지로 react-native와 웹뷰 내의 react 애플리케이션간의 통신도 브릿지라고 할 수 있다.
이번 글에서는 react ↔ react-native 사이의 브릿지를 구현하고 활용 방법도 작성하려고 한다.
구현 방법
react-native
import WebView from 'react-native-webview'; export default function Screen() { const webViewRef = useRef(null); // 웹으로부터 수신된 메세지 처리 const handleMessage = async (event) => { try { const parsedData = JSON.parse(event.nativeEvent.data); if (data.type === 'GREETING_FROM_WEB') { Alert.alert('[RN] 웹이 보낸 인사', data.payload); } else if() { // 다른 타입 처리 // ... } } catch (error) { console.error('Error handling message:', error); } }; // 웹으로 메세지 송신 const sendToWeb = () => { const msg = { type: 'GREETING_FROM_RN', payload: 'React Native에서 인사합니다 👋', }; webviewRef.current?.postMessage(JSON.stringify(msg)); }; return ( <WebView ref={webViewRef} onMessage={handleMessage} source={{ uri }} /> ) }
- 웹에 메세지 보내기:
webviewRef.current?.postMessage(...)
- 웹으로부터 메세지 수신:
<WebView onMessage={handleOnMessage} />
react
// RN으로 메세지 송신 const sendToRN = (msg) => { window.ReactNativeWebView.postMessage(JSON.stringify(msg)); }; // RN으로부터 메세지 수신 const messageReciver = (event) => { const msg = JSON.parse(event.data); if (msg.type === "GREETING_FROM_RN") { alert("[웹] RN이 보낸 인사: " + msg.payload); } }; useEffect(() => { document.addEventListener('message', messageReciver); return () => { document.removeEventListener('message', messageReciver); }; }, [messageReciver]);
- RN으로 메세지 송신:
window.ReactNativeWebView.postMessage(…)
- RN으로부터 메세지 수신:
document.addEventListener("message", callback)
응용
#1. 웹 서비스와 앱 서비스의 분기
요구사항
- 웹과 앱에서 각각 로그인 가능한 서비스에서 어떤 플랫폼에서 로그인하였는지 알 수 있어야한다.
해결방법
- 사용자가 앱을 실행한다.
- push_token을 생성하고 웹으로 송신한다.
- 웹에서는 push_token을 받아서 상태로 저장한다.
- 로그인 페이지 진입 후 로그인 api 요청시 push_token을 포함한다.
→ push_token이 포함된 경우라면 모바일 앱에서 로그인한 사용자임을 알 수 있다.
+로그인 페이지 진입시, react-native에 push_token을 요청하는 로직까지 구현할 수 있다
구현코드
// 앱 실행시 push_token을 송신하기 위한 effect useEffect(() => { const initializeToken = async () => { await NotificationService.createDefaultChannel(); const newToken = await NotificationService.requestPermissions(); if (newToken && webViewRef.current) { webViewRef.current.postMessage(JSON.stringify({ type: 'expoToken', token: newToken })); } }; initializeToken(); }, []);
#2. 푸시 알림 클릭시 딥링크 처리
요구사항
- 백그라운드 상태에서 푸시 알림을 클릭하여 앱을 실행했을때, 특정 페이지로 바로 이동해야한다.
- notifee를 사용중이다
해결방법
- 사용자가 푸시 알림을 클릭한다.
- notifee.onBackgroundEvent 핸들러에서 이벤트를 수신하고, 이벤트에서 필요한 정보들을 postMessage를 통해 웹쪽으로 송신한다
- 정보를 수신한 웹에서는 필요한 페이지로 네비게이션 처리한다.
구현코드
const handleNotificationData = (data) => { if (type && patient_id && webViewRef.current) { webViewRef.current.postMessage(JSON.stringify(data)); } }; useEffect(() => notifee.onBackgroundEvent(async (event) => { if (event.type === EventType.PRESS) { // 필요한 정보들 추출 const data = event.detail.notification.data; handleNotificationData(daa); } }); ,[])