민프

[React-Native] React Native란? 동작원리 및 아키텍쳐는 어떻게 되어있을까? 본문

[React-Native]

[React-Native] React Native란? 동작원리 및 아키텍쳐는 어떻게 되어있을까?

민프야 2023. 10. 5. 18:22

이번 포스팅에서는 React-Native에 대해서 알아보려고 합니다.

 

React Native란?

공식홈페이지에 의하면

2015년 Facebook이 개발한 오픈 소스 모바일 애플리케이션 프레임 워크이고,
아래 사진과 같이 현재 수많은 기업에서 스택을 선정하여 운영을 하고 있는 것을 알 수 있었습니다.

React Native의 역사

Facebook 기술 블로그에서 React Native가 탄생하게 된 계기를 볼 수 있었습니다.

결론적으로 웹 환경에서 네이티브 모바일 환경을 구현하기가 어렵다는 것이었습니다.

 

그럼 어떠한 부분들이 구현하기가 어렵다는 것인지에 대해서

첫번째로 왜 네이티브가 필요한 것인지부터 알아보겠습니다.

네이티브가 필요한 이유가 무엇일까요?

네이티브 위젯들

네이티브 모바일 앱을 개발하는 데 시간이 오래 걸리더라도 웹보다 모바일 플랫폼에서 더 나은 경험을 제공 할 수 있기 때문입니다.

예를 들어서 지도, 날짜 선택기, 스위치 및 탐색 스택과 같은 플랫폼별 UI 구성 요소에 엑세스할 수 있습니다.

물론 위 구성 요소를 직접 구현하는 것은 가능하지만 재구현은 기본 구성 요소와 정확히 동일하게 느껴지지 않으며 플랫폼 변경 사항에 따라 자동으로 업데이트 되지도 않습니다. 또한 기본 제스처 인식기 만큼 정교한 것도 없으며, 이를 올바르게 수행하는 시스템을 구축하는 데 필요한 적절한 도구나 규칙도 없습니다.

 

스레딩 모델

웹 개발자라면 고성능 및 반응형 웹 앱을 구축하는 데 있어서 병렬처리 및 비동기처리 고민을 할 수 있는 부분인데

웹에는 정교한 스레딩 모델이 없기 때문에 여러 스레드에서 작업을 병렬화할 수 없습니다.

일부 애플리케이션 로직을 백그라운드에서 실행하려고 시도할 수 있지만 아직은 브라우저의 기본 스레드에서 이미지 디코딩이나 텍스트 측정과 같은 고도의 수치 계산을 효율적으로 수행할 수 없습니다.

 

네이티브 모바일 플랫폼의 사용자 경험과 웹에서 React로 빌드할 때의 개발자 경험 구축을 위한 Facebook의 고민

네이티브가 필요한 이유는 위 와 같다.

