Skip to content

iq-dev-lab/react-native-deep-dive

Repository files navigation

🔷 React Native Deep Dive

"RN은 네이티브 뷰를 JS로 제어한다 — Bridge는 그 둘을 잇던 비동기 큐, JSI는 직접 통하는 C++ 다리다"


"RN으로 앱을 만드는 것과, JS와 네이티브가 어떤 경계로 통신하고 그 경계가 어떻게 진화했는지 아는 것은 다르다"

구형 Bridge의 직렬화 비동기 큐에서 JSI·Fabric·TurboModules의 직접 호출로 옮겨가는 과정과, Hermes 바이트코드가 모바일 시작 비용을 어떻게 0에 가깝게 만드는지 — 왜 이렇게 동작하는가 라는 질문으로 React Native의 두 세계 경계를 끝까지 파헤칩니다


GitHub React Native New Architecture Hermes Docs License


🎯 이 레포에 대하여

RN 자료는 넘쳐납니다. 하지만 대부분은 "어떻게 쓰나" 에서 멈춥니다.

일반 자료 이 레포
"RN은 JS로 만드는 네이티브 앱입니다" JS 스레드에서 돌아가는 React 트리가 어떤 경계를 거쳐 UIView/android.View가 되는지, 스레드 모델과 메시지 흐름을 직접 추적
"Bridge가 New Architecture로 바뀌었습니다" 구형 Bridge의 JSON 직렬화 비동기 큐가 어떤 호출 패턴에서 병목이 되는지, JSI가 그것을 어떻게 동기 직접 호출로 대체하는지 코드로 비교
"Fabric은 새 렌더러입니다" C++ Shadow Tree가 React Fiber 트리와 어디에서 만나는가, Yoga 레이아웃이 동기 측정을 가능하게 하는 메커니즘
"TurboModules는 더 빠릅니다" 구형 NativeModules의 직렬화 비용이 어디서 발생하는지, Codegen이 타입 안전한 JSI 바인딩을 어떻게 생성하는지
"Hermes는 RN에 최적화되어 있습니다" 빌드 타임에 .hbc 바이트코드를 사전 생성해 파싱·JIT 시작 비용을 제거하는 원리, V8 JIT 전략과의 트레이드오프
"큰 데이터는 Bridge로 보내지 마세요" 동일 페이로드를 Bridge vs JSI로 반복 전송하며 경계 비용을 직접 측정, 무엇을 네이티브로 보낼지에 대한 정량적 기준
이론 나열 실행 가능한 코드 + Flipper/React DevTools + TurboModule 작성 + Old/New Architecture 같은 화면 실측 비교

선행 학습 권장: React Internals Deep Dive — Fiber와 재조정이 Fabric의 입력. Android Framework Internals / UIKit · Core Animation — 네이티브 뷰가 RN의 출력.


🚀 빠른 시작

각 챕터의 첫 문서부터 바로 학습을 시작하세요!

Architecture Old Bridge JSI Fabric TurboModules Hermes Performance


📚 전체 학습 지도

💡 각 섹션을 클릭하면 상세 문서 목록이 펼쳐집니다


🔹 Chapter 1: RN 아키텍처 개요

핵심 질문: JS로 작성한 트리는 어떤 스레드에서 살고, 어떻게 진짜 네이티브 뷰가 되는가?

두 세계의 분업, 스레드 모델, 렌더 흐름, Old vs New 미리보기까지 (5개 문서)
문서 다루는 내용
01. React Native란 "JS로 네이티브 뷰를 제어"의 의미 — 웹뷰가 아닌 진짜 UIView/android.View, Flutter의 자체 렌더와 본질적으로 다른 지점
02. 스레드 모델 JS 스레드·Main(UI) 스레드·Shadow 스레드의 분업과 소유권, 각 스레드가 무엇을 할 수 있고 무엇을 할 수 없는가
03. 두 세계 JS 세계(React 트리·이벤트 핸들러)와 네이티브 세계(뷰 트리·렌더 파이프라인)의 분리, 경계가 곧 비용이라는 명제
04. 렌더 흐름 한눈에 React 트리 → Shadow Tree → 네이티브 뷰 마운트의 단계, 어느 스레드에서 무엇이 일어나는지 한 장 다이어그램으로
05. Old vs New Architecture Bridge(직렬화 비동기) → JSI(직접 동기)로의 전환 미리보기, Fabric·TurboModules가 함께 바뀌는 이유

