ghdtjgus

이번엔 웹뷰 공부를 시작했다.
사실 CMC 14기 스터디를 진행하면서 웹뷰 관련 과제를 진행해 본 적이 있었는데, 당시 너무 고통받았던 기억에 그 이후로 웹뷰 공부할 생각을 하지 않았다.
 
그런데 내가 생각하기에 웹뷰 공부를 꼭 해야하는 이유가 두 가지 있다.
1. 토스, 당근, 캐치테이블 등 정말 많은 회사가 이미 구축되어 있는 웹을 기반으로 웹뷰 방식 앱을 사용하고 있다.
2. 프론트엔드 전반적인 지식을 조금 더 활용해 볼 수 있는 환경이라고 생각한다.
 
사실 웹뷰를 사용하기만 해보면 의미가 없을 수 있는데, 웹뷰 내부 구조를 파고들면 파고들수록 새로운 개념이 나온다.
이때, 웹에만 한정된 것이 아니라 모바일(aos, ios)까지 공부를 해보며 아키텍처나 동작 방식을 파악해 볼 수 있다.
이 과정에서 배우는 점이 정말 많은 것 같다.
기존에는 그저 웹만 개발해보며 기본적인 지식들을 공부하기보다 사용해 보는 쪽에 가까웠다고 생각하는데, 웹뷰 공부를 하면서부터는 보다 기본에 충실할 수밖에 없는 공부를 하다 보니 알고 있던 지식을 검증하기도 하고 새로운 지식도 얻기도 해서 좀 많이 재밌다.
 
내가 찾아봤을 때는 아무도 이 구조를 분석하고 사용하는 것 같진 않았다.
이 구조를 분석하려면 react/react native에 대한 지식, aos/ios에 대한 지식이 필요하기 때문에 다들 안 한게 아닐까 하는...
그래서 너무 궁금해서 모바일은 잘 모르지만 조금씩 추론해 보면서 구조를 파악해 보기로 했다.
 

react-native-webview

아래 링크는 이제부터 분석해 볼 react-native-webview 깃허브 레포지토리이다.
https://github.com/react-native-webview/react-native-webview
 
사실 react-native는 facebook에서 개발했는데, react-native-webview는 따로 관리되고 있다.
그래서 react-native 최신 업데이트와 조금은 싱크가 안 맞는 부분도 있는 것 같았다.
그래도 지금으로서는 웹뷰 개발을 하기 위한 최선의 방법인 거 같으니 자세히 알아보도록 하자.
 
제일 먼저 나는 WebView.android.tsx, WebView.ios.tsx 파일을 확인했다.
https://github.com/react-native-webview/react-native-webview/blob/master/src/WebView.android.tsx
https://github.com/react-native-webview/react-native-webview/blob/master/src/WebView.ios.tsx
 
해당 코드를 보니, 확신이 들었다.
이건 모바일 모르면 공부 못한다...
 
위에 나온 웹뷰 컴포넌트 props를 하나씩 쭉 살펴보니 웹뷰 컴포넌트 사용법에 대해서는 자세히 알 수 있었다.
웹뷰 개발 시 postMessage, onMessage, injectJavaScript 메서드를 상당히 많이 사용하게 될 거 같았다.
postMessage의 경우, 내부적으로 window.ReactNativeWebView.postMessage 방식을 사용하는데, 어디서 이 내부 로직을 볼 수 있나 했더니 모바일 코드였다.
그리고 injectJavaScript 메서드도 동일했다.
모바일까지 내려가지 않으면 내부 로직을 볼 수 없는...
자바스크립트 웹뷰 컴포넌트는 그저 네이티브 기능들을 쓰기 위한 호출자 정도로 생각하게 되었다.
 
그래서 이제는 이 호출 과정이 어떻게 네이티브까지 이어지는지가 궁금해졌다.
어떻게 하면 자바스크립트에서 native 기능들을 사용할 수 있지?라는 의문에서 시작된 거다.
 
WebView.android.tsx 파일을 보면 아래 코드가 가장 중요한 걸 알 수 있다.
해당 웹뷰 컴포넌트 파일에서는 NativeWebView 컴포넌트를 사용하도록 하는데 이 자체가 모바일에서 정의한 웹뷰 컴포넌트를 자바스크립트로 불러와서 사용한다는 의미다.

const NativeWebView = (nativeConfig?.component as typeof RNCWebView | undefined) || RNCWebView;
import RNCWebView, { Commands, NativeProps } from './RNCWebViewNativeComponent';
export default codegenNativeComponent<NativeProps>(
  'RNCWebView'
) as HostComponent<NativeProps>;

 
여기까지만 알아봤다면 어떻게 자바스크립트로 native 컴포넌트를 불러오는지까지는 알 수 있었다.
여기서 더 나아가려면 한 가지 더 알아야 할 개념이 있다.
바로 네이티브 모듈이란 건데, 아래 링크에 들어가 보면 잘 설명되어 있으니 참고하면 좋을 거 같다.
https://reactnative.dev/docs/native-modules-intro