그럼 Facebook에서 네이티브 모바일 플랫폼의 사용자 경험과 웹에서 React 빌드할 때 개발자 경험 구축을 위해서 어떤 가능성 고민을 해보았을까?

 

  1. WebView 사용
    하나의 가능성은 네이티브 래퍼 애플리케이션 내에서 웹뷰를 사용하는 것 입니다.
    실제로 Facebook에서 이 방법을 사용해보았는데 원하는 성능과 확장성을 제공하지 못했지만, 해당 접근 방식은 웹의 개발자 경험, React와 웹의 빠른 반복 주기를 최대한 활용할 수 있는 장점이 있었습니다.

    하지만 모든 렌더링이 웹 기술을 사용하여 수행되기 때문에 진정으로 네이티브한 사용자 경험을 제공할 수 없습니다.

  2. 네이티브로 React 포팅
    네이티브 코드로 React를 포팅하는 것도 좋은 아이디어이고, 실제로 Facebook에서는 ComponentKit 프로젝트를 오픈 소스로 공개했습니다. 

    ComponentKit을 사용하면 React의 모든 이점, 특히 선언적이고 예측 가능한 UI를 얻을 수 있으며, 네이티브 환경의 힘을 활용할 수 있습니다. 플랫폼별 컴포넌트와 정교한 제스처 처리, 비동기 이미지 디코딩, 텍스트 측정, 렌더링 등이 가능합니다. 또한 ComponentKit은 레이아웃에 flexbox를 사용하므로 애플리케이션의 뷰를 수동으로 배치하고 크기를 조정할 필요가 없어 코드가 더 간결해지고 유지 관리가 쉬워집니다.

    그러나 이 접근 방식에는 약간의 단점이 있습니다. 
    첫째, iOS 전용이므로 Android에서 이를 활용하려면 별도의 구현을 빌드하고 엔지니어에게 사용 방법을 가르쳐야 합니다. 
    둘째, React 위에 웹용으로 구축한 것에 대한 액세스 권한이 없습니다.
    예를 들어, 데이터 패칭을 확장하는 데 도움이 되는 Relay와 같은 것입니다.
    가장 중요한 것은, 우리가 개발자의 작업 효율성 문제를 근본적으로 개선하지 않았다는 것입니다. 

  3. 네이티브 스크립팅
    JavaScript를 사용하여 네이티브 API에 호출하면 네이티브 환경의 모든 부분에 액세스할 수 있어야 하며 빠르게 반복하고 기존의 JavaScript 인프라를 활용할 수 있어야 합니다. 
    또한 JavaScript이기 때문에 이 스택을 여러 플랫폼에서 작동하게 만들 수 있을 것입니다. 
    하지만 실제로는 그렇게 간단하지 않습니다.

    네이티크 스크립은 까다로운 작업입니다.
    네이티브 환경해석 환경 간에 동기적으로 호출을 주고받으면 UI 스레드가 JavaScript 실행에 의해 차단될 위험이 있습니다.
    이를 효율적으로 해결하기 위해서는 메인 스레드 외부에서 JavaScript를 실행해야 하지만, 리소스 경합과 네이티브 환경과 JavaScript VM 간의 오버헤드 때문에 어려움이 있습니다. 올바르게 처리하지 않으면 앱의 성능이 더 나빠질 수 있습니다.

 

React Native 소개

React Native에서는 위 3가지의 문제점들을 올바르게 처리하기 위한 적절한 프로그래밍을 제공하고 있으며, 스레드 경계를 비동기적으로 메시지를 전달하고 오베헤드를 최소화하는 방법이 적용되어있습니다. 

 

React Native는 기존 렌더링된 뷰 구현을 읽지 않고도 뷰를 작성할 수 있습니다.
React Native는 DOM에 대해 논블로킹이며, DOM에 밀접하게 연결되어 있지 않아 다양한 뷰 시스템을 감쌀 수 있습니다.
이로 인해, 약간의 작업으로 모바일 애플리케이션에서도 React Native를 사용할 수 있습니다.
이 접근 방식은 점진적으로 채택할 수 있어, 새로운 제품을 구축하거나 필요에 따라 기존 제품을 전환하는 데 유용합니다.

 

모바일 환경에서의 유일한 차이점은 브라우저에서 React를 실행하고 divs와 spans로 렌더링하는 대신, 
우리의 앱 내에 내장된 JavaScriptCore 인스턴스에서 실행하고 플랫폼 특정 컴포넌트로 렌더링한다는 것입니다.

 

 

아키텍쳐

Bridge Architecture

React Native의 아키텍쳐는 처음 나왔을때 아래 사진과 같은 Bridge 아키텍처를 사용하였습니다.

이전 React Native 아키텍처의 핵심은 "Bridge"라고 불리는 구조에 있고,
이 Bridge는 JavaScript네이티브 코드 간의 통신을 담당하고 있습니다. 

 

React Native의 Bridge Architecture는 JavaScript ThreadNative Thread
그리고 이 두 쓰레드 간의 통신을 담당하는 Bridge로 구성되어 있는데요

 

