Android 개인 프로젝트가 끝난 후 기존에 회사에서 진행하던 react프로젝트를 react native로 porting하는 작업을 참여하게 되었다. 하지만 react를 접해본적 없던 나는 react를 배우기도 전 react로 작성된 코드를 react native로 migration 해야 하는 작업을 시작해야 한다. 그래서 react에 대한 개념과 react navtive에 대한 개념들을 아주 간단하게 정리하고 넘어가고자 한다.
react는 최적화된 개발 인터페이스 및 코딩 언어를 지원하며 다양한 플랫폼에서 쉽게 재사용 될 수 있기 때문에 한 번 익혀두면 계속해서 사용할 수 있는 효율적인 workflow다. 또한 그 역사가 오래된 만큼 커뮤니티 또한 방대하기 때문에 다양한 웹 솔루션을 찾아보고 알맞은 솔루션을 적용하는 과정이 쉽다.
가장 많이 사용되는 용도로는 별도의 컴포넌트(Component) 기반 아키텍처 즉, 개발자는 UI의 각 부분을 독립적인 컴포넌트로 나누어 관리하고, 이러한 컴포넌트를 재사용할 수 있다. 따라서 react 기반의 코드와 호환 가능한 다른 프로젝트에 고유한 object 추가가 가능하다.
따라서 일반적인 더 큰 계층 구조가 구축되지만 각 컴포넌트에는 별도의 전용 내부 로직과 렌더링 원칙이 존재하기 때문에 확장성이 뛰어나고 개발 지원 및 최적화가 매우 간편해 진다고 한다.
또한 Virtual DOM(Document Object Model - HTML 요소를 Java Script Object 처럼 조작할 수 있는 Model)을 사용해서 메모리에 보관하는데 중요한건 react는 모든 view 변경사항을 virtual DOM에 즉시 반영하기 때문에 매우 빠른 속도의 렌더링을 지원한다는 것이다. Android 에서 사용했던 DiffUtil처럼 특화된 diff 알고리즘이 존재하게 되는데 이전에 저장된 virtual DOM 의 상태와 현재 virtual DOM의 상태를 비교하여 새로운 변경사항을 반영할 때 가장 효율적인 방법을 계산하게 된다. (자세한 작동 원리는 다음에 알아본다.) 따라서 빠른 In/Out시간과 성능 향상이 이루어진다.
추가
단방향 데이터 흐름을 처리하는 Flux 기반 소프트웨어 아키텍처를 통해 Central dispatcher는 생성된 action을 관리하고 store를 변경하는 데 사용된다. 이후 store변경에 따라 view를 업데이트 하게 되는 이때 모든 데이터는 중복되지 않는 형태로 store에 유지되며 모델과 멀지 않은 상태로 동기화 유지가 된다.
※ flux는 편리한 UI design workflow를 위해 frontend에서 사용되는 architecture pattern일 뿐 완전한 library로 사용할 수는 없다.
flux 구현을 더욱 편리하게 할 수 있는 redux는 모든 앱 데이터를 처리할 수 있는 단일 store 객체를 제공하며 기본 데이터 관리 조작을 간편하고 편리하게 만들어주는데 view가 연관 데이터와 지속적으로 동기화 되는 동안 redux는 store의 변경을 감지하여 rendering을 실행하게 한다.
이제 위와 같은 내용을 기반으로 react.js가 Browser DOM으로 적용되는 과정을 보자
(예: <div>, <p>, <a> 등)를 객체로 표현하며, 각 객체는 JavaScript를 통해 동적으로 조작할 수 있다.react native는 Hybrid 및 Native한 앱 개발 프로젝트를 시작할 때 사용하게 되는 framework로 단일 코드베이스로 하나의 앱을 빌드하여 비용을 절감, 다양한 운영 환경, 다양한 솔루션에 맞춤형 결과를 Hybrid형태로 제공할 수 있다. 웹 개발에 react를 사용하게 되면 javascript code에서 명시적 HTML 구문을 직접 활용할 수 있는데 browser는 사용자 interface를 표시하기 위해 HTML 텍스트를 디코딩 한다. 이를 DOM tree로 구축하고 javascript로 조작하여 대화형 UI를 만든다.
즉, react native로 어떤 component(예를 들어 Button)를 만들면 Android와 iOS에서 각각 그 button에 대한 메세지를 받아서 해당 button을 생성하게 된다.

