--- id: mobile-rn-new-architecture title: React Native New Architecture — Fabric / TurboModule / JSI category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [react-native, fabric, turbomodule, jsi, vibe-coding] tech_stack: { language: "TS / Swift / Kotlin", applicable_to: ["React Native"] } applied_in: [] aliases: [Fabric, TurboModule, JSI, Codegen, Bridgeless, Hermes] --- # RN New Architecture (2024+) > 옛 Bridge → JSI 직접 호출. **Fabric (rendering) + TurboModule (native module) + Codegen (type-safe)**. 0.74+ default. 빠르고 type-safe. ## 📖 핵심 개념 - JSI (JavaScript Interface): JS ↔ native 직접 binding (bridge X). - Fabric: 새 renderer, concurrent React 호환. - TurboModule: lazy 로드 + sync 호출 가능. - Codegen: TS spec → C++/Swift/Kotlin 인터페이스 자동. - Bridgeless: 옛 bridge 완전 제거. ## 💻 코드 패턴 ### 활성화 ```jsonc // react-native.config.js / package.json "reactNativeArchVersion": "new", // iOS — Podfile :fabric_enabled => true, :hermes_enabled => true, :new_arch_enabled => true, // Android — gradle.properties newArchEnabled=true hermesEnabled=true ``` ### TurboModule spec (TS) ```ts // specs/NativeBattery.ts import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { // sync methods 가능 getBatteryLevel(): number; // async (Promise) getInfo(): Promise<{ level: number; charging: boolean }>; // void setBrightness(value: number): void; // Event listener readonly addListener: (eventType: string) => void; readonly removeListeners: (count: number) => void; } export default TurboModuleRegistry.getEnforcing('NativeBattery'); ``` ### Codegen 실행 ```bash # iOS npx pod-install # Codegen 자동 실행 # Android cd android && ./gradlew generateCodegenArtifactsFromSchemas ``` → Auto-generate Objective-C++ / Java interface. ### iOS — Swift 구현 ```swift @objc(NativeBattery) class NativeBattery: NSObject { @objc static func requiresMainQueueSetup() -> Bool { false } @objc func getBatteryLevel() -> NSNumber { UIDevice.current.isBatteryMonitoringEnabled = true return NSNumber(value: UIDevice.current.batteryLevel) } @objc(getInfoWithResolver:rejecter:) func getInfo(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { // ... } } ``` ### Android — Kotlin 구현 ```kotlin class NativeBatteryModule(reactContext: ReactApplicationContext) : NativeBatterySpec(reactContext) { override fun getName() = "NativeBattery" override fun getBatteryLevel(): Double { val bm = reactApplicationContext.getSystemService(Context.BATTERY_SERVICE) as BatteryManager return bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) / 100.0 } override fun getInfo(promise: Promise) { // ... } } ``` ### Fabric Component (native UI) ```ts // CustomViewNativeComponent.ts import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps } from 'react-native'; import type { Float, Int32 } from 'react-native/Libraries/Types/CodegenTypes'; export interface NativeProps extends ViewProps { color?: string; size?: Float; } export default codegenNativeComponent('CustomView'); ``` ```swift // iOS Fabric component class CustomViewComponentView: RCTViewComponentView { override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .red } override func updateProps(_ props: Props, oldProps: Props) { let newProps = Self.componentDescriptorProvider().rawProps(from: props) // apply super.updateProps(props, oldProps: oldProps) } } ``` ### JSI direct binding (advanced — 큰 데이터) ```cpp // C++ #include void install(jsi::Runtime& rt) { auto myFn = jsi::Function::createFromHostFunction( rt, jsi::PropNameID::forAscii(rt, "myFn"), 1, [](jsi::Runtime& rt, const jsi::Value& thisValue, const jsi::Value* args, size_t count) -> jsi::Value { // 직접 처리 — bridge 없음 return jsi::Value(42); } ); rt.global().setProperty(rt, "myFn", myFn); } ``` → 매우 hot path 만 (보통 TurboModule 충분). ### Hermes (JS engine) ``` Default JS engine = Hermes (vs JSC). + Bytecode pre-compile = 빠른 시작 + 작은 메모리 + 정적 분석 친화 ``` ```jsonc // metro.config.js hermesEnabled: true ``` ### Concurrent React 활용 (Fabric) ```tsx import { startTransition } from 'react'; // State update 분리 startTransition(() => { setHeavyState(newValue); }); // useDeferredValue const deferred = useDeferredValue(input); ``` → 무거운 업데이트가 input 안 막음. ### Performance (구 vs 신) ``` 옛 Bridge: - JS ↔ Native = JSON serialize - Async only - Bridge contention JSI / TurboModule: - 직접 binding - Sync 가능 - Lazy load (사용 시) - Codegen = type-safe ``` → 50-100ms 시작 절감, 일부 동기 작업 10x 빠름. ### Migration 옛 module → TurboModule ``` 1. TS spec 정의 2. Codegen 실행 3. Native 구현 (NativeXxxSpec extend) 4. NativeModules.X → TurboModuleRegistry.get('X') ``` ### 디버깅 ``` Flipper (RN built-in) — deprecated. 새 = React DevTools + 별 도구. Hermes profiler: $ adb shell am profile com.app start ``` ### Common 문제 ``` 1. Pod install 실패 → cd ios; pod install --repo-update 2. Codegen 결과 mismatch → clean build, ios/build, android/.gradle 삭제 3. Hermes bytecode 호환 안 — RN version 업데이트 동기 4. Native module 못 찾음 → autolinking 확인 + spec 의 module 이름 일치 ``` ## 🤔 의사결정 기준 | 상황 | 추천 | |---|---| | 새 RN 프로젝트 | New arch + Hermes default | | 기존 옛 arch | 0.74+ migration | | Sync 호출 필요 (battery, device) | TurboModule | | Native UI custom | Fabric Component | | 매우 hot path | JSI direct | | 단순 native logic | TurboModule 충분 | ## ❌ 안티패턴 - **옛 NativeModule + 새 arch**: 호환성 문제. 변환. - **Sync TurboModule + 무거운 작업**: UI 막음. async. - **Codegen 결과 commit X**: CI 빌드 필요. - **JSI 직접 + 잘못된 lifetime**: crash. weak ref. - **TurboModule 가 ReactApplicationContext 사용**: thread 주의. - **iOS / Android 구현 비대칭**: cross-platform 깨짐. ## 🤖 LLM 활용 힌트 - 새 RN = New arch default. - TurboModule + Codegen 으로 type-safe. - Sync 가능 = battery / config — 적극 활용. - Hermes 가 표준. ## 🔗 관련 문서 - [[RN_Native_Module_Bridging]] - [[RN_Hermes_Optimization]] - [[React_Native_Bridge_Performance]]