프론트엔드 기본개념 복습/React

[React Native] React Native의 작동 원리

콘요맘떼 2022. 3. 10. 17:50

React Native 앱의 구성 요소

  React Native 앱은 크게 세 가지 요소로 이루어져 있다. Native 영역JS 영역이 존재하며 그 둘을 Native Bridge가 이어준다.

 

1. Native side (Main Thread = UI Thread)

  네이티브 영역인 메인 스레드는 어플리케이션이 실행되자마자 시작된다. 메인 스레드는 우선적으로 앱을 로드하고 JS 스레드를 실행시킨다. 메인 스레드는 앱의 UI적인 부분을 담당한다. (그렇기 때문에 UI 스레드라고 부르기도 한다.) 메인 스레드는 JS의 이벤트 루프가 끝날 때마다 네이티브 브릿지를 통해 받은 메시지를 기준으로 UI를 화면에 보여준다. 반대로 사용자가 기기에 UI 이벤트를 일으키면(press, touch 등) 네이티브 브릿지를 통해 해당 이벤트 명령들을 JS 스레드로 전달한다.

 

2. Javascript side (JS Thread)

  JS 스레드는 하나의 파일로 번들링된 자바스크립트 코드들을 실행(main.bundle.js)한다. 즉, 앱의 로직적인 부분을 담당한다고 보면 된다. 이벤트 루프가 끝날 JS 스레드는 네이티브 브릿지를 통해 표시할 뷰와 관련된 정보들을 네이티브 영역인 메인 스레드에 전달해준다.

 

3. Native Bridge

  네이티브 브릿지는 메인 스레드와 JS 스레드를 연결해준다. 네이티브 브릿지를 통하는 정보는 JSON Object의 형태로 변환되어 전달된다. 리액트 네이티브를 통해 안드로이드와 iOS 앱을 동시에 만들 수 있는 것은 네이티브 브릿지가 제공하는 인터페이스 덕분이다. 예를 들어서 UI적인 측면을 바라보았을 때 JS 코드는 컴포넌트의 UI를 표현하기 위해 <View>와 같은 마크업을 사용한다. 네이티브 브릿지를 통해서 이 마크업이 해당 OS 플랫폼의 네이티브 UI 요소로 변환될 수 있다. 리액트 네이티브 애플리케이션이 네이티브 앱보다 성능의 제약을 가지는 것이 바로 이 네이티브 브릿지 때문이다. 리액트 네이티브 애플리케이션의 성능은 병목 현상이 일어나기 쉬운 네이티브 브릿지를 건너는 횟수에 아주 크게 영향을 받는다. 

 

Diffing Algorithm

  그렇다면 네이티브 브릿지를 최대한 적게 이용하기 위해서 어떻게 해야할까? 다행히 이 부분에서 React의 강점이 나온다. 리액트는 Virtual DOM을 사용한다. 따라서 매번 새로운 DOM을 렌더링하는 것이 아니라 최소한의 변경사항을 파악하여 그에 해당하는 부분을 리렌더링한다. 여기서 사용하는 알고리즘이 Diffing Algorithm이다. Diffing Algorithm은 O(n)의 시간복잡도를 가지는 트리 레벨별 비교 작업을 수행한다. 참고로 Diffing Algorithm은 동일한 클래스에 대해서만 비교 작업을 수행하며 만약 클래스가 다르면 비교를 수행하지 않고 해당 컴포넌트를 새로 렌더링한다. Diffing Algorithm이 갱신될 컴포넌트에 대해 dirty mark를 하면 이벤트 루프가 끝날 때마다 해당 컴포넌트들을 확인한 후 메인 스레드를 통해 갱신 작업을 수행한다.

 

※ 참고로 리액트 네이티브를 분석할 때에는 일반적으로 위 세 가지 구성 요소들을 이야기한다. 그렇지만 그 외의 구체적인 스레드들도 존재하는 것 같아서 정리해보았다.

(1) Shadow Thread : 네이티브 브릿지를 통해 JS 스레드로부터 변경 사항을 전달받고 레이아웃 등을 계산하여 메인 스레드로 전달한다. (UI를 실제로 그리는 것은 메인 스레드만이 수행할 수 있다.)

(2) Native Modules Thread : 애플리케이션이 해당 플랫폼 API에 직접 액세스해야 하는 경우도 간혹 존재한다. Native Modules 스레드가 이를 담당한다.

 

 

React Native 앱의 실행 과정

(1) 앱이 실행되면 메인 스레드가 우선 실행된다.

(2) 메인 스레드가 JS 스레드를 실행시킨다.

(3) JS 스레드가 JS 번들을 실행시키면서 Virtual DOM이 생성된다. 그리고 Diffing Algorithm을 기준으로 한 갱신 사항네이티브 브릿지를 통해 shadow 스레드로 전달된다.

(4) shadow 스레드는 받은 메시지를 통해 레이아웃을 계산하고 그 결과를 메인 스레드로 전달한다.

(5) 메인 스레드는 전달받은 내용을 기준으로 화면에 UI를 보여준다.

(6) 만약 사용자가 터치 등을 통해 UI 이벤트를 발생시키면 메인 스레드가 네이티브 브릿지를 통해 그 정보를 JS 스레드로 전달한다.

(7) JS 스레드는 전달받은 이벤트 내용을 기준으로 로직을 실행한다.

(8) (3)~(7)과정이 계속 반복된다.