간단하게 동작과정에 대해서 알아보겠습니다.

 

1. JavaScript Thread

여기에서 앱의 Javascript 코드가 실행됩니다.
React(컴포넌트와 상태관리)와 함께 사용되어 UI로직을 처리하고, 사용자 인터페이스의 업데이트를 계산합니다. 

 

JavaScript쓰레드에서 React 컴포넌트가 렌더링될 때, 해당 컴포넌트와 관련된 정보 구조를 포함하는 Shadow Tree가 생성됩니다.이 Shadow Tree는 실제 네이티브 UI 컴포넌트와 1:1로 매핑되지 않지만, 네이티브 UI를 구성하는 데 필요한 모든 정보를 포함하고 있습니다.

 

생성 된 Shadow Tree는 Bridge를 통해서 네이티브 쓰레드로 전달되고, 이 정보는 JSON 형식으로 직렬화되어 전달되게 됩니다.

 

2. Bridge

JavaScript Thread와 Native Thread 간의 통신을 중개하고,

UI 업데이트와 레이아웃 정보를 JSON 메시지로 네이티브 스레드로 전송합니다.

 

3. Native Thread

  • 네이티브 UI 컴포넌트 렌더링 및 관리
    Bridge를 통해서 받은 Shadow Tree 정보를 Flexbox알고리즘 기반으로 만들어진 Yoga 레이아웃 엔진으로 실제 레이아웃을 계산하고, 계산된 레이아웃 정보는 네이티브 UI 컴포넌트의 렌더링에 사용됩니다. 
  • Native Modules 실행
    React Native의 구조에서, JavaScript 코드는 JavaScript Thread에서 실행되고, 
    네이티브 코드는 Native Thread에서 실행되게 되는데,
    Native Modules는 이러한 네이티브 코드를 실행하는 부분으로, 네이티브 플랫폼의 기능과 API에 액세스하는 데 사용됩니다.

    Native Modules는 JavaScript에서 호출이 되고 ->
    Bridge를  통해 Native Thread로 전달되게 되고 ->
    Native Thread에서 Bridge를 통해 전달받은 정보를 바탕으로 Native Module 메서드를 실행하고, 이 과정에서 네이티브 플랫폼의 API와 기능에 엑세스하고 상호 작용을 하게 됩니다. ->
    마지막으로 결과를 반환해주게 되는데 Native Module의 메서드 실행 결과는 다시 Bridge를 통해 JavaScript Thread로 전달되고, JavaScript 코드에서는 이 결과를 받아 추가 처리를 수행합니다.

Bridge Architecture의 문제점

Bridge Architecture는 The Bridge 라는 구성 요소를 사용하여 JS 레이어에서 기본 레이어로 전달되어야 하는 모든 데이터를 직렬화하는 방식으로 작동했습니다. 

 

이 Bridge는 몇 가지 본질적인 제한이 있는데요

  • 비동기식
    한 계층은 데이터를 브리지에 전송하고, 다른 계층이 이를 처리할 때까지 비동기적으로 대기 하였습니다. 
  • 단일 스레드
    JS는 기본적으로 단일스레드로 작업하게되는데, 이에 따라서 React Native에서도 발생한 계산은 단일 쓰레드에서 수행되어야 했습니다.
  • 오버헤드
    한 레이어가 다른 레이어를 사용해야 할 때마다 일부 데이터를 직렬화해야 했습니다. 다른 계층에서는 이를 역직렬화해야 했습니다. 단순성과 가독성을 고려하여 JSON 형식을 선택했지만 가벼움에도 불구하고 비용이 많이 들었습니다.

 

위 문제점들을 해결하기 위한 새로운 아키텍쳐가 나왔는데 그게 바로 Fabric 이라는 것입니다.

 


Fabric Architecture

Fabric 아키텍쳐는 2018년에 처음 공개되었고 이전 아키텍쳐의 한계점으로 인해 나오게 되었고,