🔹 Chapter 2: 구형 Bridge — 비동기 직렬화 큐

핵심 질문: Bridge는 왜 "느리다"고 불리는가? 정확히 어디서 비용이 발생하는가?

JSON 직렬화 큐, 3스레드 흐름, 동기 측정 불가의 정체까지 (5개 문서)
문서 다루는 내용
01. Bridge 구조 JS와 네이티브 사이의 비동기 메시지 큐, MessageQueue/RCTBridge의 실체, 양방향 통신이 따르는 패턴
02. 직렬화 통신 모든 호출이 JSON 직렬화 → 큐 → 역직렬화를 거치는 흐름, 큰 페이로드에서 누적되는 비용
03. Bridge의 한계 직렬화 비용·비동기 강제·배치 지연 — 동기 측정이 불가능해서 생기는 레이아웃 깜빡임과 제스처 끊김
04. 3스레드 흐름 JS → Shadow(레이아웃) → Main(렌더)으로 비동기 3단 점프하는 흐름, 각 단계에서 보존되는 컨텍스트
05. 왜 느린가 스크롤 동기화·제스처·애니메이션이 끊기는 구체적 시나리오, 통신량과 응답성의 관계를 측정으로 확인

🔹 Chapter 3: JSI — New Architecture의 기반

핵심 질문: JSI는 어떻게 직렬화 없이 JS와 C++을 직접 잇는가?

동기 호출, HostObject, 엔진 독립 설계까지 (6개 문서)
문서 다루는 내용
01. JSI란 JavaScript Interface — JS 엔진에 C++로 직접 접근하는 얇은 추상화 계층, Bridge를 대체하는 것이 아니라 제거하는 설계
02. 동기 호출 직렬화 없이 JS↔C++ 함수가 같은 스레드에서 직접 호출되는 메커니즘, Bridge에서 불가능했던 동기 측정의 부활
03. HostObject JS에서 보이는 C++ 객체의 정체 — get/set 가로채기로 메서드를 동적으로 노출, JS 측 프록시와의 차이
04. 엔진 독립 설계 JSI가 JSC/Hermes/V8 어디에도 묶이지 않는 이유, 엔진 교체 비용을 RN 코어에서 분리한 추상화의 가치
05. 메모리와 생명주기 JSI 객체의 소유권 모델, JS GC와 C++ 수동 관리의 경계, weak/strong reference 관리의 실수 패턴
06. Bridge → JSI 비교 같은 호출을 Bridge와 JSI로 보내며 직렬화 비용·비동기 강제·지연을 정량 비교, 어느 패턴에서 차이가 큰가

🔹 Chapter 4: Fabric 렌더러 — C++ Shadow Tree

핵심 질문: React Fiber 트리는 어떻게 진짜 네이티브 뷰로 마운트되는가?

C++ Shadow Tree, Fiber 연결, Yoga, 동시성까지 (6개 문서)
문서 다루는 내용
01. Fabric 개요 새 렌더 시스템의 C++ 코어, React와 네이티브를 통합하는 단일 파이프라인, 구형 UIManager와의 구조 차이
02. C++ Shadow Tree 레이아웃 트리가 C++ 객체로 표현되어 iOS·Android에서 공유되는 구조, 불변 트리로 가능해진 concurrent rendering
03. React Fiber와 연결 react-internals의 Fiber가 Shadow Node로 매핑되는 경로, render 결과가 어떤 C++ 호출로 이어지는가
04. 렌더 파이프라인 render → commit → mount 3단계, 동기 측정이 가능해진 시점, 레이아웃-페인트의 책임 분담
05. Yoga 레이아웃 C++로 작성된 Flexbox 엔진, 웹·iOS·Android에 일관된 레이아웃을 보장하는 동기 측정 API
06. 동시성과 우선순위 React 18 동시성 모드가 Fabric에서 어떻게 살아나는가, 우선순위 기반 인터럽트의 네이티브 측 구현

