React Native로 웹뷰 앱 배포하기 - 2. React Native ➡️ 웹뷰 이벤트 보내기

Jiwoo JEONG·2022년 8월 7일
3

React Native WebView

목록 보기
2/2
post-thumbnail

지난 1편에 이어 2편은 React Native에서 웹뷰로 이벤트를 보내는 것을 포스팅할 것이다.

RNEventPropsType

웹뷰와 React Native에서 들어온 Event를 처리하기 위해 interface를 사용하기 위해 아래와 같은 type을 만들었다.

export interface RNEventPropsType<U = any, T = any> {
  event: U;
  data?: T;
}

다음과 같은 RNEventEnum을 가정한다.

export enum RNEventEnum {
	Example:'Example';
}

웹뷰의 RNListener

웹뷰에서 React Native에서 보내온 event를 handling하는 Listener 컴포넌트를 만들었다.
기본 컨셉은 다음과 같다.
1. iOS는 window 객체, android는 document 객체에 event listener를 등록한다.
2. event명에 따라 핸들링할 수 있도록 switch-case로 핸들링 함수를 실행하도록 한다.
3. 실행할 핸들링 함수를 구현한다.

const RNListener:React.FC = () => {

	//핸들링 함수
    const handleExaple = (parsed:RNEventPropsType<RNEventEnum, any>) => {
    	...
        // 함수 구현
    }

	// event Listener의 event명(약속된 RNEventEnum)에 따른 핸들링 함수 실행
	const listener = (receive:{data:string}) => {
    	if(receive){
        	const parsed:RNEventPropsType<RNEventEnum, any> = JSON.parse(receive.data);
            swtich(parsed.event){
            	case RNEventEnum.Example:
                	handleExample(parsed);
                    return;
                ...
            }
        }
    }

	//Event Listener 등록
	useEffect(() => {
      	if (window.ReactNativeWebView) {
        	/** android */
        	document.addEventListener('message', listener);
	        /** ios */
    	    window.addEventListener('message', listener);
      	}
  }, []);
  return <React.Fragment/>;
}

React Native에서 이벤트 보내기

React-Native-Webview는 postMessage function을 통해 웹뷰로 이벤트를 보낼 수 있도록 제공한다.
따라서 webViewRef를 만들어 WebView Component를 참조하고 다음과 같이 이벤트를 보낸다.

webViewRef.current?.postMessage({
	event: RNEventEnum.Example,
    data:{
	    ... // 웹뷰에서 처리를 위해 필요한 데이터
    },
})

웹뷰에서 RN인지 어떻게 알지?

React Native WebView에 userAgent를 설정할 수 있는 것이 있다. 기존의 userAgent에 [RNWebView]라는 것을 concat했고, 웹뷰에서 userAgent에 [RNWebView]이 있으면 RNAtom recoil을 'ios' 혹은 'android'로 값을 할당해줬다. ios인지 android인지도 userAgent를 보고 할당했다.

React Native userAgent 설정
...
<WebView 
	...
    userAgent={`${기존 userAgent}[RNWebView]`}
    ...
/>
...
웹뷰에서의 RN 설정
...
  const setRN = useSetRecoilState(RNAtom);
  export const isRNWebView = () => {
    return navigator.userAgent.match(/RNWebView/);
  };

  export const isAndroid = () => {
    return navigator.userAgent.match(/Android/);
  };

  export const isIOS = () => {
    return navigator.userAgent.match(/(iPod|iPhone|iPad)/);
  };


  useEffect(() => {
    if (isRNWebView()) {
      if (isIOS()) {
        setRN('ios');
      } else {
        setRN('android');
      }
    }
  }, []);
...

마무리

1편과 2편을 통해 React Native ↔️ 웹뷰 간의 이벤트 통신을 설명했다.
위를 통해 구현한 것들 중 하나를 예시로 들면

  • 웹에서 카카오 로그인과 앱에서 카카오 로그인은 intent 등의 이슈로 다르게 하여야했다. 그래서 앱 내 웹뷰에서 카카오 로그인 버튼을 누르면 RNEvent를 웹뷰에서 RN으로 보냈다. 그러면 React Native 모듈을 통해 구현 카카오 로그인을 RN에서 처리하고 백앤드에서 받은 token을 다시 웹뷰로 보내는 방식으로 구현하였다.

시스템 만드는 것은 구조를 생각하는 것은 어려운데 막상 만들고 잘 돌아가는 것을 보면 재밌다 🥳🥳

profile
FE Developer as Efficiency Maker

0개의 댓글