0.68버전부터 Fabric의 도입으로 아래와 같은 이점을 제공하게 됨으로써 React Native 앱의 성능, 반응성, 그리고 유연성이 크게 향상되었습니다.

  • 동기 실행: 비동기화되어서는 안되는 기능을 동기적으로 실행할 수 있습니다.
  • 동시성: JavaScript에서 다른 스레드에서 실행되는 함수를 호출하는 것이 가능합니다.
  • 낮은 오버헤드: 새 아키텍처는 더 이상 데이터를 직렬화/역직렬화할 필요가 없습니다.
  • 코드 공유: C++를 도입함으로써 이제 플랫폼에 구애받지 않는 모든 코드를 추상화하고 플랫폼 간에 쉽게 공유할 수 있습니다.
  • 유형 안전성: JS가 C++ 객체에서 메소드를 적절하게 호출할 수 있도록 하고 그 반대의 경우도 가능하도록 자동으로 생성된 코드 레이어가 추가되었습니다. 코드는 Flow 또는 TypeScript를 통해 입력해야 하는 일부 JS 사양에서 시작하여 생성됩니다.

The React Native Re-architecture

위의 아키텍쳐는 Bridge 아키텍쳐에서 Fabric 아키텍쳐를 보여주고 있는데,

Fabric 아키텍쳐에서 추가 된 개념은 Codegen, JSI, Turbo Modules 입니다.

 

아키텍쳐에 과정에 대해서 빌드 -> 런타임 -> UI 업데이트 순으로 나눠서 이야기해보자면

  1. 빌드 (Codegen)
    1. Codegen 동작 : 애플리케이션 빌드 시간에 Codegen은 JavaScript와 네이티브 코드 간의 인터페이스를 생성하게되고,
      이것은 정적 타입 정보를 기반으로 합니다.
  2. 런타임 (JSI, Turbo Modules)
    1. 사용자 인터랙션: 사용자가 애플리케이션의 UI 요소와 상호작용을 시작합니다.
    2. JavaScript 로직 실행: 사용자의 동작에 응답하여 JavaScript 로직이 실행됩니다.
    3. JSI 작동: JavaScript 로직은 JSI를 통해 필요한 경우 네이티브 코드와 직접적으로 통신합니다.
      이 통신은 Codegen에 의해 생성된 인터페이스를 통해 이루어집니다.
    4. Turbo Modules 작동: JavaScript는 Turbo Modules를 통해 네이티브 모듈에 빠르게 접근하게 되고,
      Turbo Modules 역시 Codegen에 의해 생성된 인터페이스를 활용하여 네이티브와 통신합니다.
  3. UI 업데이트 (Fabric)
    1. Fabric 작동: JavaScript와 네이티브 코드 간의 통신 결과에 따라 필요한 UI 업데이트가 있으면, 
      Fabric 아키텍처를 통해 UI가 동기적으로 업데이트됩니다. 
    2. 화면 렌더링: 업데이트된 UI는 사용자에게 즉시 표시되어 반응적인 사용자 경험을 제공합니다.

 

추가적으로  Codegen, JSI, Turbo Modules 에 대해서 자세하게 알아보겠습니다. 

  • Codegen
    • Codegen은 JavaScript와 네이티브 코드 간의 인터페이스를 자동으로 생성하고,
      개발자가 작성한 타입이 지정된 JavaScript 코드를 기반으로, 네이티브 코드와의 통신 인터페이스를 생성합니다.
    • 이로 인해 타입 불일치나 다른 호환성 문제 없이 안정적으로 네이티브 기능을 호출하고 사용할 수 있습니다. 또한, 매번 데이터를 검증할 필요 없이 빠르고 안정적으로 네이티브 코드와 통신할 수 있습니다.
  • JSI(JavaScript Interface)
    • JSI는 JavaScript와 네이티브 코드 간의 직접적인 상호 작용을 가능하게 함으로써 JavaScript코드가 네이티브 모듈에 더 빠르고 효율적으로 엑세스 할 수 있게 됩니다.
    • Bridge를 통한 메세지 전달의 오버헤드를 제거하여서 애플리케이션의 성능을 향상시킵니다. 
  • Turbo Modules
    • Turbo Modules는 JSI를 활용하여 JavaScript에서 네이티브 모듈에 더 빠르게 접근할 수 있는 방법을 제공합니다.
    • 네이티브 코드는 JavaScript 실행 환경과 동일한 메모리 공간에 로드되므로, JSI를 통해 직접적인 호출이 가능해집니다.
    • Turbo Modules는 레이지 로딩을 지원합니다. 즉, 네이티브 모듈은 JavaScript에서 실제로 필요할 때만 초기화되고 로드되게 됨으로써 이로 인해 앱의 시작 시작이 단축됩니다. 

 

