[React Native] Native Module ์์ฑ
ํ๊ทธ: development · React-Native · android · ios · Objective-C · Swift · kotlin · IOS ๋ค์ดํฐ๋ธ ๋ชจ๋ · Android ๋ค์ดํฐ๋ธ ๋ชจ๋ · reactnative
- ๋ค์ดํฐ๋ธ ๋ชจ๋์ด๋
๋ค์ดํฐ๋ธ ๋ชจ๋์ด๋
React Native์์ ์ง์ํ์ง ์๋ Android,IOS ๋ง์ ์ ์ฉ ๊ธฐ๋ฅ์ ๊ฐ์ง ์ฝ๋
๐ Android ๋ค์ดํฐ๋ธ ๋ชจ๋๋ง๋ค๊ธฐ ( Java )
Android Studio > ReactNative ํ๋ก์ ํธ / android ํด๋ ์ด๊ธฐ
1. ๋ชจ๋ ํด๋์ค ๋ง๋ค๊ธฐ
2. ReactNative์ ์ฐ๊ฒฐํ ํจํค์ง ๋ง๋ค๊ธฐ
3. ๋ง๋ ํจํค์ง ๋ฑ๋กํ๊ธฐ
Copy
// app/java/com.nativemoduleworkshop/pakagename.java
package com.pakagename.newarchitecture;
import android.app.Application;
import androidx.annotation.NonNull;
import com.facebook.react.PackageList;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
import com.facebook.react.bridge.JSIModulePackage;
import com.facebook.react.bridge.JSIModuleProvider;
import com.facebook.react.bridge.JSIModuleSpec;
import com.facebook.react.bridge.JSIModuleType;
import com.facebook.react.bridge.JavaScriptContextHolder;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.UIManager;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.react.fabric.CoreComponentsRegistry;
import com.facebook.react.fabric.EmptyReactNativeConfig;
import com.facebook.react.fabric.FabricJSIModuleProvider;
import com.facebook.react.fabric.ReactNativeConfig;
import com.facebook.react.uimanager.ViewManagerRegistry;
//ReactNative Java ๋ชจ๋ ์์
import com.pakagename.BuildConfig;
import com.pakagename.newarchitecture.components.MainComponentsRegistry;
import com.pakagename.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
import java.util.ArrayList;
import java.util.List;
// ReactNative์ ๋ฑ๋กํ ํจํค์ง๋ฅผ ๋ง๋ค๊ธฐ
/**
* A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
* TurboModule delegates and the Fabric Renderer.
*
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
* `newArchEnabled` property). Is ignored otherwise.
*/
public class MainApplicationReactNativeHost extends ReactNativeHost {
public MainApplicationReactNativeHost(Application application) {
super(application);
}
@Override
public boolean getUseDeveloperSupport() {
/*
ํจํค์ง๋ฅผ ๋ฐ์์ค๋ ๋ถ๋ถ
*/
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
// TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
// packages.add(new TurboReactPackage() { ... });
// If you have custom Fabric Components, their ViewManagers should also be loaded here
// inside a ReactPackage.
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@NonNull
@Override
protected ReactPackageTurboModuleManagerDelegate.Builder
getReactPackageTurboModuleManagerDelegateBuilder() {
// Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
// for the new architecture and to use TurboModules correctly.
return new MainApplicationTurboModuleManagerDelegate.Builder();
}
@Override
protected JSIModulePackage getJSIModulePackage() {
return new JSIModulePackage() {
@Override
public List<JSIModuleSpec> getJSIModules(
final ReactApplicationContext reactApplicationContext,
final JavaScriptContextHolder jsContext) {
final List<JSIModuleSpec> specs = new ArrayList<>();
// @ReactMethod ๋ฅผ ๋ถ์ฌ์ฃผ๋ฉด,
// ์ดํ js ์ฝ๋์์ ํธ์ถ ํ ์ ์๋ค.
// Here we provide a new JSIModuleSpec that will be responsible of providing the
// custom Fabric Components.
specs.add(
new JSIModuleSpec() {
@Override
public JSIModuleType getJSIModuleType() {
return JSIModuleType.UIManager;
}
@Override
public JSIModuleProvider<UIManager> getJSIModuleProvider() {
final ComponentFactory componentFactory = new ComponentFactory();
CoreComponentsRegistry.register(componentFactory);
// Here we register a Components Registry.
// The one that is generated with the template contains no components
// and just provides you the one from React Native core.
MainComponentsRegistry.register(componentFactory);
final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
ViewManagerRegistry viewManagerRegistry =
new ViewManagerRegistry(
reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
return new FabricJSIModuleProvider(
reactApplicationContext,
componentFactory,
ReactNativeConfig.DEFAULT_CONFIG,
viewManagerRegistry);
}
});
return specs;
}
};
}
}
์ฐ๊ฒฐํ ํจํค์ง ์ฌ์ฉํ๊ธฐ
Copy
// ํ๋ก์ ํธ/App.js
import { NativeModules } from 'react-native'
const App = () => {
const { ToastModule } = NativeModules;
ToastModule.show('Hello Module!', ToastModule.SHORT);
return ...
}
๐ ์ฝํ๋ฆฐ์ผ๋ก ๋ง๋ค๊ธฐ
React Native ํ๋ก์ ํธ ์ฝํ๋ฆฐ์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ
ํ๋ก์ ํธ / android / build.gradle ํ์ผ ์์
Copy
...
buildscript {
ext {
buildToolsVersion = "31.0.0"
minSdkVersion = 21
compileSdkVersion = 31
targetSdkVersion = 31
kotlinVersion = "1.5.0" // ์ฝํ๋ฆฐ ์ถ๊ฐ
...
}
...
dependencies {
classpath("com.android.tools.build:gradle:7.1.1")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("de.undercouch:gradle-download-task:5.0.1")
// ์ฝํ๋ฆฐ ์ถ๊ฐ
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
...
}
...
}
ํ๋ก์ ํธ / android / app / build.gradle ํ์ผ ์์
Copy
...
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
...
}
// ๋งจ ๋ง์ง๋ง ์ค ์๋์ ์์ฑ
apply plugin: 'kotlin-android'
๋ชจ๋ ๋ง๋ค๊ธฐ
Copy
// ํ๋ก์ ํธ/app/java/com.nativemoduleworkshop/BrightnessModule.kt
package com.nativemoduleworkshop
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
// ReactContext ๋ชจ๋ ์์ ๋ฐ๊ธฐ ( ์ฝํ๋ฆฐ ๋ฐฉ์ )
class BrightnessModule(reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
// ๋ชจ๋ ์ด๋ฆ ์ง์
override fun getName(): String {
return "BrightnessModule"
}
// ์์ ๋ด๋ณด๋ด๊ธฐ
override fun getConstants(): MutableMap<String, Any>? {
val constants = HashMap<String, Any>()
constants.put("SAMPLE_VALUE", "Hello World")
return constants;
}
// ๋ชจ๋์์ ์ฌ์ฉํ ๋ฉ์๋ ์ ์
@ReactMethod
fun getBrightness(){
}
@ReactMethod
fun setBrightness(brightness: Float){
}
}
ํจํค์ง ๋ง๋ค๊ธฐ
Copy
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
import java.util.Collections
import kotlin.collections.ArrayList
class BrightnessPackage : ReactPackage {
// ๋ชจ๋ ๋ฑ๋ก
override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule> {
val modules = ArrayList<NativeModule>()
modules.add(BrightnessModule(reactContext))
return modules;
}
// ๋ค์ดํฐ๋ธ UI ์ปดํฌ๋ํธ ๋ฑ๋ก
override fun createViewManagers(reactContext: ReactApplicationContext): MutableList<ViewManager<*, ReactShadowNode<*>>> {
return Collections.emptyList();
}
}
ํจํค์ง ๋ฑ๋กํ๊ธฐ
Java์ ๋์ผํ ๋ฐฉ๋ฒ์ผ๋ก ํจํค์ง ๋ฑ๋กํ๊ธฐ
Copy
// app/java/com.nativemoduleworkshop/MainApplication.java
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() { ... }
/*
ํจํค์ง๋ฅผ ๋ฐ์์ค๋ ๋ถ๋ถ
*/
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// toast ํจํค์ง ์ถ๊ฐ
packages.add(new ToastPackage());
// Brightness ํจํค์ง ์ถ๊ฐ
packages.add(new BrightnessPackage());
return packages;
}
@Override
protected String getJSMainModuleName() { ... }
};
...
}
๐ IOS ๋ค์ดํฐ๋ธ ๋ชจ๋๋ง๋ค๊ธฐ ( Objective.c )
XCode > ReactNative ํ๋ก์ ํธ / ios / ํ๋ก์ ํธ.xcworkspace ์ด๊ธฐ
Header File ์์ฑ
ํ๋ก์ ํธ / ํ๋ก์ ํธ ํด๋ ์ฐํด๋ฆญ > New FIle > Header File
Header File ์์ฑ, ์ ์ฅ
Copy
// RCTBridgeModule ํค๋ํ์ผ ๋ถ๋ฌ์ค๊ธฐ
#import <React/RCTBridgeModule.h>
// js ํธ์ถ ๊ฐ๋ฅํ ๋ฉ์๋ ๋ง๋ค๊ธฐ ์ํ ํค๋ํ์ผ
#import <UIKit/UIKit.h>
// RCTBridgeModule ๊ฐ์ฒด๋ฅผ, RCTAlertModule๋ผ๋ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ๊ฒ ๋ค.
@interface RCTAlertModule : NSObject <RCTBridgeModule>
@end
Objective.c File ์์ฑ
ํ๋ก์ ํธ / ํ๋ก์ ํธ ํด๋ ์ฐํด๋ฆญ > New FIle > Objective.c File
Objective.c File ์์ฑ, ์ ์ฅ
Copy
,/// RCTAlertModule.m
// ํค๋ํ์ผ ๊ฐ์ ธ์ค๊ธฐ
#import "RCTAlertModule.h"
// ํค๋ํ์ผ์์ ์์ฑํ RCTAlertModule ์์ ๋ฐ๊ธฐ
@implementation RCTAlertModule
/* ๋ค์ดํฐ๋ธ ๋ชจ๋ ๋ด๋ณด๋ด๋ ๋ฉ์๋
์ธ์๋ก ๋ชจ๋์ ์ด๋ฆ์ ์ง์ ํ๋ค.
์ธ์๋ฅผ ์ง์ ํ์ง ์์ผ๋ฉด, ํด๋์ค ์ด๋ฆ์์ RCT๋ฅผ ์ ์ธํ ๋ถ๋ถ์ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ๋ค (AlertModule)
์ธ์๋ฅผ ๋ฌธ์์ด ""๋ก ์ง์ ํ์ง ๋ง๊ฒ!
*/
RCT_EXPORT_MODULE();
// js์์ ํธ์ถ ๊ฐ๋ฅํ ๋ฉ์๋ ๋ง๋ค๊ธฐ
RCT_EXPORT_METHOD(alert:(NSString *)message)
{
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"My Alert"message:@"This is an alert." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@:"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
// UI๊ด๋ จ ์์
์ main์ค๋ ๋์์ ์คํ
dispatch_async(dispatch_get_main_queue(), ^{
[rootViewController presentViewController:alert animated:YES completion:nil]
})
}
// ์์ ๋ด๋ณด๋ด๊ธฐ
- (NSDictionary *)constantsToExport
{
return @{
@"STRING_VALUE": @"Hello World",
@"NUMBER_VALUE": @(15)
};
}
// ๋ชจ๋์ด js ์ฝ๋๋ฅผ ์คํํ๊ธฐ ์ ์, main์ค๋ ๋์์ ์์ ์ด๊ธฐํ ํ๊ธฐ
+ (BOOL)requiresMainQueueSetup
{
return YES;
}
@end
๋ชจ๋ ์ฌ์ฉํ๊ธฐ
Copy
// ํ๋ก์ ํธ/App.js
import { NativeModules } from 'react-native'
const App = () => {
const { AlertModule } = NativeModules;
AlertModule.alert('Hello Module!');
console.log(AlertModule.NUMBER_VALUE);
return ...
}
๐ Swift๋ก ๋ง๋ค๊ธฐ
XCode > ReactNative ํ๋ก์ ํธ / ios / ํ๋ก์ ํธ.xcworkspace ์ด๊ธฐ
Swift File ์์ฑ
ํ๋ก์ ํธ / ํ๋ก์ ํธ ํด๋ ์ฐํด๋ฆญ > New FIle > Swift File
Create Bridging Header ์์ฑ ( ๋ฒํผ ํด๋ฆญ )
Copy
// NativeModuleWorkshop-Bridging-Header.h
#import "React/RCTBridgeModule.h"
Swiftย File ์์ฑ, ์ ์ฅ
Copy
dfsdf