[번역] React-Native WebView 완벽 가이드

January·2023년 9월 4일
0

번역

목록 보기
2/3

WebViews는 React Native 애플리케이션에서 웹 구성 요소를 렌더링할 수 있는 기회를 제공합니다. 웹 구성 요소는 전체 웹 페이지/애플리케이션이 될 수도 있고 간단한 HTML 파일일 수도 있습니다. 패키지인 'react-native-webview'는 React Native 앱에 WebView를 쉽게 내장할 수 있도록 도와줍니다!

이 글에서는 React Native WebView의 가장 일반적인 사용 사례를 살펴보겠습니다.


Creating the basic URL structure

간단함을 위해 코드를 App.js 파일에 추가하고 추가 파일을 생성하지 않겠습니다.

React Native 애플리케이션에 WebView를 삽입하는 가장 간단한 방법은 WebView 컴포넌트에 소스로 URL을 제공하는 것입니다:

# App.js
import React, { Component } from 'react';
import { SafeAreaView } from "react-native";
import { WebView } from 'react-native-webview';

class MyWeb extends Component {
  render() {
    return (
      <SafeAreaView style={{ flex: 1 }}>
        <WebView 
          source={{ uri: 'https://reactnative.dev/' }} 
        />
      </SafeAreaView>
    );
  }
}

WebView 컴포넌트를 사용하려면 우리가 4번 라인에서 한 것처럼 임포트해야 합니다. 그 다음으로 해야 할 일은 소스(props)를 설정하는 것뿐입니다!

소스는 값으로 객체를 취합니다. 이 경우에는 URI를 제공하고 있습니다:

source={{ uri: 'https://reactnative.dev/' }}

이 코드는 다음과 같은 결과를 얻을 것입니다:

Writing the basic inline HTML

WebView에 소스를 제공하는 또 다른 일반적인 방법은 인라인 HTML 코드를 작성하는 것입니다. 여기서 매우 간단한 예제로 시작해 봅시다:

# App.js

class MyWeb extends Component {
  render() {
    const customHTML = `
      <body style="display:flex; flex-direction: column;justify-content: center; 
        align-items:center; background-color: black; color:white; height: 100%;">
          <h1 style="font-size:100px; padding: 50px; text-align: center;" 
          id="h1_element">
            This is simple html
          </h1>
          <h2 style="display: block; font-size:80px; padding: 50px; 
          text-align: center;" id="h2_element">
            This text will be changed later!
          </h2>
       </body>`;

    return (
      <SafeAreaView style={{ flex: 1 }}>
        <WebView 
          source={{ html: customHTML }} 
        />
      </SafeAreaView>
    );
  }
}

This will be the result:

이 코드와 이전 코드의 가장 기본적인 차이점은 이제 WebView 컴포넌트의 소스로 인라인 HTML을 사용한다는 것입니다: source={{ html: customHTML }}.

6번부터 16번까지, 우리는 상수 customHTML을 정의합니다. 이것은 본질적으로 body 태그 안에 포장된 h1h2 태그를 포함하는 문자열일 뿐입니다.

또한 중앙에 요소를 배치하고 일부 배경 색상을 제공하기 위해 기본 인라인 스타일을 정의합니다.

이렇게 간단하게 사용자 정의 HTML 코드를 렌더링할 수 있습니다. 그러나 JavaScript를 포함해야 하는 동적 기능과 같은 기능을 포함하려면 어떻게 해야 할까요? 이 문제에 대한 해결책을 제공하는 것도 React Native WebView가 가능합니다!

Communicating between JavaScript and Native

코드로 시작해봅시다.

# App.js

class MyWeb extends Component {
  render() {
  const runFirst = `
      setTimeout(function() { 
          window.alert("Click me!");
          document.getElementById("h1_element").innerHTML = 
          "What is your favourite language?";
          document.getElementById("h2_element").innerHTML =
          "We will see!";
        }, 1000);
      true; // note: this is required, or you'll sometimes get silent failures
    `;

  const runBeforeFirst = `
      window.isNativeApp = true;
      true; // note: this is required, or you'll sometimes get silent failures
  `;

    return (
      <SafeAreaView style={{ flex: 1 }}>
        <WebView 
          source={{ html: customHTML }} 
          onMessage={(event) => {}}
          injectedJavaScript={runFirst}
          injectedJavaScriptBeforeContentLoaded={runBeforeFirst}
        />
      </SafeAreaView>
    );
  }
}

만약 25-27번 라인의 WebView 컴포넌트를 간략히 살펴보면, 세 가지 새로운 프롭스가 도입되었음을 알 수 있습니다: onMessage, injectedJavaScriptinjectedJavaScriptBeforeContentLoaded.

injectedJavaScript 프롭에 제공된 JavaScript 코드는 리소스가 처음으로 로드된 후에만 실행됩니다. 웹사이트를 새로 고쳐도 코드는 다시 실행되지 않습니다!

우리의 스크립트인 runFirst는 5-14번 라인에서 찾을 수 있습니다. 이 스크립트 안에서는 먼저 렌더링을 위한 메시지를 트리거하고 나서 h1h2 요소의 텍스트를 변경합니다. 이 모든 것은 1초 후에 이 스크립트를 실행하기 위해 setTimeout 함수로 래핑되어 있습니다.