🔹 Chapter 5: TurboModules와 네이티브 모듈

핵심 질문: 네이티브 모듈이 JSI 위에 올라타면 무엇이 달라지는가?

지연 로딩, Codegen, 모듈 작성, 경계 비용까지 (5개 문서)
문서 다루는 내용
01. TurboModules JSI 기반 네이티브 모듈 — 지연 로딩동기 호출, 앱 시작 시 모든 모듈을 미리 로드하던 구형 패턴과의 결별
02. NativeModules 비교 구형 Bridge 기반 NativeModules vs JSI 기반 TurboModules의 호출 경로·시그니처·비용 비교
03. Codegen TypeScript Spec → C++/Java/Obj-C 인터페이스 자동 생성, 타입 불일치를 빌드 타임에 잡는 메커니즘
04. 네이티브 모듈 작성 Android(Kotlin)와 iOS(Swift)로 TurboModule을 직접 작성, 경계를 어디에 그을지에 대한 설계 결정
05. 경계 비용 JSI에서도 여전히 존재하는 호출당 오버헤드, 큰 데이터를 어떻게 다룰지(ArrayBuffer·shared memory) 결정 기준

🔹 Chapter 6: Hermes 엔진

핵심 질문: Hermes는 어떻게 모바일 앱 시작 시간을 거의 0으로 만드는가?

바이트코드 사전 컴파일, V8 비교, 모바일 GC까지 (5개 문서)
문서 다루는 내용
01. Hermes란 RN 전용 경량 JS 엔진의 설계 목표 — JIT를 포기하고 시작 비용메모리를 우선한 모바일 최적화
02. 바이트코드 사전 컴파일 빌드 타임에 .hbc 바이트코드를 생성해 앱 번들에 포함, 런타임 파싱·컴파일 비용을 제거하는 흐름
03. V8과 비교 V8의 JIT 계층(Ignition·TurboFan) vs Hermes의 AOT 바이트코드 전용 — 시작·메모리·정상상태 처리량의 트레이드오프
04. 메모리와 GC 모바일 제약(작은 힙·앱 일시정지 시 swap)에 맞춘 세대 GC, V8의 incremental marking과의 설계 차이
05. 디버깅 Hermes 디버거 + Chrome DevTools 프로토콜, 바이트코드 수준 추적, 프로덕션에서도 켤 수 있는 sampling profiler

🔹 Chapter 7: 성능과 실전

핵심 질문: 같은 화면을 Old/New Architecture로 만들면 얼마나 다른가?

측정 도구, 흔한 병목, 마이그레이션, 종합 비교까지 (4개 문서)
문서 다루는 내용
01. 성능 측정 Flipper · React DevTools · Systrace · Instruments를 경계별로 분리해서 보는 법, JS 스레드 vs 네이티브 추적
02. 흔한 병목 과한 Bridge/JSI 호출, 큰 리스트(FlatList vs FlashList), 이미지 디코딩 — 각 병목의 측정 방법과 회피 패턴
03. New Architecture 마이그레이션 기존 RN 앱을 New Architecture로 점진 전환, interop 레이어가 보장하는 호환성과 깨지는 지점
04. 종합 — Old vs New 실측 같은 화면(리스트·애니메이션·제스처)을 Old와 New로 직접 측정, p50/p99/메모리/시작 시간 비교

🗺️ 목적별 학습 경로

🟢 "Bridge가 왜 느리고 JSI가 무엇을 바꾸는가" 정확히 알고 싶다 — 면접/실무 의문 해소 (2주)

