--- id: mobile-native-module-bridging-deep title: Native Module Bridging β€” RN / Flutter / KMP category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [mobile, rn, flutter, vibe-coding] tech_stack: { language: "TS / Swift / Kotlin", applicable_to: ["Mobile"] } applied_in: [] aliases: [native module, JSI, bridge, platform channels, FFI, Kotlin/Native, Swift/C interop] --- # Native Module Bridging Deep > Cross-platform κ°€ native API 호좜. **RN JSI, Flutter platform channel, KMP expect/actual, FFI**. ## πŸ“– 핡심 κ°œλ… - Cross-platform κ°€ λ§€ native 의 wrap. - Bridge / channel κ°€ cost. - Modern: JSI (RN), MethodChannel (Flutter). - KMP = native interop. ## πŸ’» μ½”λ“œ νŒ¨ν„΄ ### React Native New Architecture (JSI) ```cpp // NativeMyModule.h (TurboModule) class NativeMyModule : public TurboModule { public: facebook::jsi::Value getDeviceInfo(facebook::jsi::Runtime &runtime); }; ``` ```ts // JS import NativeMyModule from './NativeMyModule'; const info = NativeMyModule.getDeviceInfo(); // β†’ JSI = direct call. 빠름. ``` β†’ Old: JSON bridge (slow). New: JSI (synchronous, fast). ### iOS (Swift) ```swift // MyModule.swift @objc(MyModule) class MyModule: NSObject { @objc func getDeviceInfo(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) { let info = ['model': UIDevice.current.model] resolve(info) } @objc static func requiresMainQueueSetup() -> Bool { return true } } ``` ### Android (Kotlin) ```kotlin class MyModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { override fun getName() = "MyModule" @ReactMethod fun getDeviceInfo(promise: Promise) { promise.resolve(mapOf("model" to Build.MODEL)) } } ``` ### TurboModule (modern RN) ```ts // TS spec import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { getDeviceInfo(): Object; multiply(a: number, b: number): number; } export default TurboModuleRegistry.getEnforcing('MyModule'); ``` β†’ Code generated. Type-safe. ### Flutter platform channel ```dart // lib/my_module.dart import 'package:flutter/services.dart'; class MyModule { static const channel = MethodChannel('my_module'); static Future getDeviceInfo() async { return await channel.invokeMethod('getDeviceInfo'); } } ``` ### Flutter iOS (Swift) ```swift @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application(...) -> Bool { let controller = window?.rootViewController as! FlutterViewController let channel = FlutterMethodChannel(name: 'my_module', binaryMessenger: controller.binaryMessenger) channel.setMethodCallHandler { call, result in if call.method == 'getDeviceInfo' { result(['model': UIDevice.current.model]) } } } } ``` ### Flutter Pigeon (type-safe) ```dart // pigeons/messages.dart @HostApi() abstract class MyApi { @async Map getDeviceInfo(); } ``` β†’ Codegen κ°€ native + Dart side. ### KMP (expect / actual) ```kotlin // commonMain expect class Platform() { val name: String } // androidMain actual class Platform { actual val name = 'Android ${Build.VERSION.SDK_INT}' } // iosMain actual class Platform { actual val name = 'iOS ${UIDevice.currentDevice.systemVersion}' } ``` ### KMP iOS interop ```kotlin // iosMain import platform.UIKit.UIDevice import platform.Foundation.NSDate fun getDate() = NSDate() fun getDevice() = UIDevice.currentDevice ``` β†’ Apple SDK κ°€ Kotlin μ•ˆ. ### Swift / C interop ```swift // Swift 의 C function call import Darwin let pid = getpid() ``` ```swift // Swift κ°€ C struct let buf = UnsafeMutablePointer.allocate(capacity: 100) strcpy(buf, 'hello') ``` ### Rust FFI ```rust #[no_mangle] pub extern 'C' fn add(a: i32, b: i32) -> i32 { a + b } ``` ```c // C header int32_t add(int32_t a, int32_t b); ``` β†’ iOS / Android κ°€ Rust shared library. ### React Native + Rust ```ts // react-native-uniffi. // β†’ Rust β†’ JSI native module. ``` β†’ Cryptography, ML inference μΉœν™”. ### Performance ``` JSON bridge (μ˜› RN): 10-100 ms / call. JSI / TurboModule: < 1 ms. Flutter platform channel: ~1 ms. KMP: ~ direct call (no bridge). FFI: native speed. β†’ Modern = bridge cost 거의 X. ``` ### Codegen ``` RN: Codegen (TS spec β†’ C++ binding). Flutter: Pigeon. KMP: 자체 (no codegen). β†’ Type-safe + λΉ λ₯Έ development. ``` ### Async vs sync ``` JSI (RN): sync κ°€λŠ₯. Platform channel (Flutter): async 만. KMP: λ§€ (suspend OK). β†’ Sync κ°€ μ•½κ°„ 빠름 κ°€, deadlock μœ„ν—˜. ``` ### Threading ``` Native callback κ°€ main thread or background: - iOS: dispatch_async. - Android: Handler / Coroutine. - 잘λͺ» = crash. ``` ### Plugin ecosystem ``` RN: - npm install + auto-link (RN 0.60+). - TurboModule κ°€ modern. Flutter: - pub.dev. - Plugin 의 Dart + native. KMP: - Maven / CocoaPods. - Compose Multiplatform. ``` ### When NOT bridge? ``` - Pure UI: framework UI κ°€ μΆ©λΆ„. - Network: HTTP client (cross-platform). - Storage: SQLite / KV (cross-platform library). β†’ Native API 만 (Bluetooth, sensor, AR) bridging. ``` ### Real native vs bridged ``` Camera: - Native: AVCaptureSession (iOS), CameraX (Android). - Bridged: react-native-camera, image_picker (Flutter). β†’ λ§€ platform 의 nuance. Bridge 의 quality = library 따라. ``` ### Bluetooth (예) ``` RN: react-native-ble-plx. Flutter: flutter_blue_plus. KMP: kable. β†’ λ§€ κ°€ native API 의 wrapper. ``` ### ML (Core ML / TFLite) ``` RN: react-native-fast-tflite. Flutter: tflite_flutter. KMP: 자체 wrap. β†’ Performance κ°€ native speed. ``` ### Debug ``` Native crash: - iOS: Xcode debug + symbol. - Android: Logcat + adb. - Flutter: flutter logs. - RN: react-native log. β†’ Native crash κ°€ cross-platform 의 어렀움. ``` ### Cross-platform library ``` - SQLite (λͺ¨λ“ ). - Realm (RN, Flutter). - WatermelonDB (RN). - Drift (Flutter). - SQLDelight (KMP). β†’ 1 library, λͺ¨λ“  platform. ``` ### Type safety ``` TurboModule (RN): TS spec β†’ μžλ™ type. Pigeon (Flutter): Dart spec β†’ μžλ™ type. KMP: Kotlin types κ°€ native. β†’ Manual writing κ°€ typo / drift μœ„ν—˜. ``` ### Production tips ``` 1. TurboModule / Pigeon (codegen). 2. Async wherever possible. 3. Native crash report (Sentry). 4. Test κ°€ λ§€ platform. 5. Plugin 신쀑 선택 (maintenance). 6. Native module version pin. ``` ### Common 함정 ``` - Main thread block: ANR / freeze. - Memory leak (callback ref). - Native crash κ°€ silent. - Plugin 의 maintainer 0. - Old bridge (RN 0.60 μ΄ν•˜). - Synchronous on Flutter: μ•ˆ 됨. ``` ## πŸ€” μ˜μ‚¬κ²°μ • κΈ°μ€€ | Cross-platform | Native bridge | |---|---| | RN | TurboModule | | Flutter | Pigeon (Dart + native) | | KMP | expect/actual | | Rust shared | FFI | | Multi-FW | KMP | | Native UI 도 | λ§€ native UI separate | ## ❌ μ•ˆν‹°νŒ¨ν„΄ - **Old RN bridge**: slow. - **Sync from main**: ANR. - **Manual type binding**: drift. - **Plugin κ°€ unmaintained**: vulnerable. - **Memory leak in callback**: crash. ## πŸ€– LLM ν™œμš© 힌트 - TurboModule (RN), Pigeon (Flutter), expect/actual (KMP). - Codegen κ°€ type-safe + λΉ λ₯Έ dev. - FFI κ°€ Rust / C interop. - Native API 만 bridge (UI X). ## πŸ”— κ΄€λ ¨ λ¬Έμ„œ - [[Mobile_RN_New_Architecture]] - [[Mobile_KMP_Deep]] - [[Mobile_Flutter_Patterns]]