The complete guide to React Native WebView > 앱개발

앱개발

The complete guide to React Native WebView 정보

The complete guide to React Native WebView

본문

간단히 말해서 WebView 는 React Native 앱에서 웹 페이지를 로드하는 데 사용되는 구성 요소입니다. 이전에는 React Native 에서 즉시 사용할 수 있었지만 이제 React Native 코어에서 제거되어 React Native Community 라이브러리의 구성 요소로 추가됩니다. 자세한 내용은 The Slimmening proposal을 참조하십시오. 이제 react-native-webview 라이브러리를 설치해야 합니다.

Platforms supported

저는 React Native 개발자이기도 하므로 앱에서 사용할 라이브러리에 대해 플랫폼간 지원이 얼마나 중요한지 이해합니다. 앱에서 라이브러리를 사용해야 할 때마다 가장 먼저 묻는 것은 크로스 플랫폼인지 여부입니다. react-native-webview 에 대해 걱정할 필요가 없습니다. iOS 및 Android 플랫폼을 모두 지원합니다.

참고: React Native WebView 에 대한 Expo 지원은 Expo SDK v33.0.0로 시작되었습니다.

Getting started

먼저 아래 명령을 실행하여 라이브러리를 설치해야합니다.

// with yarn
$ yarn add react-native-webview

// with npm
$ npm install --save react-native-webview

그런 다음 종속성을 연결하십시오. react-native 0.60 부터 자동 연결은 연결 프로세스를 처리하지만 pod install를 실행하는 것을 잊지 마십시오.

React 네이티브 Objective-C, Swift, Java 또는 Kotlin 코드를 포함하는 네이티브 모듈은 컴파일러가 앱에 포함할 수 있도록 link되어야합니다.

연결하려면 아래 명령을 실행하십시오.

$ react-native link react-native-webview

For iOS:

ios/디렉토리에서 CocoaPods 를 사용하는 경우 다음을 실행하십시오.

$ pod install

For Android:

react-native-webview 버전≥ 6.X.X 를 사용하는 경우 android/gradle.properties를 편집하고 아래 두 줄을 추가하여 프로젝트에서 AndroidX 를 사용하도록 설정하십시오.

android.useAndroidX=true
android.enableJetifier=true

참고 : React Native WebView 를 제거해야하는 경우 react-native unlink react-native-webview를 실행하여 링크를 해제하십시오.

성공적으로 설치했으면 합니다. 어딘가에 갇힌 경우 공식 설치 안내서를 참조하십시오.

이제 간단한 것부터 고급까지 WebView 의 유용한 예와 그 이후의 사용법을 보여 드리겠습니다.

Basic quickstart

WebView 의 기본 속성을 검토하여 시작하겠습니다.

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

class MyWeb extends Component {
  render() {
    return (
      <WebView
        source={{ uri: 'https://logrocket.com/' }}
        style={{ marginTop: 20 }}
      />
    );
  }
}

먼저 source속성은 URL 또는 HTML 에서 컨텐츠를 가져 오는 데 사용됩니다. URL 로 웹 페이지를 로드하려면 아래와 같이 uri 속성을 가진 객체를 전달해야 합니다.

<WebView
  source={{ uri: 'https://logrocket.com/' }}
/>

Loading inline HTML

위의 URL 로 웹 페이지를 로드하는 방법을 보았습니다. 그러나 HTML 을 직접 로드하려는 경우 아래와 같이 WebView 의 source 속성에서 html 속성을 사용할 수 있습니다.

<WebView
  originWhitelist={['*']}
  source={{ html: '<h1>Hello world</h1>' }}
/>

참고 : HTML 소스를 설정하려면 originWhiteList 속성을 ['*']로 설정해야 합니다.

What is the originWhitelist property anyway?

간단히 말해 originWhitelist속성은 사용자가 WebView 에서 탐색 할 수 있는 위치를 제어합니다. 문자열 배열이 필요하며 기본 whitelisted원점은 http:// 및 https://입니다.

예를 들어, 사용자가 https:// 또는 git://로 시작하는 URI 만 탐색할 수 있도록 하려면 다음과 같이 구현하십시오.

<WebView
  source={{ uri: 'https://logrocket.com/' }}
  originWhitelist={['https://*', 'git://*']}
