๐ ๋ค์ดํฐ๋ธ ๋ชจ๋์ด๋
React Native์์ ์ง์ํ์ง ์๋,
Android,IOS ๋ง์ ์ ์ฉ ๊ธฐ๋ฅ์ ๊ฐ์ง ์ฝ๋
๐ Android ๋ค์ดํฐ๋ธ ๋ชจ๋๋ง๋ค๊ธฐ ( Java )
Android Studio > ReactNative ํ๋ก์ ํธ / android ํด๋ ์ด๊ธฐ
๋ชจ๋ ํด๋์ค ๋ง๋ค๊ธฐ
// app/java/com.nativemoduleworkshop/ToastModule.java
package com.nativemoduleworkshop;
import android.widget.Toast;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.HashMap;
import java.util.Map;
// ReactNative Java ๋ชจ๋ ์์
public class ToastModule extends ReactContextBaseJavaModule {
// ์์ฑ์๋ก ์ด๊ธฐ๊ฐ ์ค์ - ํญ์ ํด์ฃผ์ด์ผํจ
ToastModule(ReactApplicationContext context) {
super(context);
}
/* getName ๋ฉ์๋
- ๋ค์ดํฐ๋ธ ๋ชจ๋ ์ด๋ฆ ์ ํ๊ธฐ
- ์ดํ์ js ์ฝ๋์์ ๋ถ๋ฌ์ฌ ๋ชจ๋ ์ด๋ฆ
import { NativeModules } from 'react-native';
const { ToastModule } = NativeModules;
*/
@Override
public String getName(){
return "ToastModule";
}
/*
@ReactMethod ๋ฅผ ๋ถ์ฌ์ฃผ๋ฉด,
์ดํ js ์ฝ๋์์ ํธ์ถ ํ ์ ์๋ค.
@๋ฅผ ๋ถ์ฌ์ฃผ๋ ๋ฌธ๋ฒ - ๋ฐ์ฝ๋ ์ดํฐ ๋ฌธ๋ฒ
message๋ฅผ ๋ฐ์, ํ๋ฉด์ ์๋ฆผ์ ๋์์ฃผ๊ณ
duration์ ๋ฐ์, ํ๋ฉด์ ๋ณด์ฌ์ค ์๊ฐ์ ์ ํ๋ค ( 0 ์งง์, 1 ๊น )
ToastModule.show(message, duration);
*/
@ReactMethod
public void show(String message, int duration) {
// ์์ฑ์๋ก ์ค์ ํ, context ๊ฐ์ ธ์ค๊ธฐ
ReactApplicationContext context = getReactApplicationContext();
//
Toast toast = Toast.makeText(context, message, duration);
toast.show();
}
/*
java์์ ์ ์ธํ ์์๋ฅผ,
js์์ ์ฌ์ฉํ ์ ์๋๋ก ๋ด๋ณด๋ด๊ธฐ
ToastModule.SHORT
*/
@Override
public Map<String, Object> getConstants(){
final Map<String, Object> constants = new HashMap<>();
constants.put("SHORT", Toast.LENGTH_SHORT);
constants.put("LONG", Toast.LENGTH_LONG);
return constants;
}
}
ReactNative์ ์ฐ๊ฒฐํ ํจํค์ง ๋ง๋ค๊ธฐ
// app/java/com.nativemoduleworkshop/ToastPackage.java
package com.nativemoduleworkshop;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
ReactNative์ ๋ฑ๋กํ ํจํค์ง๋ฅผ ๋ง๋ค๊ธฐ
*/
public class ToastPackage implements ReactPackage {
/*
ArrayList๋ฅผ ๋ง๋ค๊ณ ,
๊ทธ ์์ ToastModule์ ๋ฑ๋กํด ๋ฐํ
*/
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new ToastModule(reactContext));
return modules;
}
/*
๋ค์ดํฐ๋ธ UI ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด์ ๋ฑ๋ก
์ง๊ธ์ ํ์์์ผ๋ฏ๋ก, ๋น ์ปดํฌ๋ํธ ๋ฐํ
*/
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext){
return Collections.emptyList();
}
}
๋ง๋ ํจํค์ง ๋ฑ๋กํ๊ธฐ
// 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());
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
return packages;
}
@Override
protected String getJSMainModuleName() { ... }
};
...
}
์ฐ๊ฒฐํ ํจํค์ง ์ฌ์ฉํ๊ธฐ
// ํ๋ก์ ํธ/App.js
import { NativeModules } from 'react-native'
const App = () => {
const { ToastModule } = NativeModules;
ToastModule.show('Hello Module!', ToastModule.SHORT);
return ...
}
๐ ์ฝํ๋ฆฐ์ผ๋ก ๋ง๋ค๊ธฐ
React Native ํ๋ก์ ํธ ์ฝํ๋ฆฐ์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ
ํ๋ก์ ํธ / android / build.gradle ํ์ผ ์์
...
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 ํ์ผ ์์
...
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
...
}
// ๋งจ ๋ง์ง๋ง ์ค ์๋์ ์์ฑ
apply plugin: 'kotlin-android'
๋ชจ๋ ๋ง๋ค๊ธฐ
// ํ๋ก์ ํธ/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){
}
}
ํจํค์ง ๋ง๋ค๊ธฐ
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์ ๋์ผํ ๋ฐฉ๋ฒ์ผ๋ก ํจํค์ง ๋ฑ๋กํ๊ธฐ
// 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
ํ์ผ๋ช : RCTAlertModule.h
์์น (๊ฒฝ๋ก) : ios / ํ๋ก์ ํธ ( AppDelegate.h ํ์ผ์ด ์๋ ์์น )
ํ๊ฒ (Targets) : ํ๋ก์ ํธ, ํ๋ก์ ํธTest ๋๋ค ์ ํ
Header File ์์ฑ, ์ ์ฅ
// 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
ํ์ผ๋ช : RCTAlertModule
์์น (๊ฒฝ๋ก) : ios / ํ๋ก์ ํธ ( AppDelegate.h ํ์ผ์ด ์๋ ์์น )
ํ๊ฒ (Targets) : ํ๋ก์ ํธ, ํ๋ก์ ํธTest ๋๋ค ์ ํ
Objective.c File ์์ฑ, ์ ์ฅ
,/// 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
๋ชจ๋ ์ฌ์ฉํ๊ธฐ
// ํ๋ก์ ํธ/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
ํ์ผ๋ช : BrightnessModule.swift
์์น (๊ฒฝ๋ก) : ios / ํ๋ก์ ํธ ( AppDelegate.h ํ์ผ์ด ์๋ ์์น )
ํ๊ฒ (Targets) : ํ๋ก์ ํธ, ํ๋ก์ ํธTest ๋๋ค ์ ํ
Create Bridging Header ์์ฑ ( ๋ฒํผ ํด๋ฆญ )
// NativeModuleWorkshop-Bridging-Header.h
#import "React/RCTBridgeModule.h"
Swift File ์์ฑ, ์ ์ฅ
dfsdf
๋ฐ์ํ