Week 1 — 두 세계와 구형 Bridge

Ch1-02  스레드 모델
Ch1-03  두 세계
Ch2-01  Bridge 구조
Ch2-02  직렬화 통신
Ch2-05  왜 느린가

Week 2 — JSI로의 전환

Ch3-01  JSI란
Ch3-02  동기 호출
Ch3-06  Bridge → JSI 비교
Ch5-01  TurboModules
Ch7-04  Old vs New 실측
🔵 RN 내부를 원리로 이해하고 싶은 개발자 (7주)
Week 1  Chapter 1 전체 — 아키텍처 개요와 스레드 모델
Week 2  Chapter 2 전체 — 구형 Bridge의 한계
Week 3  Chapter 3 전체 — JSI 기반
Week 4  Chapter 4 전체 — Fabric 렌더러
Week 5  Chapter 5 전체 — TurboModules와 네이티브 모듈
Week 6  Chapter 6 전체 — Hermes 엔진
Week 7  Chapter 7 전체 — 성능과 실전 비교
🔴 네이티브 모듈을 작성하는 개발자의 집중 코스
핵심 경로 (Android/iOS 어느 쪽이든 적용 가능)

Step 1  Ch1-02~03  스레드 소유권과 두 세계
Step 2  Ch3-01~03  JSI · 동기 호출 · HostObject
Step 3  Ch3-05     메모리·생명주기 (JSI 객체 소유)
Step 4  Ch5-01~03  TurboModules와 Codegen
Step 5  Ch5-04     네이티브 모듈 직접 작성
Step 6  Ch5-05     경계 비용 — 무엇을 어디서 처리할지
Step 7  Ch7-02     흔한 병목과 회피 패턴

각 문서의 "📊 측정" 섹션에서 페이로드 크기·호출 빈도·지연을 확인하세요.
🟡 성능 병목을 찾고 고치는 개발자의 집중 코스
핵심 경로 (Old/New Architecture 양쪽에서 측정 가능해야 의미가 있음)

Step 1  Ch1-02     스레드 모델 — 누가 무엇을 하는지부터
Step 2  Ch2-03~05  Bridge의 한계 · 3스레드 흐름 · 왜 느린가
Step 3  Ch3-06     Bridge → JSI 비교 — 정량 차이의 출처
Step 4  Ch4-04     렌더 파이프라인 — 동기 측정이 가능해진 지점
Step 5  Ch6-02~03  Hermes 바이트코드 · V8과 비교 — 시작 비용의 정체
Step 6  Ch7-01     성능 측정 — Flipper · Systrace · perfetto · Instruments
Step 7  Ch7-02     흔한 병목 — 통신·리스트·이미지 디코딩
Step 8  Ch7-04     종합 실측 — 같은 화면을 Old/New로 매트릭스 비교

각 문서의 "💻 실전 실험"에서 도구를 직접 띄워 추적하세요.

📖 각 문서 구성 방식

모든 문서는 동일한 구조로 작성됩니다.

섹션 설명
🎯 핵심 질문 이 문서를 읽고 나면 답할 수 있는 질문
🔍 왜 이게 존재하는가 문제 상황과 설계 배경
😱 흔한 오해 또는 잘못된 사용 Before — 많은 RN 개발자가 틀리는 방식
올바른 이해와 사용 After — 경계를 알고 난 후의 올바른 접근
🔬 내부 동작 원리 Bridge/JSI 호출 흐름 + Fabric 파이프라인 + Hermes 바이트코드 추적
💻 실전 실험 실행 가능한 RN 코드 + Flipper/DevTools 스크린샷 + 네이티브 모듈 작성
📊 측정 Old vs New Architecture 비교 / Hermes vs JSC / 페이로드 크기별 호출 비용
🤔 트레이드오프 이 설계의 장단점, 언제 다른 방법을 택할 것인가
📌 핵심 정리 한 화면 요약
🤔 생각해볼 문제 개념을 더 깊이 이해하기 위한 질문 + 해설