/>

다른 예를 살펴 보겠습니다.

Loading local HTML files

때로는 WebView 에 로드하려는 HTML 파일이 앱과 함께 로컬로 있습니다.

iOS 에서는 아래 예제와 같이 다른 자산과 마찬가지로 HTML 파일을 가져 오기만 하면 됩니다.

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

const myHtmlFile = require("./my-asset-folder/local-site.html");

class MyWeb extends Component {
  render() {
    return (
      <WebView source={myHtmlFile} />
    );
  }
}

매우 간단합니다. 정확히 예상했던 것입니다.

그러나 Android 에서는 HTML 파일을 Android 자산 디렉토리에 넣어야합니다. 예를 들어, 안드로이드 앱에 logrocket.html이라는 파일을 로드하려면 안드로이드 자산 디렉토리인 yourProject/android/src/main/assets/로 이동해야 합니다.

그런 다음 아래 예제와 같이 HTML 파일을 로드할 수 있습니다.

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

class MyWeb extends Component {
  render() {
    return (
      <WebView source={{ uri: "file:///android_asset/logrocket.html" }} />
    );
  }
}

Controlling navigation state changes by user

onNavigationStateChange는 WebView 로딩이 시작되거나 종료될 때 호출되는 함수입니다.

탐색 상태 변경을 제어하고 WebView 에서 탐색하는 것과 다른 작업을 수행해야 하는 경우 이를 수행하는 완벽한 방법입니다. 예를 들면 다음과 같습니다.

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

class MyWeb extends Component {
  webview = null;

  render() {
    return (
      <WebView
        ref={ref => (this.webview = ref)}
        source={{ uri: 'https://logrocket.com/' }}
        onNavigationStateChange={this.handleWebViewNavigationStateChange}
      />
    );
  }

  handleWebViewNavigationStateChange = newNavState => {
    // newNavState looks something like this:
    // {
    //   url?: string;
    //   title?: string;
    //   loading?: boolean;
    //   canGoBack?: boolean;
    //   canGoForward?: boolean;
    // }
    const { url } = newNavState;
    if (!url) return;

    // handle certain doctypes
    if (url.includes('.pdf')) {
      this.webview.stopLoading();
      // open a modal with the PDF viewer
    }

    // one way to handle a successful form submit is via query strings
    if (url.includes('?message=success')) {
      this.webview.stopLoading();
      // maybe close this view?
    }

    // one way to handle errors is via query string
    if (url.includes('?errors=true')) {
      this.webview.stopLoading();
    }

    // redirect somewhere else
    if (url.includes('google.com')) {
      const newURL = 'https://logrocket.com/';
      const redirectTo = 'window.location = "' + newURL + '"';
      this.webview.injectJavaScript(redirectTo);
    }
  };
}

