ReactNative

[React-Native] 3. React Native WebView 띄우기

졸려질려 2023. 3. 26. 17:16
반응형

 React Native 앱에서도 웹뷰를 사용할 수 있다. "react-native-webview" 라이브러리를 추가하여 웹뷰를 사용하고, 웹뷰와 앱 간에 동작 연동을 해본다. 그리고 그에 대한 내용과 그 과정에서 겪었던 오류들에 대한 내용들을 모두 정리하고자 한다.

개발 환경
- M1 Macbook Pro (2021)
- macOS Ventura 13.2.1
- react@18.2.0
- react-native@0.71.4

1. Install Package

npm install --save react-native-webview

 웹뷰를 사용하고자 하는 RN 프로젝트 폴더로 이동하여, 위 명령어를 입력한다. install 이 완료되면 "package.json" 파일에 dependencies 블럭에 잘 추가되었는지 확인한다.

react-native-webview@11.26.1


2. Link Native Dependencies

 React-Native 0.60 부터는 AutoLinking 이 있어서 링크 명령어를 따로 처리해줄 필요가 없다. 만약 링크 명령어가 필요하다면, 다음 명령어를 실행하면 된다. 참고로, 현재 필자가 사용하는 0.71 버전에서는 link 명령어 자체가 없다.

react-native link react-native-webview

 link 명령어와 반대로, react-native-webview 를 제거할 때 unlink 를 해줘야한다. unlink 명령어는 다음과 같다.

react-native unlink react-native-webview

 링킹(Linking) 과정 후에는 iOS 와 Android 폴더 내에서 각각 추가 설정을 해줘야한다. 아래 정보는 react-native-webview 깃허브 레포의 글에서 가져와 정리하였다.

2-1) iOS & macOS

 iOS 나 macOS 에서 빌드할 예정이라면, react-native-webview 를 설치한 후에 "pod install" 을 해줘야한다. iOS 의 경우에는, ios 폴더로 이동하여 아래 명령어를 실행한다.

pod install

 설치가 정상적으로 마쳐지면, "Installing react-native-webview" 라는 문구가 보일 것이다. react-native-webview 라이브러리가 ios 에서 잘 인식되었다고 보면 된다. 이제 Webview 를 넣고 싶은 코드에 추가하면 된다.


2-2) Android

 사용하고자 하는 react-native-webview 의 버전이 6 이상이라면, Android 는 android 폴더 안에 gradle.properties 파일을 수정해야 한다. 반면에 react-native-webview 의 버전이 6 미만이라면 아래 과정을 할 필요는 없다.

// gradle.properties

...
android.useAndroidX=true
android.enableJetifier=true
...

 공식 레포의 가이드 문서에서는 Window 환경에서 설정법도 담고 있다. 하지만, 필자는 iOS 와 Android 만 다룰 예정이기에 여기서 마무리한다. 더 자세한 내용은 위에 링크나 여기 링크를 클릭하면 된다.


3. WebView 출력하기 

 react-native-webview 는 <WebView /> 라는 이름의 Component 로 사용할 수 있다. 기본적인 사용법은 아래 코드와 같다.

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

 source 라는 속성 안에 uri 를 비롯한 다양한 설정값을 넣어주면 된다. 필수적인 요소는 당연히 "uri" 일 것이다. 하지만, 간단하게 <WebView /> Component 안에 uri 만 넣어서 해보고 싶지만 쉽게 되지 않는다. 아래 코드와 같이 구현하여 Android 와 iOS 에서 실행시켜본다.

// App.tsx

const App = () => {
  return (
    <SafeAreaView>
      <WebView
          source={{ uri: 'https://www.google.com/' }} />
    </SafeAreaView>
  );
};

 구글 홈페이지의 아무런 모습도 볼 수 없다. 필자도 react-native-webview 를 처음 도입하면서 제일 당황스러운 부분이었다. 물론, 위 코드의 상태에서 시작한 것은 아니었지만, 처음 <WebView/> 를 사용했을 때 아무것도 출력이 되지 않아서 당황했었다. 그렇게 구글링으로 계속 찾은 결과, 인과 관계는 잘 모르겠으나 어떻게 해야 <WebView/> 가 잘 출력되는지 알 수 있었다.

 WebView 를 감싸는 상위 Component 와 WebView 에 각각 style 속성을 넣어줘야한다. 상위 Component 에는 "flex: 1" 을 포함하는 속성 값들을 적용시켜야 하고, <WebView /> 에는 "width" 와 "height" 에 대한 속성 값을 적용시켜줘야 한다. 정리하자면 다음과 같다.