네이티브 모듈에 대해 간단히 설명해 보자면, react native 앱에서 기본적으로 제공되지 않는 네이티브 플랫폼 API에 접근할 수 있게 해 준다.
예를 들어, Apple Pay나 Google Pay와 같은 네이티브 API에 접근하거나, 기존의 Objective-C, Swift, Java, C++ 라이브러리를 자바스크립트에서 사용할 수 있게 해 준다.
그러니까 이 네이티브 모듈이란 걸 사용하면 자바스크립트로 네이티브 API를 호출할 수 있게 해주는 것이다.
 
그래서 안드로이드 네이티브 모듈 구조도 알아야 한다는 걸 깨닫고 아래 링크를 통해 안드로이드에서 네이티브 모듈을 어떻게 작성하는지에 대해서 공부했다.
https://reactnative.dev/docs/native-modules-android
 
react-native-webview android 폴더 내부 파일들을 살펴보니 쉽게 네이티브 모듈 파일도 찾을 수 있었다.
https://github.com/react-native-webview/react-native-webview/blob/master/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.java
이 네이티브 모듈 파일에서는 두 가지를 관리한다고 볼 수 있다.
1. RNCWebViewModule
2. RNCWebViewManager
 
여기서 RNCWebViewModule은 자바스크립트에서 네이티브 기능을 호출할 수 있게 해주는 인터페이스를 제공하고, RNCWebViewManager는 react native에서 웹뷰를 관리하고 렌더링 하는 데 필요한 기능들을 제공한다.
 
그래서 더 아래까지 내려가서 RNCWebViewModule, RNCWebViewManager 인터페이스 및 구현 파일도 살펴보았다.
https://github.com/react-native-webview/react-native-webview/blob/master/android/src/newarch/com/reactnativecommunity/webview/RNCWebViewManager.java
https://github.com/react-native-webview/react-native-webview/blob/master/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManagerImpl.kt
https://github.com/react-native-webview/react-native-webview/blob/master/android/src/newarch/com/reactnativecommunity/webview/RNCWebViewModule.java
https://github.com/react-native-webview/react-native-webview/blob/master/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModuleImpl.java
 
코드를 보다 보니 둘 다 RNCWebViewModule, RNCWebViewManager 둘 다 자바스크립트에서 안드로이드 api를 호출할 수 있게 해주는 건 알겠는데, 왜 모듈과 뷰매니저로 구분했는지 궁금했다.
 
뷰매니저에서 관리하는 기능들과 모듈에서 관리하는 기능들이 차이가 있었다.
뷰매니저에는 UI와 관련된 기능 및 개별 웹뷰 인스턴스로 관리할 기능들이 들어가 있었고, 모듈에는 웹뷰 공통으로 관리할 기능들이 들어가 있었다.
 
그래서 postMessage와 injectJavascript 등 메서드는 뭔가 기능적인 면이 있으니까 모듈에 들어가야 할 거 같지만? 개별 웹뷰 인스턴스로 관리해야 하기 때문에 뷰매니저에 들어가 있었다.
만약 이 두 메서드를 모듈에서 관리한다고 생각해 보자.
그럼 메시지를 보낸 인스턴스를 찾는 별도의 처리가 필요한 상당히 비효율적인 로직이 나온다.
그래서 개별 인스턴스에서 처리할 수 있도록 뷰매니저에 있는 것이다.
 
이 글을 요약하자면 아래 그림으로 나타낼 수 있을 거 같다.
결국 WebView.android.tsx 파일에 있는 NativeWebView 컴포넌트는 codegenNativeComponent 메서드 호출을 통해 네이티브 WebView 컴포넌트를 불러오게 된다.
이 과정에서 ReactPackage를 구현한 구현체인 RNCWebViewPackage가 관여하게 되는데 해당 구현체가 관리하는 것은 뷰매니저와 네이티브 모듈이다.

RNCWebViewPackage가 네이티브 모듈과 뷰매니저를 React Native 애플리케이션과 연결하게 된다.

 
추후에는 이 RNCWebViewModule, RNCWebViewManager 구현 코드에 대해서 좀 더 자세히 알아본 후 직접 네이티브 모듈을 작성해서 react native와 연결해보려고 한다.
일단 오늘은 여기까지만 알아보도록 하자.

profile

ghdtjgus

@gugu76

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그