반면, injectedJavaScriptBeforeContentLoaded 프롭에 제공된 스크립트는 페이지가 처음으로 로드되기 전에 실행됩니다. 해당 스크립트인 runBeforeFirst는 16-19번 라인에서 찾을 수 있습니다. 이 경우 이 스크립트는 앱의 시각적 요소에 영향을 미치지 않습니다.

onMessage 프롭은 비어 있는 함수로 있어야 하며, 이 프롭이 없으면 스크립트가 실행되지 않습니다!

주의사항

injectedJavaScriptinjectedJavaScriptBeforeContentLoaded 프롭의 단점은 두 프롭 모두 한 번만 실행된다는 것입니다. 그러나 여러 번 JavaScript 코드를 실행하려는 시나리오가 있는데, 다음 섹션에서 살펴보겠습니다!

The injectJavaScript method

이 섹션에서는 이 데모 앱의 최종 기능을 구현할 것입니다. 프로그래밍 언어를 무작위로 표시하고 마지막으로 LogRocket 블로그의 해당 섹션으로 리디렉션할 것입니다.

# App.js
const selectProgrammingLanguage = () => {
  const languages = [
    "Rust",
    "Python",
    "JavaScript",
    "TypeScript",
    "C++",
    "Go",
    "R",
    "Java",
    "PHP",
    "Kotlin",
  ];
  const randomInt = Math.floor(Math.random() * languages.length);
  return languages[randomInt];
};

class MyWeb extends Component {
  render() {
  let counter = 1;

  const script = () => {
      const selectedLanguage = selectProgrammingLanguage();
      counter += 1;
      const newURL = "https://blog.logrocket.com";
      const redirectTo = 'window.location = "' + newURL + '"';

      if (counter <= 10) {
        return `
          if (document.body.style.backgroundColor === 'white') {
            document.body.style.backgroundColor = 'black'
            document.body.style.color = 'white'
          } else {
            document.body.style.backgroundColor = 'white'
            document.body.style.color = 'black'
          };

          document.getElementById("h2_element").innerHTML = "${selectedLanguage}?";
          window.ReactNativeWebView.postMessage("counter: ${counter}");
          true;  // note: this is required, or you'll sometimes get silent failures
      `;
      } else if (counter === 11) {
        return `
          window.ReactNativeWebView.postMessage("you are now getting redirected!");
          ${redirectTo};
          true;  // note: this is required, or you'll sometimes get silent failures
        `;
      } else {
        return null;
      }
    };

    setInterval(() => {
        this.webref.injectJavaScript(script());
      }, 2000);

    return (
      <SafeAreaView style={{ flex: 1 }}>
        <WebView 
          source={{ html: customHTML }} 
          ref={(r) => (this.webref = r)}
          onMessage={(event) => {
          console.log(event.nativeEvent.data);
          }}
          injectedJavaScript={runFirst}
          injectedJavaScriptBeforeContentLoaded={runBeforeFirst}
        />
      </SafeAreaView>
    );
  }
}

2에서 17행까지, 먼저 3행에서 languages 배열에서 무작위로 프로그래밍 언어를 반환하는 함수를 정의합니다. 이와 동일한 함수가 23행에서 정의된 script 함수 내에서 다시 호출됩니다. script 함수가 호출될 때마다 무작위 프로그래밍 언어가 생성되고 39행의 HTML 코드에 포함됩니다.

document.getElementById("h2_element").innerHTML = "${selectedLanguage}?";

게다가, 배경색이 검정에서 흰색으로 변경될 때마다 글꼴 색상도 변경되어야합니다. 그러나 이것은 이 함수가 호출되는 첫 10번에만 발생합니다.

10번째 실행 후, 스크립트는 44행에서 48행으로 이동합니다. 거기에서 우리는 26행과 27행에서 정의한 URL로 리디렉션을 원한다고 정의합니다.

마지막으로, script 함수가 어디서 호출되는지 궁금할 수 있습니다. 그럼 54행에서 56행을 보면 이 코드가 매 2초마다 실행됨을 알 수 있습니다.

this.webref.injectJavaScript(script());

이렇게하면 JavaScript를 한 번 이상 실행할 수 있습니다!

하지만 아직 끝나지 않았습니다. 아마도 63행에서 65행의 WebView 구성 요소 내부의 onMessage 속성이 변경되었음을 알아챘을 것입니다. 어떤 종류의 정보를 로그로 남기고 있는지 볼 수 있습니다.

지금까지 앱에서 웹페이지로 정보를 보냈습니다. 그러나 웹페이지에서 정보를 받고 싶다면 어떻게 해야 할까요? 여기서 onMessage 속성이 등장합니다.

우리는 이미 (event.nativeEvent.data)로 이러한 유형의 데이터를 로그로 기록하고 있습니다. 이 데이터는 49행에서 가져옵니다:

window.ReactNativeWebView.postMessage("counter: ${counter}");

그리고 45행

window.ReactNativeWebView.postMessage("you are now getting redirected!");

이것이 데모 앱의 최종 결과입니다:

Conclusion

이 글에서는 React Native 앱에 WebView를 임베드하는 방법을 검토했습니다. WebView 컴포넌트에 URL을 제공하거나 사용자 정의 인라인 HTML을 추가할 수 있습니다. 또한 WebView 컴포넌트에 JavaScript 코드를 삽입하는 방법에 대해서도 논의했습니다.

원글

기술 설명 문맥이 자연스럽기 위해 chat-GPT를 사용해 번역했습니다.

0개의 댓글