Notice
Recent Posts
Recent Comments
Link
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

유리의 개발새발

[RN] Native Module (legacy) 본문

React Native

[RN] Native Module (legacy)

yuri_ 2025. 9. 4. 22:44
반응형

공식 문서를 기반으로 한 번 해보져.

https://reactnative.dev/docs/legacy/native-modules-intro

 

Native Modules Intro · React Native

Sometimes a React Native app needs to access a native platform API that is not available by default in JavaScript, for example the native APIs to access Apple or Google Pay. Maybe you want to reuse some existing Objective-C, Swift, Java or C++ libraries wi

reactnative.dev

Android에서 먼저 시작

Android는 비교적 구조가 단순하니 여기서부터 해보겠습니다.

비교적 Android가 쉬우니까 먼저 해보겠습니다.

1. CalendarModule.kt 작성

android/app/src/main/java/com/{프로젝트명}/CalendarModule.kt 생성.

package com.practice_rn_app
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import android.util.Log

class CalendarModule(reactContext: ReactApplicationContext) 
  : ReactContextBaseJavaModule(reactContext) {

    override fun getName() = "CalendarModule"

    @ReactMethod
    fun createCalendarEvent(name: String, location: String) {
        Log.d("CalendarModule", "Create event called with name: $name, location: $location")
    }
}

✔ getName() → JS에서 모듈을 불러올 때 사용할 이름 지정
✔ @ReactMethod → JS에서 호출 가능한 메서드 표시

JS에서는 이렇게 접근합니다.

import { NativeModules } from 'react-native';
const { CalendarModule } = NativeModules;

CalendarModule.createCalendarEvent('회의', '서울');

2. 패키지 등록

android/app/src/main/java/com/{프로젝트명}/MyAppPackage.kt 생성

package com.practice_rn_app

import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager

class MyAppPackage : ReactPackage {
    override fun createViewManagers(
        reactContext: ReactApplicationContext
    ): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()

    override fun createNativeModules(
        reactContext: ReactApplicationContext
    ): MutableList<NativeModule> =
        listOf(CalendarModule(reactContext)).toMutableList()
}

 

3. MainApplication.kt에 등록

override fun getPackages(): List<ReactPackage> =
    PackageList(this).packages.apply {
        add(MyAppPackage()) // 직접 만든 패키지 추가
    }

여기까지 하면 Android 네이티브 모듈 등록 완료! 🎉

너무 쉽지 않나요?


iOS에서 CalendarModule 만들기

이제 iOS 차례입니다.
⚠️ 팁: iOS는 Xcode에서 작업하는 게 정신 건강에 좋아요.

1. 헤더 파일 작성

RCTCalendarModule.h

#import <React/RCTBridgeModule.h>

@interface RCTCalendarModule : NSObject <RCTBridgeModule>
@end

 

클래스 이름: RCTCalendarModule
Objective-C에는 네임스페이스가 없으므로 접두어(prefix)를 붙이는 게 일반적입니다. 여기서 RCT는 React를 의미합니다.

2. 구현 파일 작성

RCTCalendarModule.m

#import "RCTCalendarModule.h"
#import <React/RCTLog.h>

@implementation RCTCalendarModule

// 모듈 등록
RCT_EXPORT_MODULE();

// JS에서 호출할 수 있는 메서드 정의
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location) {
  RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
}

@end

✔ RCT_EXPORT_MODULE() → 모듈 등록. 인자 없이 쓰면 클래스명에서 RCT 접두어가 빠진 이름(CalendarModule)으로 JS에 노출됩니다.
✔ RCT_EXPORT_METHOD → JS에서 접근 가능한 메서드. 반환값은 항상 void (비동기).

JS에서는 이렇게 사용합니다.

import { NativeModules } from 'react-native';
const { CalendarModule } = NativeModules;

CalendarModule.createCalendarEvent('스터디', '카페');
 

🚨 동기 메서드 주의

@ReactMethod(isBlockingSynchronousMethod = true) (Android)
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD (iOS)

동기 호출도 가능하지만 성능 저하 + 스레드 버그 위험이 크고, Chrome 디버거도 못 쓰게 되니 특별한 이유가 없다면 비추천합니다.


Android vs iOS 네이티브 모듈 파일 구조