🔬 검증 환경

Node + RN CLI + 시뮬레이터/실기. 핵심은 Flipper · React DevTools · Systrace · perfetto · Instruments · Chrome DevTools(Hermes CDP) · TurboModule 작성 입니다.

# 신규 프로젝트 (New Architecture · Hermes 기본)
npx react-native@latest init RNLab
cd RNLab

# 핵심 검증 도구 1 — Old/New Architecture 토글
# iOS:    Podfile의 newArchEnabled 플래그
# Android: gradle.properties의 newArchEnabled=true
#  → 같은 화면을 두 모드로 빌드해서 측정

# 핵심 검증 도구 2 — Flipper / React DevTools
#  JS 스레드 프로파일, 네이티브 뷰 계층, 네트워크
#  Fabric에서는 동기 측정·레이아웃 시각화

# 핵심 검증 도구 3 — 네이티브 스레드 추적
#  Android: Systrace / perfetto trace
#    python systrace.py -t 5 sched gfx view -a com.rnlab
#    perfetto --txt -c trace.cfg -o trace.perfetto
#  iOS:    Instruments (Time Profiler · System Trace)
#  → JS·Shadow·Main 스레드의 실제 분업을 타임라인으로 관찰

# 핵심 검증 도구 4 — Hermes 바이트코드 & 프로파일
hermesc -emit-binary -out app.hbc app.js
hermes-tool dump-bytecode app.hbc
#  → 빌드 타임에 .hbc가 생성되는 흐름, 디스어셈블로 직접 확인
#  Hermes sampling profiler 결과를 Chrome DevTools 형식으로 변환
npx hermes-profile-transformer input.cpuprofile -o chrome.cpuprofile
#  Chrome → chrome://inspect → Hermes CDP로 직접 디버깅

# 실측 실험
#  TurboModule(Codegen) Android(Kotlin) / iOS(Swift) 작성
#  큰 데이터(이미지 바이트·문자열)를 Bridge vs JSI로 N회 왕복 → 비용 비교
#  큰 리스트: FlatList vs FlashList — 메모리·스크롤 FPS 비교
#  Yoga: 같은 Flexbox 트리가 웹/네이티브에서 동일하게 측정되는지 검증

🔗 레포 연결

⬆️ 선행 학습
  react-internals-deep-dive        → Fiber와 재조정 (Fabric의 입력)
  javascript-deep-dive             → JS 의미와 이벤트 루프
  android-framework-internals      → android.View · Looper (네이티브 출력)
  uikit-core-animation             → UIView · Core Animation (네이티브 출력)

🤝 시너지
  v8-engine-deep-dive              → Hermes와 대비되는 V8 JIT 전략
  event-loop-async-deep-dive       → JS 스레드 · 마이크로태스크
  flutter-deep-dive                → "네이티브 뷰 제어" vs "자체 렌더" 대조

🧬 수렴 (렌더링 파이프라인 비교)
  rendering-pipelines-compared     → RN(네이티브 뷰) ↔ Flutter(자체 렌더) ↔ Web(브라우저)

🙏 Reference

공식 아키텍처

소스 코드

도구·실측

  • Flipper — 네이티브 디버거 플랫폼 (Bridge/JSI 추적 플러그인)
  • perfetto — Android 시스템 트레이싱 (Systrace 후속)
  • hermes-profile-transformer — Hermes sampling profiler → Chrome DevTools 변환
  • FlashList by ShopifyFlatList 병목을 해결한 고성능 리스트 (Ch7-02 사례)

⭐️ 도움이 되셨다면 Star를 눌러주세요!

Made with ❤️ by Dev Book Lab


"RN으로 만드는 것과, JS와 네이티브가 어떤 경계로 통신하는지 아는 것은 다르다"

About

RN으로 앱을 만드는 것과, JS와 네이티브가 어떤 경계로 통신하고 그 경계가 어떻게 진화했는지 아는 것은 다르다

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors