React Native Deep Dive
React Native Deep Dive
React Native 아키텍처를 이해하기
React Native 아키텍처를 깊이 이해하는 건 개발자가 성능을 최적화하고, 효율적으로 디버깅하며, 최신 기술을 활용해 고품질의 확장 가능한 애플리케이션을 구축하는 데 중요함.
구 아키텍처: Bridge 모델
구 아키텍처에서는 React Native가 두 개의 별도 세상에서 작동했음:
- JavaScript World — 앱 로직이 실행되는 곳
- Native World — UI와 시스템 기능이 작동하는 곳
이 두 세상은 서로 다른 언어(JavaScript vs Swift/Java/Kotlin)를 사용하므로 통신 방법이 필요했음. 바로 여기서 Bridge가 등장함.
Bridge가 어떻게 작동하는가?
- JavaScript 측은 JSON 메시지를 통해 Native 측에 무엇을 해야 할지 알려줌.
- Native 측은 이 메시지를 읽고 UI를 렌더링하거나 텍스트를 업데이트하는 등의 작업을 실행함.
- 사용자가 UI와 상호작용하면(예: 버튼 클릭 시) Native 측은 다시 JavaScript로 메시지를 보냄.
예시: 로그인 화면 만들기
- JavaScript는 Bridge를 통해 메시지를 보냄:
- "이 스타일로 입력 필드를 만들어라"
- "이 속성으로 버튼을 만들어라"
- Native 측은 메시지를 받고 UI를 렌더링함.
- 사용자가 텍스트를 입력하면 Native 측은 데이터를 JavaScript로 다시 보냄.
React Native의 Thread(구 아키텍처)
React Native 앱은 여러 Thread에서 실행됨:
- JavaScript Thread — 모든 React Native 논리를 실행하고 UI 업데이트를 처리함.
- Native Thread — UI 요소에 대한 플랫폼 특정 코드(Swift, Java/Kotlin)를 실행함.
- 쉐도우 Thread — 레이아웃을 처리하는 Yoga Engine을 사용해 스타일을 Native 레이아웃으로 변환함.
구 아키텍처의 단점
🚨 1. 성능 문제
- JavaScript와 Native 간의 통신이 느려서 메시지가 비동기적으로 전달됨.
- UI 업데이트가 늦어지면 스크롤에 지연이 발생할 수 있음.
🚨 2. 메모리 공유 불가
- JavaScript와 Native는 메모리를 공유하지 않음.
- 대신 데이터를 JSON 형식으로 복사해 전달하는데, 이로 인해 성능이 저하됨.
🚨 3. Native Module 로딩의 비효율성
- React Native는 필요하지 않은 Native Module도 앱 시작 시 모두 로드함. 이로 인해 로드 시간이 길어짐.
🚨 4. 기여가 어려움
- React Native의 코드베이스가 복잡해서 개발자들이 개선하거나 수정하는 게 어려움.
새로운 아키텍처: Fabric과 Turbo Modules
이 문제를 해결하기 위해 React Native는 새로운 아키텍처인 Fabric과 Turbo Modules를 도입함.
Fabric이란 무엇인가?
Fabric은 Bridge를 제거하고 JavaScript와 Native 간의 더 빠르고 효율적인 통신 모델을 제공함.
Fabric이 더 좋은 이유?
- 비동기 메시지가 아닌 동기식 통신을 사용함.
- JavaScript와 Native가 메모리를 공유해 데이터 복사 필요성을 줄임.
- UI 응답성과 부드러움을 개선함.
Turbo Modules란 무엇인가?
Turbo Modules는 React Native가 시작 시 모든 Native Module을 로드하는 대신, 필요한 Module만 로드할 수 있게 함.
Turbo Modules가 더 좋은 이유?
- 앱 시작 시간을 줄임.
- 필요할 때만 Module을 로드해 메모리를 절약함.
비교: 구 아키텍처 vs 새로운 아키텍처
React Native 앱 아이콘을 클릭했을 때의 흐름
-
1단계: 앱 시작 & UI 관리자 시작
앱 아이콘을 클릭하면 운영 체제가 앱을 실행하고 React Native를 시작함. UI 관리자는 텍스트 필드, 버튼, 이미지 등의 Native 컴포넌트를 초기화함. -
2단계: JavaScript 번들 로드
React Native는 MainBundle.js를 로드해 앱의 모든 JavaScript 코드를 포함함. -
3단계: Bridge를 통한 뷰 생성 (구 아키텍처) 또는 Fabric (새로운 아키텍처)
- 구 아키텍처: JavaScript는 Bridge를 통해 JSON 메시지를 보내 UI 요소를 생성함.
- 새로운 아키텍처: Fabric은 Native 코드와 직접 상호작용해 UI 렌더링을 더 빠르게 만듬.
-
4단계: 레이아웃 계산 (Yoga Engine 사용)
React Native는 웹에서 사용하는 표준 CSS 대신 Yoga Engine을 사용해 레이아웃을 계산하고 요소의 위치를 설정함. 쉐도우 Thread가 이 레이아웃 처리를 담당함. -
5단계: UI가 화면에 표시됨
마지막으로 UI 관리자는 계산된 레이아웃을 기반으로 UI를 표시함. 앱이 완전히 로드되고 사용할 준비가 됨! 🎉
앱 시작 시의 흐름
- UI 관리자는 Native 컴포넌트를 초기화함.
- JavaScript는 MainBundle.js를 로드함.
- Yoga Engine을 사용해 레이아웃을 계산함.
- UI가 화면에 표시됨.
MainBundle.js에 무엇이 포함되어 있는가?
MainBundle.js(또는 Android의 index.bundle)는 React Native 애플리케이션에서 모든 JavaScript 코드를 포함하는 번들임. 이 파일은 앱 빌드 시 생성됨.
MainBundle.js에 포함되는 것들:
- 모든 JavaScript 코드 — React Native 애플리케이션의 전체 논리.
- React 및 React Native Core API — 렌더링을 위한 필수 라이브러리.
- Metro Bundler 변환 — 최적화되고 축소된 JavaScript 코드.
- 서드파티 라이브러리 — Axios, Redux 등 외부 라이브러리.
- Native Bridge 호출 (구 아키텍처 사용 시) — Native 컴포넌트와의 통신 코드.
MainBundle.js는 어떻게 생성되는가?
React Native의 Metro Bundler는 모든 JavaScript 파일을 컴파일해 MainBundle.js라는 단일 파일로 번들링함.
Metro Bundler의 역할
- ES6+ JavaScript를 ES5 문법으로 변환함.
- 여러 JavaScript 파일을 하나의 번들로 결합함.
- 코드를 최적화해 프로덕션을 위한 축소(minify) 작업을 함.
- 개발 중 핫 리로딩을 처리함.
간단한 비유
React Native 앱을 음식점에서 음식을 주문하는 것으로 비유할 수 있음:
- ☕ JavaScript Thread (고객) - 어떤 종류의 커피를 주문할지 결정함(앱 논리).
- 🧑🍳 Bridge (바리스타) - 주문을 전달받고 커피를 만드는 과정으로 넘김.
- 🍵 Native 측 (커피 머신) - 커피를 만들고 필요한 추가 작업을 처리함(UI 렌더링).
- 🛎 UI 관리자 (서빙 직원) - 완성된 커피를 고객에게 전달함(UI를 표시).
음식점이 너무 바쁘면(Bridge 요청이 많으면) 서비스가 느려짐. 그래서 React Native의 최신 버전에서는 성능 향상을 위해 Bridge 의존도를 줄였음.
주요 요약 (구 아키텍처)
- React Native는 모바일 앱을 JavaScript로 작성할 수 있게 해주지만 여전히 Native 컴포넌트를 사용함.
- JavaScript와 Native 측을 연결하는 Bridge가 커피 주문과 전달을 처리하는 역할을 함. UI 업데이트는 비동기적으로 이루어져 지연이 발생할 수 있음. Shadow Thread가 스타일을 모바일 OS가 이해할 수 있는 형식으로 변환함.
- 구 아키텍처는 Bridge 사용으로 인해 성능 저하가 발생하고, 이를 해결하기 위해 Fabric과 Turbo Modules와 같은 개선 사항이 도입됨.
간단한 비유 (새로운 아키텍처)
새로운 시스템에서는 모든 것이 더 직관적이고 효율적임. React Native 앱은 다음과 같음:
- ☕ JavaScript Thread (고객) - 고객이 원하는 커피를 빠르게 결정함(앱 논리).
- 🧑🍳 Fabric (바리스타) - 커피를 직접 만들고, 필요한 모든 작업을 한 번에 처리함(UI 렌더링).
- ⚙️ Turbo Modules (고급 커피 도구) - 특수한 커피 머신으로 특별한 요구를 처리함(카메라나 GPS와 - 같은 Native 기능 접근).
- 🛎 직접 통신 (서빙 직원) - 커피가 준비되면 바로 고객에게 전달함, 지연 없이 빠르게!
새로운 시스템에서는 커피가 더 빠르고 직관적으로 제공되며, 이전보다 더 효율적이고 즉각적인 서비스를 경험할 수 있음.