정리를 해보자면 Codegen, JSI, Turbo Modules, Fabric은 함께 동작하여 React Native 앱의 성능을 향상시키고 더 나은 사용자 경험을 제공하고, Codegen은 빌드 시간에 인터페이스를 생성하고, JSI와 Turbo Modules는 런타임에 이러한 인터페이스를 통해 효율적으로 네이티브 코드와 통신합니다. Fabric은 이 모든 결과를 바탕으로 UI를 빠르고 동기적으로 업데이트합니다.

 


참고링크

https://reactnative.dev/

 

React Native · Learn once, write anywhere

A framework for building native apps using React

reactnative.dev

https://reactnative.dev/showcase

 

Showcase · React Native

Thousands of apps are using React Native, check out these apps!

reactnative.dev

https://ko.wikipedia.org/wiki/%EB%A6%AC%EC%95%A1%ED%8A%B8_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C

 

리액트 네이티브 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 리액트 네이티브(React Native)는 페이스북이 개발한 오픈 소스 모바일 애플리케이션 프레임워크이다.[3] 안드로이드[4], iOS, 웹[5], UWP[6]용 애플리케이션을 개발하

ko.wikipedia.org

https://engineering.fb.com/2015/03/26/android/react-native-bringing-modern-web-techniques-to-mobile/

 

React Native: Bringing modern web techniques to mobile

Visit the post for more.

engineering.fb.com

https://componentkit.org/

 

ComponentKit | ComponentKit

Fine-grained Recycling With ComponentKit, each UI item such as text, image, or video is recycled individually. As soon as an item goes off screen, it can be reused anywhere in the UI and pieced together with other items to create new UI elements. Such recy

componentkit.org

https://reactnative.dev/docs/javascript-environment

 

JavaScript Environment · React Native

JavaScript Runtime

reactnative.dev

https://reactnative.dev/docs/intro-react-native-components

 

Core Components and Native Components · React Native

React Native lets you compose app interfaces using Native Components. Conveniently, it comes with a set of these components for you to get started with right now—the Core Components!

reactnative.dev

https://reactnative.dev/docs/next/the-new-architecture/why

 

Why a New Architecture · React Native

The goal of the New Architecture is to solve some of the issues that afflicted the Old Architecture in terms of performance and flexibility. This section provides the basic context to understand the Old Architecture's limitations and how it has been possib

reactnative.dev

https://www.iteratorshq.com/blog/react-native-vs-native-the-ultimate-comparison-which-one-is-better/

 

React Native vs Native: The Ultimate Comparison, Which One is Better? | Iterators

Startups need the best possible tools for mobile apps. This article shows you why and when development teams should use React Native or do native development.

www.iteratorshq.com

https://reactnative.dev/docs/native-modules-intro

 

Native Modules Intro · React Native

Sometimes a React Native app needs to access a native platform API that is not available by default in JavaScript, for example the native APIs to access Apple or Google Pay. Maybe you want to reuse some existing Objective-C, Swift, Java or C++ libraries wi

reactnative.dev

https://medium.com/@Kelset/the-react-native-re-architecture-ab7219850d4f

 

The React Native Re-architecture

My experience in writing about this history in the making

medium.com

 

Comments