네이티브 모듈 생성하기

Tags

RN프로젝트에서 안드로이드 프로젝트 열기

RN 프로젝트를 만들면 ios, android 폴더가 각각 있다.
거기서 android 폴더를 Android Studio로 열면 된다.
notion image
🔥
android code는 android studio로 작성하는 것을 추천한다. syntax error나 auto complete 등 IDE의 장점을 누리자

네이티브 모듈 생성하기

모듈 클래스 생성

notion image
notion image
우선 Project 뷰로 폴더구조 보는 방식을 변경한다.
 
notion image
 
notion image
클래스 생성
여기서 자바로 작성할 건지, 코틀린으로 작성할 건지 정하면 되는데,
이번엔 Kotlin으로 진행한다.
생성 경로 : android/app/src/main/java/com/your-app-name/
 

모듈 내용 작성

package com.calendar class CalendarModule { }
갓 생성하면 위의 내용만 작성되어 있다.
 
package com.your-apps-package-name; // replace your-apps-package-name with your app’s package name import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod class CalendarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {...}
위의 코드들을 추가해준다.
맨 위의 package 명은 클래스 생성할 때 알아서 알맞게 채워지므로, 패키지 명을 바꿀 게 아니라면 그대로 두면 되고 나머지만 작성해주면 된다.
 
CalendarModule 모듈에게 ReactContextBaseJavaModule를 extends 시켰다.
React-Native용 모듈로 작성하려면 ReactContextBaseJavaModule를 상속하고, 요구되는 기능들을 작성해줘야 한다.
💡
RN에서 Native Module로 인식되는 데에는 다음의 두 가지로도 충분하다. - BaseJavaModule 을 상속하거나, - NativeModule 인터페이스를 구현한다. 하지만 ReactContextBaseJavaModule 를 상속하는 것을 더 추천하며, 그 이유는 다음과 같다. - ReactApplicationContext(RAC)에 접근할 수 있다. - 추후에 type safe 처리 시에도 편리하다. 향후 릴리스에 제공될 네이티브 모듈 유형 안전성을 위해 React Native는 각 네이티브 모듈의 JavaScript의 spec을 살펴보고 ReactContextBaseJavaModule을 확장하는 추상 기본 클래스를 생성한다.

모듈 이름 지정하기

getName() 메소드를 구현해서 모듈 이름을 지정한다.
이는 ReactContextBaseJavaModule 의 필수 구현 항목이다.
 
class CalendarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { override fun getName(): String { return "CalendarModule"; } }
문자열을 반환하는 함수로 작성하면 되는데, 문자열을 바로 대입해줘도 된다.
 
const { CalendarModule } = ReactNative.NativeModules;
그러면 JavaScript에서 지정한 이름으로 현재 네이티브 모듈에 접근할 수 있다.
 

Native Method를 JS로 내보내기

메소드에 @ReactMethod 어노테이션을 선언해주면 된다.
@ReactMethod fun createCalendarEvent(name: String, location: String) {}
 

Synchronous Methods

@ReactMethod(isBlockingSynchronousMethod = true)
위 옵션으로 synchronous메소드로 만들 수도 있다.
그런데 이 방식은 추천하지 않는다.
  • 성능 패널티가 굉장히 크다.
  • 네이티브 모듈에 스레드 관련 버그들을 야기할 수 있다.
  • 구글 크롬 디버거로 디버깅을 할 수 없어진다.
    • synchronous methods은 JS VM과 앱 메모리를 공유해야 하는데 그럴 수 없기 때문
    • 크롬 브라우저에 내장된 JS VM안에서 React-native를 돌리고 모바일 디바이스와는 웹소켓으로 통신하는 구조다.

모듈 등록하기 (안드로이드에서만 필요)

네이티브 모듈을 작성하고 나면, React Native에 등록해야 하는데,
  1. 네이티브 모듈을 ReactPackage에 추가하고
  1. ReactPackageReact Native에 등록한다.
그러면 초기화 하는 과정에서 모든 패키지를 도는데, ReactPackage라면 네이티브 모듈을 React Native에 등록한다.
 
React Native는 등록할 네이티브 모듈 목록을 가져오기 위해 ReactPackagecreateNativeModules()라는 메소드를 호출한다.
안드로이드의 경우 모듈이 인스턴스화 되지 않고, createNativeModules에서 반환되지 않으면 Javascript에서 사용할 수 없다.
 
  1. 패키지를 생성하고
  1. 패키지에 내가 작성한 네이티브 모듈을 등록하고
  1. 패키지를 React Native에 등록해야 한다.

패키지 생성 및 패키지에 모듈 추가

네이티브 모듈을 ReactPackage에 추가하려면, 먼저 다음의 경로에 Java/Kotlin 클래스를 만들고 ReactPackageimplements 한다.
패키지 생성 경로 : android/app/src/main/java/com/your-app-name/
💡
클래스 파일 생성은 모듈 생성 시와 완전히 동일하다.
notion image
 
다음의 내용으로 클래스를 채운다.
package com.your-app-name // replace your-app-name with your app’s name 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 MyPackage : ReactPackage { override fun createViewManagers( reactContext: ReactApplicationContext ): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf() override fun createNativeModules( reactContext: ReactApplicationContext ): MutableList<NativeModule> = listOf(CalendarModule(reactContext)).toMutableList() }
🔥
우리가 모듈을 ReactContextBaseJavaModule을 상속했기 때문에 reactContext를 넘겨줄 수 있다!
이 파일에서 내가 만든 네이티브 모듈(CalendarModule)을 imports 한다.
그리고 CalendarModule을 instantiate(인스턴스화) 해서 createNativeModules() 안에 담는다.
등록할 네이티브 모듈들의 리스트를 반환하는데, 만약 등록하고 싶은 모듈이 여러개라면 여기에 추가해주면 된다.
(배열이니까 배열에 추가로 담으라는 의미)

패키지를 ReactNative에 등록

MainApplication 파일로 가서 ReactNativeHost 내에 패키지 리스트를 반환하는 getPackages() 메소드가 방금까지 만들었던 패키지도 반환할 수 있도록 추가한다.
notion image

java ↔ kotlin 이슈 (cannot find symbol)

notion image
  • kotlin으로 모듈과 패키지를 생성하고,
  • java로 작성된 MainApplication.java 파일에서 kotlin으로 작성한 패키지를 사용하니 “error: cannot find symbol” 에러가 떴다.
분명히 IDE 상에서는 자동완성도 너무 잘 되고, 에러 하나도 없는데, 빌드를 하니까 에러가 뜸.
🔥
https://medium.com/@pasinduyeshann/native-module-for-react-native-using-kotlin-1f169372b6d3 이 글을 참고하자!!! 꼭 꼭 꼭 꼭! 코틀린→자바 변환 관련 설정을 해줘야 컴파일 때도 잘 동작한다.