작은 지식주머니
사내 스터디 기록 - React-native 인 액션 chapter 1 ( 스레드 처리 ) 본문
React-native 인 액션 챕터 1에서 추가로 설명이 필요할 것 같은 내용을 찾아서 공부한 내용을 기록해두었습니다.
chapter 1 . 스레드 처리
네이티브 기기와 통신하는 모든 자바스크립트의 기능은 분리된 별도의 스레드로 처리됩니다.
사용자 인터페이스와 애니메이션 구동이 별도의 간섭없이 자연스럽게 보이게 됩니다.
리액트 네이티브 앱 내에서 실행되는 스레드는 API 호출, 터치 이벤트, 인터렉션입니다.
네이티브 안쪽의 변화가 필요하다면 일괄처리하여 네이티브 쪽으로 전달이 됩니다.
이러한 작업은 이벤트 루프의 마지막 단계에서 매번 이루어지게 됩니다.
이 내용이 요점정리가 되어있었는데요. 조금 더 심도있게 내용 파악이 된다면 좋을 것 같습니다.
React-native 0.67.4 아키텍처
React Native의 기본 개념은 네이티브 코드와 자바스크립트 코드를 양면으로 구성하고있습니다.
네이티브 코드는 Android에서 *Java / Kotlin, IOS의 경우 Objective-c / Swift 이어야 합니다.
네이티브 코드는 기기 내에서 바로 코드가 작동하지만 자바스크립트는 코드를 실행할 가상 머신이 필요합니다.
이를 위해 React Native에는 JavaScriptCore Webkit 엔진을 사용하여 구동합니다.
* 다만 iOS는 쓰기 가능한 실행 가능 메모리가 없다고 하여 JavascriptCore 에서 JIT를 사용하지 않습니다.
JavaScriptCore Webkit 엔진이 자바스크립트 코드를 앱 내에서 실행 할 수 있도록 도와줍니다.
네이티브 언어와 자바스크립트는 서로 다른 프로그래밍 언어로 중간에서 서로 인식이 가능한 JSON 언어로 통신합니다.
이 작업은 Bridge에 의해 처리됩니다.
빌드 시 Java, Objective-C로 작성된 네이티브 코드는 Java 및 C++ 바이너리 파일로 컴파일되고
JavaScript 코드는 Metro 번들러를 사용하여 번들됩니다.
바이너리와 JS 번들은 결국 타겟 플랫폼용 실행 파일 안에 패킹(.apk, .ipa)되며,
런타임에 자바스크립트 코드는 자바스크립트 가상머신에서 실행되고 네이티브 코드는 디바이스에서 직접 실행됩니다.
Bridge는 이 두 영역 간에 직렬화된 메시지를 전송한 후, 역직렬화되어 처리됩니다.
사용자가 앱을 실행하면 3개의 메인 스레드와, 서브 스레드 하나가 실행됩니다.
Main Thread
사용자 인터랙션과 디바이스 화면 UI 렌더링을 담당하고있는 메인 네이티브 스레드입니다.
JavaScript Thread
JavaScript 코드가 실행되는 곳 입니다.
Shadow Thread
자바스크립트 스레드를 따라 실행되고있는 스레드입니다. 뷰 위치를 계산, JS 스레드에서 레이아웃 트리를 구성하는 역할입니다.
Native Modules Thread
플랫폼 API에 액세스 역할을 맡고있는 스레드입니다.
React-native Bridge
자바스크립트 와 네이티브 코드간 정보를 교환하기 위해서 Bridge를 거치게 됩니다.
과정은 위 사진과 같습니다.
- 네이티브 이벤트가 발생합니다
- 직렬화된 메세지는 브릿지를 통하여 네이티브 측에서 전송합니다.
- 자바스크립트는 메시지를 수신하고 역직렬화 하여 수행할 작업을 결정합니다.
- 자바스크립트 계층에서 요청된 작업을 브릿지를 통해 전송합니다.
- 네이티브 측에서 수신 뒤 역직렬화하여 뷰를 업데이트합니다.
문제는 이 모든 작업이 비동기로 이루어지고 있고,
직렬화와 역질렬화의 작업 자체가 너무 무겁기 때문에 성능적인 문제가 발생합니다.
이 문제를 해결하기 위해서 React-native 는 16.8 버전에서 새로운 아키텍쳐를 만들었습니다.
React-native 16.8 이후의 아키텍처
JSI ( JavaScript interface )
브릿지를 사용하여 통신하였을 경우 역직렬화와 직렬화의 시간이 느려 병목현상이 발생하였는데요.
JSI 는 자바스크립트와 네이티브 파트가 직접 상호 작용하도록 되어있습니다.
JS 코드와 C++ 간 인터페이스를 이용하여 직접 커뮤니케이션 하도록 바뀌었습니다.
브릿지의 치명적 문제인 속도를 빠르게 해결하였습니다.
JSI가 상호 작용하는 네이티브는 Fabric 과 Turbo Modules 두 개가 있습니다.
Fabric
https://reactnative.dev/architecture/fabric-renderer
Fabric · React Native
Fabric is React Native's new rendering system, a conceptual evolution of the legacy render system. The core principles are to unify more render logic in C++, improve interoperability with host platforms, and to unlock new capabilities for React Native. Dev
reactnative.dev
React-Native Fabric을 통해 UI 관리자는 C++에서 직접 Shadow Tree를 만들 수 있으며,
이는 영역의 터널링을 줄여 성능을 향상시켰습니다. 브릿지 환경에서 비동기적으로 UI를 그려주던 작업을 동기적으로
작업이 가능하도록 바뀌었습니다.
TruboModules
TruboModules 접근 방식을 통해 JS 코드들은 실제로 필요할 때만
각 모듈들을 로드하고 모듈에 대한 직접 참조를 유지할 수 있습니다.
더 이상 기존 브릿지에서 배치 된 JSON 메시지를 사용하여 통신할 필요가 없습니다.
즉, 네이티브 모듈이 있는 응용프로그램을 기존보다 더 빠르게 시작할 수 있습니다.
Codegen
https://reactnative.dev/docs/next/the-new-architecture/pillars-codegen
Codegen · React Native
The Codegen is not a proper pillar, but it is a tool that can be used to avoid writing a lot of repetitive code. Using Codegen is not mandatory: all the code that is generated by it can also be written manually. However, it generates scaffolding code that
reactnative.dev
Codegen 은 iOS 또는 Android 앱이 빌드될 때마다 React Native에 의해 자동으로 호출됩니다.
Codegen은 JS 에서 정적 타이핑을 이용해 React-native의 새로운 아키텍처에 필요한
보일러플레이트 C++ 코드를 자동으로 생성하는 도구 입니다.
React-native 에서 네이티브 코드와 JS 코드 사이의 통신은 타입의 안정성이 중요합니다.
타입 오류는 실행 오류로 이어지며 디버깅은 복잡할 수 있는데 Codegen은 이 문제를 해결하기 위하여 개발되었습니다.
Codegen은 JS 코드에 있는 타입 정보를 사용하여 타입 에러를 예방합니다. Typescript와 Flow를 사용할때 특히 유용하다고 합니다.
Codegen은 타입 정보를 이요해여 네이티브 코드와 JS 사이의
인터페이스 C++ 코드를 생성하여 Native와 JS 사이의 통신을 위한 코드를
수동으로 작성할 필요가 없어져 개발 과정의 단순화, 오류 발생 가능성의 저하로 이어집니다.
TMI 보일러플레이트란?
컴퓨터 프로그래밍에서 보일러플레이트 또는 보일러플레이트 코드라고 부르는 것은
최소한의 변경으로 여러곳에서 재사용되며, 반복적으로 비슷한 형태를 띄는 코드를 말한다.
스레드 처리만 해도 너무 많은 길이가 나와서 다음 글에 더 적도록 하겠습니다.
참고자료
https://mycodings.fly.dev/blog/2022-11-29-react-native-new-architecture-jsi-javascript-interface
https://firework-ham.tistory.com/117
https://www.yeummy-blog.com/post/80285a63-730b-4cd7-94eb-399af12b994e
'React' 카테고리의 다른 글
ESLint 설정을 해보자 ( React ) (0) | 2023.07.28 |
---|---|
사내 스터디 기록 - NEXT.JS 체험기 (0) | 2023.07.25 |
GenericType 을 활용해서 컴포넌트를 만들어보자 (0) | 2023.07.19 |