본문 바로가기
React Native

RN에서 네이티브 코드 불러오기

by 붕어사랑 티스토리 2025. 11. 6.
반응형

1. expo module

 

플러터에서는 네이티브 코드를 호출하려면 메소드 채널, 이벤트 채널이라는걸 사용했는데 rn에서는 모듈이라는걸 사용한다.

 

 

먼저 프리빌드를 한 뒤 모듈을 설치해준다

 

npx expo prebuild
npx create-expo-module@latest --local

 

 

 

2. module의 구조

 

모듈을 설치하면 아래와 같은 폴더구조가 생긴다

 

module/
  모듈폴더/
    android/
      네이티브모듈.kt
      네이티브뷰.kt
    ios/
      네이티브모듈.swift
      네이티브뷰.swift
    src/
      타입스크립트.types.ts
      타입스크립트모듈.ts
    expo-module.config.json
    index.ts

 

 

여기서 index.ts가 가장 최상단 구조이고 여기서 export한걸 expo에서 임포트 할 수 있다.

 

 

 

index.ts

여기서 ABC는 MyModule 익스포트한걸 ABC로 바꾼건데 이를 expo단에서 ABC로 임포트해서 사용 가능

TestModule은 디폴트 모듈 이외에 본인이 추가하고 싶은게 있다면 저런식으로 추가하면 된다.

// Reexport the native module. On web, it will be resolved to DbbeatsModule.web.ts
// and on native platforms to DbbeatsModule.ts
export * from './src/Dbbeats.types';
export { default as ABC } from './src/MyModule';
export { default as MyView } from './src/MyView';
export { default as TestModule } from './src/TestModule';

 

 

 

 

 

 

타입스크립트모듈.ts

타입스크립트모듈.ts는 파일이 여러개여도 된다.(모듈이 여러개라는 뜻) 그에맞춰 네이티브 모듈 파일수도 늘어나야 한다.

여기서 위 코드를 보면 모듈이름이 Test라는걸 읽어오겠다는 뜻이고, declare class 부분은 함수 목록을 나타낸다.

 

모듈을 추가할때는 반드시 expo-module.config.json에서 모듈을 추가로 등록해주어야 빌드된다!

import { NativeModule, requireNativeModule } from 'expo';

import { TestModuleEvents } from './Test.types';

declare class TestModule extends NativeModule<TestModuleEvents> {
  PI: number;
  hello(): string;
  setValueAsync(value: string): Promise<void>;
}

// This call loads the native module object from the JSI.
export default requireNativeModule<TestModule>('Test');

 

 

 

 

 

 

네이티브모듈.kt


앞서 타입스크립트 모듈에서 문자열로 이름을 지정해서 네이티브 모듈을 읽어오는걸 보았다.

아래 코드는 그 내용을 나타낸다.

 

  • 먼저 Name('Test')로 이름을 정해서 타입스크립트 모듈에서 읽어갈 수 있도록 한다
  • Function을 이용해서 타입스크립트에서 정의했던 함수 모양과 맞추어 함수를 작성해준다
class TestModule : Module() {
  // Each module class must implement the definition function. The definition consists of components
  // that describes the module's functionality and behavior.
  // See https://docs.expo.dev/modules/module-api for more details about available components.
  override fun definition() = ModuleDefinition {
    // Sets the name of the module that JavaScript code will use to refer to the module. Takes a string as an argument.
    // Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
    // The module will be accessible from `requireNativeModule('Dbbeats')` in JavaScript.
    Name("Test")

    // Defines constant property on the module.
    Constant("PI") {
      Math.PI
    }

    // Defines event names that the module can send to JavaScript.
    Events("onChange")

    // Defines a JavaScript synchronous function that runs the native code on the JavaScript thread.
    Function("hello") {
      "Hello Test!! 👋"
    }

    // Defines a JavaScript function that always returns a Promise and whose native code
    // is by default dispatched on the different thread than the JavaScript runtime runs on.
    AsyncFunction("setValueAsync") { value: String ->
      // Send an event to JavaScript.
      sendEvent("onChange", mapOf(
        "value" to value
      ))
    }

    // Enables the module to be used as a native view. Definition components that are accepted as part of
    // the view definition: Prop, Events.
    View(DbbeatsView::class) {
      // Defines a setter for the `url` prop.
      Prop("url") { view: DbbeatsView, url: URL ->
        view.webView.loadUrl(url.toString())
      }
      // Defines an event that the view can send to JavaScript.
      Events("onLoad")
    }
  }
}

 

 

 

 

모듈 여러개 등록하기

 

expo module을 설치하면 기본적으로 하나의 모듈만 등록되어있다. 폴더 구조를 보면 여러개를 등록 가능해보이고 실제로 가능하다.

 

앞서 설명된 내용으로 이미 유추 가능하겠지만 아래와 같은 flow로 진행된다.

 

  • expo-module.config.json에서 먼저 네이티브 모듈 파일을 등록한다.
  • src 폴더 밑에 타입스크립트 모듈파일을 만들고 네이티브 모듈을 name을 통해 읽어오도록한다
  • 네이티브 모듈을 작성한다
  • index.ts에 모듈을 노출시킨다.

 

expo-module.config.json은 아래와 같은 형태로 생겼다.

 

{
  "platforms": ["apple", "android", "web"],
  "apple": {
    "modules": ["MyModule", "TestModule"]
  },
  "android": {
    "modules": ["expo.modules.dbbeats.MyModule", "expo.modules.dbbeats.TestModule"]
  }
}
반응형

댓글