이 메소드는 해시 URL 변경시 호출되지 않습니다 (예: [https://logrocket.com/users#list](https://logrocket.com/users#list)에서 [https:/ /logrocket.com/users#help](https://logrocket.com/users#help)). 그러나 버전 8.0.0 부터 iOS 에서 onNavigationStateChange를 사용하면 URL 이 #번 변경될 때 트리거됩니다.

How to add support for file uploads

WebView 에서 파일 업로드를 허용하려면 아래 권한을 추가해야 합니다. 아래에서 작업과 플랫폼으로 구분하여 필요한 것을 정확하게 선택할 수 있습니다.

For iOS:

iOS 를 사용한다면 ios/[project]/Info.plist 파일에 권한을 지정하기만 하면 됩니다.

사진 캡처의 경우:

<key>NSCameraUsageDescription</key>
<string>Take pictures for certain activities</string>

갤러리 선택의 경우:

<key>NSPhotoLibraryUsageDescription</key>
<string>Select pictures for certain activities</string>

비디오 녹화의 경우:

<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for recording videos</string>

For Android:

AndroidManifest.xml에 권한을 추가하십시오. `/Android/app/src/main/AndroidManifest.XML 에 있습니다.

Android 개발을 시작할 때 프로젝트에서 해당 파일을 찾는 데 실제로 문제가 발생했기 때문에 해당 파일 위치를 추가했습니다.

<manifest ...>
  ......

  <!-- this is required only for Android 4.1-5.1 (api 16-22)  -->
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

  ......
</manifest>

<input type="file"/>을 사용한 파일 업로드는 Android 4.4 KitKat 에서 지원되지 않습니다 (자세한 내용은 여기 참조) - 파일 업로드가 지원되는지 확인하려면 isFileUploadSupported()를 사용하여 파일 업로드를 확인할 수 있습니다. 아래 예를 참조하십시오.

WebView.isFileUploadSupported().then(res => {
  if (res === true) {
    // file upload is supported
  } else {
    // file upload is not supported
  }
});

Controlling multiple file uploads

어쨌든 단일 및 다중 파일 업로드를 제어하려면 아래 예제와 같이 input 요소에 다중 속성을 추가하면됩니다.

// multiple file selection
<input type="file" multiple />

// single file selection
<input type="file" />

Adding support for file downloads

예, 사용자가 WebView 에서 파일을 다운로드할 수 있게 하려면 해당 권한을 추가해야 합니다.

For iOS:

iOS 의 경우 ios/[project]/Info.plist 파일에 권한을 지정하기만 하면 됩니다.

갤러리에 저장:

<key>NSPhotoLibraryAddUsageDescription</key>
<string>Save pictures for certain activities.</string>

For Android:

/android/app/src/main/AndroidManifest.xml에 있는 AndroidManifest.xml에 권한을 추가하십시오:

<manifest ...>
  ......

  <!-- this is required to save files on Android  -->
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

  ......
</manifest>

How to inject JavaScript in WebView

때로는 WebView 로 JavaScript 를 실행하려는 상황에 처할 수도 있습니다. 이 경우 WebView 는 다음과 같은 세 가지 방법을 제공합니다.

  1. injectedJavaScript prop
  2. injectJavaScript method
  3. postMessage method 와 onMessage prop

The injectedJavaScript prop

이 메소드는 웹 페이지가 처음으로 로드된 직후 제공된 스크립트를 실행합니다. 페이지가 다시 로드되거나 사용자가 이동하더라도 한 번만 실행됩니다. 예를 들면 다음과 같습니다.

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

export default class App extends Component {
  render() {
    const myScript = `
      document.body.style.backgroundColor = 'red';
      setTimeout(function() { window.alert('hi') }, 2000);
      true; // note: this is required, or you'll sometimes get silent failures
    `;
    return (
      <View style={{ flex: 1 }}>
        <WebView
          source={{
            uri:
              'https://github.com/react-native-community/react-native-webview',
          }}
          injectedJavaScript={runFirst}
        />
      </View>
    );
  }
}

참고: 이유는 모르겠지만 공식 문서에 따르면 스크립트 끝에 true;가 필요합니다. 사용하지 않으면 때로는 자동 실패가 발생하므로 포함하는 것이 좋습니다.

따라서 위 스크립트에서 배경색을 빨간색으로 설정하고 2 초 후에 hi를 경고합니다. 아래 이미지에서 볼 수 있습니다. myScript는 페이지가 로드되면 실행됩니다.

injectedJavaScriptpropexample.png

What’s going on internally?

iOS 에서 injectedJavaScript는 WebView 에서 evaluateJavaScript:completionHandler:라는 메소드를 실행합니다. 안드로이드에서 injectedJavaScript는 안드로이드 웹뷰에서 evaluateJavascriptWithFallback이라는 메소드를 실행합니다.

앞서 언급했듯이 injectedJavaScript prop 은 컨텐츠 로드후 실행됩니다. 그러나 컨텐츠를 로드하기 전에 JavaScript 코드를 실행해야 하는 경우 어떻게 해야 합니까?

이를 위해 페이지가 처음 로드되기 전에 JavaScript 코드를 실행하는 injectedJavaScriptBeforeContentLoaded라는 또 다른 소품이 있습니다. 페이지가 다시 로드되거나 사용자가 이동하더라도 한번만 실행됩니다. 코드를 실행하기 전에 창, localStorage 또는 문서에 무엇이든 삽입하려는 경우 이 소품을 사용할 수 있습니다.

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

export default class App extends Component {
  render() {
    const runFirst = `
      window.isNativeApp = true;
      true; // note: this is required, or you'll sometimes get silent failures
    `;
    return (
      <View style={{ flex: 1 }}>
        <WebView
          source={{ uri: 'https://logrocket.com/' }}
          injectedJavaScriptBeforeContentLoaded={runFirst}
        />
      </View>
    );
  }
}

The injectJavaScript method

injectedJavaScript prop 의 단점은 한 번만 실행된다는 것입니다. 그렇기 때문에 WebView 참조에 injectJavaScript라는 메소드를 노출시키는 이유도 있습니다. (이름에 약간의 차이가 있습니다!)

다음은 injectJavaScript 소품을 사용하는 방법입니다.

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

export default class App extends Component {
  render() {
    const run = `
      document.body.style.backgroundColor = 'blue';
      true;
    `;

    setTimeout(() => {
      this.webref.injectJavaScript(run);
    }, 3000);

    return (
      <View style={{ flex: 1 }}>
        <WebView
          ref={r => (this.webref = r)}
          source={{ uri: 'https://logrocket.com/' }}
        />
      </View>
    );
  }
}

3 초 후에 코드가 실행되고 배경이 파란색이됩니다.

injectJavaScriptmethodexample.png

What’s going on internally?

iOS 에서 injectJavaScript는 WebView 의 evaluateJS:andThen:을 호출합니다. Android 에서 injectJavaScript는 Android WebView 의 evaluateJavascriptWithFallback 메소드를 호출합니다.

The window.ReactNativeWebView.postMessage method and onMessage prop

이전 접근법은 prop 을 사용하여 JavaScript 코드를 주입하는 데 실제로 도움이 됩니다. 그러나 웹 페이지가 React Native 코드로 무언가를 보내거나 통신하려면 어떻게해야합니까? 여기서window.ReactNativeWebView.postMessage 및 onMessage prop 을 사용할 수 있습니다.

웹 페이지에 onMessage 또는 window.ReactNativeWebView.postMessage 메소드를 삽입하지 않도록 설정해야합니다.

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

export default class App extends Component {
  render() {
    const html = `
      <html>
      <head></head>
      <body>
        <script>
          setTimeout(function () {
            window.ReactNativeWebView.postMessage("Hello!")
          }, 2000)
        </script>
      </body>
      </html>
    `;

    return (
      <View style={{ flex: 1 }}>
        <WebView
          source={{ html }}
          onMessage={event => {
            alert(event.nativeEvent.data);
          }}
        />
      </View>
    );
  }
}

코드의 결과는 Hello!이며 아래 이미지와 같이 경고합니다.

onMessagepropexample.png

Conclusion

이 기사 전체를 읽으면 React Native WebView 에서 사용할 것보다 더 많은 것을 알고 있다고 말할 수 있습니다. 항상 더 많이 아는 것이 좋습니다.

Plug: LogRocket, a DVR for Web apps

1d0cd1srmyo6nbraspxtvbaxfg.png

LogRocket은 마치 자신의 브라우저에서 발생한 것처럼 문제를 재생할 수 있는 프런트엔드 응용 프로그램 모니터링 솔루션입니다. LogRocket 을 사용하면 오류가 발생하는 이유를 추측하거나 사용자에게 스크린 샷 및 로그 덤프를 요청하는 대신 세션을 재생하여 무엇이 잘못되었는지 신속하게 이해할 수 있습니다. 프레임 워크에 관계없이 모든 앱에서 완벽하게 작동하며 Redux, Vuex 및 @ngrx/store 의 추가 컨텍스트를 기록하는 플러그인이 있습니다.

Redux 작업 및 상태 로깅 외에도 LogRocket 은 콘솔 로그, JavaScript 오류, 스택 추적, 헤더 + 본문이 있는 네트워크 요청/응답, 브라우저 메타 데이터 및 사용자 지정 로그를 기록합니다. 또한 DOM 을 계측하여 페이지에 HTML 및 CSS 를 기록하여 가장 복잡한 단일 페이지 앱의 완벽한 픽셀 비디오를 재생성합니다.

무료로 사용해보십시오.

공감
0
  • 복사

댓글 0개

© SIRSOFT
현재 페이지 제일 처음으로