// App.tsx

...
const App = () => {
  return (
    <SafeAreaView style={styles.container}>
      <WebView
          style={styles.webview}
          source={{ uri: 'https://www.google.com/' }} />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'space-between'
  },
  webview: {
    flex: 1,
    width: 300,
    height: 300,
  },
});
...

 width 와 height 의 값을 각각 300 으로 넣어준 뒤, Android 와 iOS 시뮬레이터에서 확인해보면 다음과 같이 출력된다.

 아까 보이지 않았던 <WebView/> 의 모습을 볼 수 있다. 다만, "width" 와 "height" 값이 임의로 지정되어 화면에 꽉차게 나오지는 않고 있다. 이를 해결하기 위해 "width" 와 "height" 에 넣는 값을 코드에서 기기 해상도 값으로 넣도록 추가한다.

// App.tsx

...
const deviceHeight = (Dimensions.get('window').height);
const deviceWidth = Dimensions.get('window').width;

const App = () => {
  return (
    <SafeAreaView style={styles.container}>
      <WebView
          style={styles.webview}
          source={{ uri: 'https://www.google.com/' }} />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'space-between'
  },
  webview: {
    flex: 1,
    width: deviceWidth,
    height: deviceHeight,
  },
});
...

 그러면 직전과 달리 width 가 확실히 딱 맞게 출력되는 것을 볼 수 있다. 다만, height 는 스크롤이 될 정도로 넘어가있는 상태이다. 이에 대해선 좀 더 조사를 해봐야할 것 같다.


4. Inline HTML, Local HTML

 위에 사용한 기본적인 URL 뿐만 아니라, <WebView /> 의 속성 값 안에 HTML 코드를 넣어서 그대로 출력시킬 수도 있다.

// 출처: https://github.com/react-native-webview/react-native-webview/blob/HEAD/docs/Guide.md#basic-inline-html

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

class MyInlineWeb extends Component {
  render() {
    return (
      <WebView
        originWhitelist={['*']}
        source={{ html: '<h1>This is a static HTML source!</h1>' }}
      />
    );
  }
}

 위 코드와 같이 "html" 속성 안에 직접 HTML 코드를 넣어서 출력할 때는 "originWhitelist" 속성을 ['*'] 으로 설정해야만 한다. 그리고 이 외에 로컬에 있는 HTML 파일을 로드해서 사용해볼 수도 있다. 하지만, 로컬에 있는 HTML 파일을 로드하는 것은 아직 지원하지 않는다.

Loading local HTML files
Note: This is currently not working as discussed in #428 and #518. Possible workarounds include bundling all assets with webpack or similar, or running a local webserver.

 따라서, 로컬에서 웹페이지를 로드하는 방법은 로컬 서버로 대체해서 사용해야한다. 구현해놓은 로컬 페이지를 "localhost:[PORT_NUM]" 의 형식으로 "uri" 속성 값에 넣어주면, 구현한 페이지를 RN 앱 위에서 볼 수 있다. 다만, Android Emulator 에서 테스트를 한다면, "adb reverse" 명령어를 실행해야한다. 만약 "localhost:8887" 의 로컬 웹페이지로 접속하는 것이라면, 다음 명령어를 사용한다.

// IF you want to enter "http://localhost:8887/"

adb reverse tcp:8887 tcp:8887

 위 명령어를 실행하면, Android Emulator 가 PC 에서 실행시킨 로컬 서버로 접속할 수 있게 된다. iOS Simulator 는 이와 같은 과정이 없이 바로 접속이 가능했다.


 이렇게 <WebView /> 를 출력하는 방법에 대해 정리해보았다. 그 과정에서 왜 그런지 감도 안잡히는 에러들을 발견했다. 이를 알아내는 과정에서 다양하게 검색을 해보았고, 다양한 방법으로 해결해보려 했었다. 하지만, 필자의 환경에 딱 맞는 해결법은 위의 해결법이었다. 아직 필자도 RN 은 초급자 수준이기 때문에 좀 더 공부를 해보면서 깨달아 나가야할 것 같다.

참고 자료

https://github.com/react-native-webview/react-native-webview/blob/master/docs/Getting-Started.md

https://stackoverflow.com/questions/35451139/react-native-webview-not-loading-any-url-react-native-web-view-not-working

반응형