React-Native

로토

웹 개발자가 시도해본

스마트스터디

오늘 공유할 내용

  • what is react-native?
  • 써본 후기
  • 그외 특징들

쉽게 말해서 react로

모바일 앱 개발하는 것

앱 개발에 숟가락 얹을 수 있겠는데..?

비슷한 기술

개발자의 욕심은 끝이 없고

같은 코딩을 반복한다

경험담 - instagram

경험담 - ubereats

  • React/Flux SPA로 레스토랑 대시보드가 구현되어 있었음
    • WebView로 래핑되어 제공
    • 사운드 알람 등의 기능이 웹 기반 구현에서 좋지 않은 사용성
    • 영수증 인쇄 등의 기능은 웹에서 구현하기 힘들었음
  • 로직을 JS 코드에 집중
    • Javascript와 Objective C, Java 간의 컨텍스트 전환 감소
    • 플랫폼 고유 코드 감소로 인한 이식성 향상
    • 버그 범위 축소
  • JS Bundle만 재배포하여 앱 재배포 없이 업데이트 가능해짐

경험담 - airbnb

결국은 code share

Architecture

Architecture

Bridge

Native Code

JS Runtime Environment

React Native Code

iOS or Android OS

Architecture

React Native Build

node.js 로 컴파일 및 
js bundle publish

Node Server

127.0.0.1:8001/index.platform.bundle.js

JS Runtime

iOS or Android Native Project

Native Project의 JS Runtime에서는

publish된 JS Bundle을 참조

Hello! React Native!

Hello! React Native!

npm install -g react-native

react-native init HelloRN

cd HelloRN

react-native run-ios // ios 
react-native run-android // android

mac + iOS는 쉽게 시작 할 수 있음

mac + Android는 Android SDK setting 필요

windows 에선 Android 개발만 가능

windows 10 mobile도 지원

Hello! React Native!

Live Reload

  • React Web 개발환경에서 아주 편하게 쓰던 그것
  • JS에 변경점이 있다면 Bundle을 새로 생성하고
    해당 Bundle을 자동 reload 후 앱을 다시 렌더링
  • 수동 리로드도 가능
    • Android - R 두번(한영 상태 주의)
    • iOS - command + R

Hot Reloading

  • React Web 개발환경에서 아주 편하게 쓰던 그것(2)
  • JS에 변경점이 있다면 변경된 부분만 화면을 다시 그림
  • 리로드 일어나지 않음

공통점

다시 컴파일 할 필요가 없다!

UI를 빠르게 개발할 수 있다!

Platform

Supported Platforms

Detect Platform

import { Platform, View, Text } from 'react-native';

const Panel = () => (
  <View style={{paddingTop: Platform.OS === 'ios' ? 20 : 0}}>
    <Text>SmartStudy!</Text>
  </View>
);

Platform module의 OS 파라메터 이용

Detect Platform

// app/Hello/index.ios.js
const Hello = () => (
  <View style={{paddingTop:20}}>
    <Text>안녕?iOS!!</Text>
  </View>
);

export default Hello;

// app/Hello/index.android.js
const Hello = () => (
  <View>
    <Text>안녕?안드로이드!!</Text>
  </View>
);

export default Hello;

index.{platform}.js

// platform에 따라 index.js가 로딩됨
import Hello from './app/Hello'; 

const App = () => (
  <View>
   <Hello />
  </View>
);

export App;

App.js

Native Module

Android

  • ReactContextBaseJavaModule를 상속 
  • getName() 메소드를 override
  • 제공할 메소드에 @ReactMethod 애너테이션 붙임
public class ToastModule extends ReactContextBaseJavaModule{
    private static final String DURATION_SHORT_KEY = "SHORT";
    private static final String DURATION_LONG_KEY = "LONG";

    public ToastModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "ToastExample";
    }

    @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();
        constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
        constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
        return constants;
    }

    @ReactMethod
    public void show(String message, int duration) {
        Toast.makeText(getReactApplicationContext(), "NATIVE MESSAGE : " + message, duration).show();
    }
}

Android

  • ReactPackage interface를 implements
  • createNativeModules에 RN으로 제공할 modules을 add