react native의 작동 방식 - 실제로 구현하는 것은 javascript 부분이다.
예를 들어 어떤 event를 기다리고 있을때
1. 사용자가 이벤트(ex 버튼을 클릭)를 발생 시킨다. - listener
2. native(Android/iOS)에서 event가 기록된다.(event에 관한 모든 정보) - listener
3. react native는 그 정보를 가지고 JSON Message를 생성한다. - bridge
4. Javascript에서 해당 메세지를 받고 해당 메세지에 대한 코드를 수행한다. (전송 및 데이터 수신, 화면 교체 등등)
5. 변경된 data 및 ui 업데이트를 위해 Native methods 호출이나 UI update를 위한 명령을 생성한다.
6. native 코드에 전달할 명령을 직렬화 하고 batch로 묶여 전달한다.
7. 역직렬화를 통해 명령들을 처리한다.
8. ui를 업데이트 한다.
출처 - nomad coder 왕초보를 위한 React Native 101
이렇게 react native로 작성되는 APP의 전체적인 그림이다.

위에서도 말했듯이 여기서 실제로 개발자가 작성하는 코드는 JavaScript와 Markup/Styling이다. 다른 infra는 java, object-c/swift 에 있을것이다.
즉, React는 브라우저를 통해 DOM 트리에 컴포넌트를 구축하게 되고, React Native는 브리지(Bridge)를 통해 Android/iOS에서 네이티브 코드로 변환된 컴포넌트를 구축하게 된다.
react와 react native의 동작 과정
Android Studio와 vscode중에서 이번엔 일단 간단한 프로젝트 몇개만 진행 할 생각으로 vscode에 expo를 사용하여 진행하기로 하였다.
기본적으로 프로젝트를 진행할 폴더를 먼저 만든다. 나는 D: react라는 폴더를 만들어 진행하였다.
1. vscode와 node js를 다운, 설치한다.
2. expo site에 접속, project를 생성한다. (이때 생성되는 창을 닫지 않는다.)
위처럼 생성되어 있을텐데 project를 생성하며 진행하므로 create a new project의 절차대로 진행하였다.
3. terminal을 관리자 권한으로 실행하여 해당 폴더로 이동하고 (D의 경우 D:를 하면 C에서 바로 이동이 가능하다. 물론 C:도 가능) project를 진행할 위치로 이동해서 create후 npm install까지 해주면 된다. (npm은 Node Package Manager의 약자로, Node.js 패키지 생태계에서 가장 널리 사용되는 패키지 관리자다.)

그러면 기본적인 구성이 끝나고 vscode로 해당 프로젝트를 열면 아래처럼 프로젝트 구성이 되어 있을텐데 app.js는 없고 app.json과 app폴더만 존재하는데 이전과 달리 app.js대신에 app/폴더 내의 파일들이 application의 진입점 역할을 한다. (tsx는 react component와 type script를 같이 사용할때 사용하는 확장자이다. 따라서 ts에서는 jsx를 사용할 수 없다.)


다만 이렇게 설정하게 될 경우 기본적으로 typescript방식으로 설치가 된다. 따라서 template blank를 사용해서 기본적으로 js를 설치하여 사용할 수 있도록 설치하는 것이 필요하다.
🥧우선 npm install expo 를 통해 expo 를 설치하고 위 코드를 통해 expo 패키지를 생성한다.
npx create-expo-app RoundNote --template blank
npx expo install react-dom react-native-web @expo/metro-runtime
npx expo start
npm install @react-navigation/native @react-navigation/native-stack
npx expo install react-native-screens react-native-safe-area-context
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import MainScreen from "./screens/MainScreen";
const Stack = createNativeStackNavigator();
const NavigateStack = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="MainScreen"
component={MainScreen}
options={{
title: "Main Screen",
headerShown: false,
}}
/>
</Stack.Navigator>
);
};
export default function App() {
return (
<NavigationContainer>
<NavigateStack />
</NavigationContainer>
);
}
해당 사이트를 참고하였다. 다만 여기서 명령어를 인식하지 못해서 아래와 같이 입력하여 사용하였다.
%ANDROID_HOME%\emulator\emulator -avd expo