1. 모듈 파일 (예: CalendarModule.kt)

  • 역할: 실제 네이티브 기능 구현
  • ReactContextBaseJavaModule(레거시) 또는 Native…Spec(Turbo) 상속
  • getName() → JS에서 사용할 모듈 이름 정의
  • @ReactMethod 붙은 메서드 → JS에서 호출 가능
  • 쉽게 말하면: “이 파일이 JS에서 호출되는 기능 본체”

2. 패키지 파일 (예: MyAppPackage.kt)

  • 역할: React Native에 내가 만든 모듈을 등록하는 관리자
  • ReactPackage 인터페이스 구현
  • createNativeModules()에서 내 모듈 인스턴스를 반환
  • MainApplication에서 getPackages()에 추가해야 함
  • 쉽게 말하면: “앱이 실행될 때 내 모듈을 React Native에 연결해 주는 다리”

🍎 iOS

1. 헤더 파일 (예: RCTCalendarModule.h)

  • 역할: 인터페이스(명세) 정의
  • @interface RCTCalendarModule : NSObject <RCTBridgeModule>
  • 이 파일을 통해 “이 클래스는 네이티브 모듈이고, 이런 메서드들을 가질 수 있다”를 알림
  • 쉽게 말하면: “이 모듈은 이런 기능을 가질 거야!” 선언문

2. 구현 파일 (예: RCTCalendarModule.m)

  • 역할: 실제 기능 구현
  • RCT_EXPORT_MODULE() → JS에서 사용할 모듈 이름 등록
  • RCT_EXPORT_METHOD → JS에서 호출 가능한 메서드 구현
  • RCTLogInfo 같은 API 호출로 동작 확인 가능
  • 쉽게 말하면: “헤더에서 약속한 기능을 실제로 만드는 곳”

// ++

📝 브리징 헤더(Bridging Header)란?

  • Swift 코드에서 Objective-C 코드(헤더 파일)를 가져다 쓰려면 필요한 파일이에요.
  • 즉, Swift ↔ ObjC 간 상호운용을 위해 자동으로 생성하자고 Xcode가 묻는 겁니다.
  • React Native 네이티브 모듈은 전통적으로 Objective-C 예제로 제공되는데, 프로젝트 기본 언어를 Swift로 만들면 Xcode가 “Swift에서 ObjC 코드를 쓸 거면 브리징 헤더를 만들래?” 하고 물어보는 거죠.

🤔 왜 필요한가?

React Native 예제는 보통 Objective-C(.m, .h) 기반으로 제공되는데,
프로젝트 기본 언어를 Swift로 만들면 Xcode가 묻습니다:

“Swift에서 ObjC 코드도 쓸 거야? 그럼 내가 브리징 헤더 만들어 줄까?”

👉 예를 누르면 프로젝트명-Bridging-Header.h라는 파일이 생깁니다.

🛠️ 어떻게 쓰는가?

1. 브리징 헤더 파일 안에, Swift에서 쓰고 싶은 ObjC 헤더를 #import 합니다.

 

예시 (practice_rn_app-Bridging-Header.h)

#import "RCTCalendarModule.h"
#import <React/RCTLog.h>

 

2. 그러면 Swift 파일에서 별도의 import 없이 바로 해당 클래스/함수를 쓸 수 있습니다.

예시 (Swift 네이티브 모듈)

import Foundation

@objc(CalendarModule)
class CalendarModule: NSObject {
  @objc func createCalendarEvent(_ name: String, location: String) {
    RCTLogInfo("Create event called with name: \(name), location: \(location)")
  }
}

 

✅ 요약

  • ObjC 기반 코드를 Swift에서 사용하려면 브리징 헤더가 필요하다.
  • Swift 기반 프로젝트인데 ObjC 모듈을 추가하면 Xcode가 자동으로 “브리징 헤더 만들래?” 하고 물어본다.
  • ObjC만 쓰거나 Swift만 쓰면 필요 없다.
  • Swift + ObjC 혼합 프로젝트일 때만 필요하다.

지금 .m/.h로 모듈을 짜고 있다면 브리징 헤더는 필요 없음.
Swift로 네이티브 모듈을 만들고 싶을 때만 신경 쓰면 됩니다.

반응형

'React Native' 카테고리의 다른 글

[RN] 프로젝트 초기에 할 것  (0) 2025.12.24
[RN] 채팅 기능 (socket.io)  (0) 2025.09.07
[RN] Firebase FCM 02  (4) 2025.08.26
[RN] Firebase FCM  (7) 2025.08.26
[RN] react-native-seoul/kakao-login issue  (0) 2025.02.15