public class ToastModulePackage implements ReactPackage{
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();

        modules.add(new ToastModule(reactContext));

        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

Android

  • MainApplication.java 의 getPackages 의 리턴 값으로 앞에서 만든 ReactPackage 구현체를 추가
        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new ToastModulePackage()
            );
        }

Android

  • NativeModules에서 꺼내서 쓰면 됨
import React from 'react';
import { View, Text, Button, NativeModules } from 'react-native';

const { ToastExample } = NativeModules;

const Hello = () => (
  <View>
    <Text>안녕?안드로이드!!</Text>
    <Button text="누질러봐" onPress={() => ToastExample.show('눌렀니?', ToastExample.LONG)} />
  </View>
);

export default Hello;

My Experience

저의 앱 개발 관련 지식

  • Java & Gradle 할 줄은 압니다.
  • 하이브리드 웹앱은 만들어봤습니다.
    (using ionic framework, cordova)
  • 안드로이드는 맛만 살짝 봤습니다.
    • 2.1 기준
    • 사실 게임 만들어본 거라 별 도움 안 됩니다.
  • Objective C와 XCode는 전혀 모릅니다.

Toy Project

  • Instagram app 카피 시도
    • react-native 에서의 스타일링을 익혀보기 위함
    • 전형적인 CRUD + 네이티브의 기능을 체험
      • Timeline
      • Story + Image upload
      • Camera
  • Back-End는 firebase 사용
    • Auth
    • Storage
    • Database

고민의 시작 - navigation

react-navigation

  • https://reactnavigation.org/
  • 공식 문서에서 언급이 되어있어서 이 모듈을 사용
  • 크게 StackNavigation, TabNavigation, DrawingNavigation
  • 다양한 Navigation을 조합해서 Screen간 인터랙션을 구현

styled-components

Screens

  • Login Screen
  • Create Account Screen
  • Timeline Screen
  • SelectMedia Screen
  • Create Story Screen
  • Profile Screen

Login / Create Account Screen

Timeline Screen

  • FlatList  컴포넌트 사용
    • ScrollView 확장
  • pull to refresh 구현 쉬움
  • 무한 스크롤 구현 쉬움
  • code link

Select Media / Create Story Screen

Profile Screen

실제로 해보니까...

  • UI 관련 작업은 상당히 빠르고 쾌적하게 작업 가능
    • 다시 컴파일 할 필요가 없이 빠르게 화면에 반영​
    • css flex 지식이 있다면
    • 웹이랑 유사한 느낌
  • 그러나 실제 시간을 많이 쓰는 부분은 Native 관련 오류
    • 네이티브 코드 볼 줄 알아야 함
    • 안드로이드는 문제가 생겼을 때 쉽게쉽게
      해결 할 수 있었으나 iOS는 해결이 잘 안 되어서 포기(cocoapods 문제로 예상)

 Tools

Code Push

Code Push Setup

// code push cli install
npm install -g code-push-cli

// register
// 브라우저가 열리며 계정을 연동하는 과정을 거침
// 계정 연동 후 발급된 토큰을 console에 붙여넣음
code-push register

// 앱 등록
// code-push app add <ProjectName> <Platform> react-native
code-push app add HelloRN android react-native

// 앱에 code-push 모듈 설치
npm install --save react-native-code-push@latest 

react-native link react-native-code-push

Code Push

code-push release-react HelloRN android

Expo

  • js bundle만 전송 받아서 렌더링 하는 앱
  • 네이티브 영역은 숨겨져 있고, JS 코드만 드러나있음
    • 네이티브 연동이 필요한 모듈은 연동하기 어려움
    • 일부 네이티브 기능은 expo에서 자체적으로 지원
    • 네이티브 기능이 필요 없거나 expo로 커버할 수 있다면 좋은 선택

create-react-native-app

  • expo 기반
  • 플랫폼 별 네이티브 코드들이 숨겨져 있음
    • 네이티브 기능이 크게 중요하지 않다면 좋은 선택

결론

이젠 해볼만 한 것 같습니다.

Q&A

감사합니다.