앱에서 웹뷰 구현하기

dudgus5766·2023년 1월 26일
1

Junior Developer

목록 보기
14/18

앱 개발을 하다보면 웹뷰(Webview)를 띄워야할 상황이 생깁니다.(지금이 바로 그 순간..) 앱 특성 상 웹보다 한계가 많기 때문인데, 저의 경우에는 게시글의 URL 클릭 시 페이지를 웹뷰로 보여주기 위해 사용하였습니다.

📍react-native-webview

앱 내 웹뷰를 위해 react-native-webview 라이브러리를 사용했습니다.

🔗 npm 링크

웹뷰를 띄우는 방법을 크게 2가지로 나눠 살펴보면,

사용 방법

1️⃣ uri로 웹 연결

import React from 'react';
import { WebView } from 'react-native-webview';

const App = () => {  

	return (
    <Webview
			source={{uri: 'https:...중략'}}
    />
  );
};

2️⃣ inline HTML 사용

import React from 'react';
import { WebView } from 'react-native-webview';

const App = () => {  

	return (
    <Webview
			originWhitelist={['*']}
      source={{html: '<h1>Hello world</h1>'}}    />
  );
};

📍WebView 사용

먼저 게시글 상세화면에 집입했을 때 웹 URL가 있다면 URL를 간략하게 보여주는 UI를 제작했고, UI 컴포넌트를 클릭했을 때 해당 웹 URL을 웹뷰로 보여주는 로직입니다.

(사용한 props메서드는 주석으로 설명을 적어놨습니다.)

//communityDetailScreen.js

<WebView
  ref={wvRef} //웹뷰 컴포넌트의 새로고침이나 navigation 등을 처리하기 위해 ref를 사용
  originWhitelist={['*']}
  source={{ uri: `${loadWebUrl.trim()}` }} //uri를 사용
  style={{ flex: 1 }}
  injectedJavaScript={eventScript} //View가 로드될 때 자바스크립트를 웹페이지에 주입

  // WebView가 window.postMessage를 call하면 호출
  onMessage={(event) => { 
    handleMessage(event);
  }}

	...중략
 
	// WebView 로딩이 시작되거나 끝나면 호출
  onNavigationStateChange={(navState) => {

	  ...중략

	setCanGoback(navState.canGoBack); // 뒤로 갈 수 있는 체크하는 state
    setCanGoForward(navState.canGoForward); // 앞으로 갈 수 있는 체크하는 state
	setCurrentWebUrl(navState.url); // 현재 url 저장 -> 외부 링크(ex, 사파리)로 사용자가 이동하려고 할 때 필요한 url

  }}

	// WebView가 시작될 때 호출
  onShouldStartLoadWithRequest={(request) => {

		...중략

  }}
  onError={() => {
    setIsWebPageError(true);
  }}
/>;

웹뷰에 대한 적용이 끝났다면, 이제 웹뷰를 감싸는 UI를 만들어보겠습니다.

<IconBtn
    iconName={canGoback ? 'communityBrowserBackActive' : 'communityBrowserBack'}
    onPress={() => {
        wvRef && wvRef.current.goBack();
    }}
/>
<IconBtn
    iconName={canGoForward ? 'communityBrowserForwardActive' : 'communityBrowserForward'}
    onPress={() => {
        wvRef && wvRef.current.goForward();
    }}
/>
<IconBtn
    iconName={isWebPageError ? 'communityIconDisableBrowserRefresh' : 'communityBrowserRefresh'}
    onPress={() => {
        wvRef && wvRef.current.reload();
    }}
/>
<IconBtn
    iconName={isWebPageError ? 'communityIconDisableBrowserExternal' : 'communityBrowserExternalBrowser'}
    onPress={async () => {
        try {
            await Linking.openURL(currentWebUrl);
        } catch (e) {
            AppUtils.CONSOLE_ERR(e.message);
        }
    }}
/>

🚨 android Intent 처리

웹뷰를 이용할 경우 (특히 안드로이드에서) Intent가 동작하지 않는 경우가 있습니다. 대표적으로 많이 사용하는 카카오링크 공유하기 기능을 사용할 때 카카오 JavaScript SDK에서는Intent로 카카오 링크를 전송하는데 웹뷰에 이 기능이 구현되어있지 않다면 에러를 내뱉습니다🤮..

react-native-send-intent 설치

npm i react-native-send-intent
yarn add react-native-send-intent

설치 후 안드로이드 세팅을 끝내면 onShouldStartLoadWithRequest 함수에 intent 링크 로직을 추가해주면 됩니다.

const onShouldStartLoadWithRequest = (request) => {
    if (event.url.startsWith('http://') || event.url.startsWith('https://') || event.url.startsWith('about:blank')) {
      return true;
    }
    if (Platform.OS === 'android' && request.url.indexOf('intent') !== -1) {
      SendIntentAndroid.openChromeIntent(event.url)
        .then(isOpened => {
          if (!isOpened) {
            // console.log('앱 실행 실패')
          }
        })
        .catch(err => {
          console.log(err);});

			return false;

      ...중략

마치며

최근 앱이지만 웹뷰로 운영되는 서비스가 많이 보입니다. 앱 업데이트 없이 배포 + 앱 반영이 가능하다보니 앱을 사용하는 사용자들의 빈번한 업데이트를 막을 수 있는 큰 장점 때문인 것 같습니다. 그렇지만..웹뷰 또한 한계는 존재하니(웹으로 진입할 때 뜨는 하얀화면 등등)…. 결국 앱과 웹 둘 다 잘하고 싶다는 뜻입니다🥶

그래서 다음에는 웹으로 사이드 프로젝트를 진행 + 페이지를 띄운 후에 앱에서 웹뷰로 사이드 프로젝트를 실행시키는 작업을 진행할 생각입니다. 화이팅!💪


참고📚


https://www.npmjs.com/package/react-native-webview

https://kyounghwan01.github.io/blog/React/react-native/react-native-webview/#rn-프로젝트-및-웹-뷰-라이브러리-설치

https://www.mrlatte.net/code/2020/12/18/react-native-webview-intent

profile
RN App Developer

0개의 댓글