React에서 React Native로

MUNGI JO·2024년 8월 12일

React와 React Native

목록 보기
4/6

서론

Android 개인 프로젝트가 끝난 후 기존에 회사에서 진행하던 react프로젝트를 react native로 porting하는 작업을 참여하게 되었다. 하지만 react를 접해본적 없던 나는 react를 배우기도 전 react로 작성된 코드를 react native로 migration 해야 하는 작업을 시작해야 한다. 그래서 react에 대한 개념과 react navtive에 대한 개념들을 아주 간단하게 정리하고 넘어가고자 한다.

react란

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으로 적용되는 과정을 보자

- 추가, DOM이란?

  • DOM(Document Object Model)은 HTML 문서의 구조를 트리 형태로 표현한 모델이다. 이 트리는 문서의 각 요소(예: <div>, <p>, <a> 등)를 객체로 표현하며, 각 객체는 JavaScript를 통해 동적으로 조작할 수 있다.
  • DOM은 브라우저에 의해 생성되며, HTML 문서의 요소들이 어떻게 구조화되어 있고, 서로 어떤 관계를 가지고 있는지를 나타낸다.

1. 브라우저와 DOM

  • 브라우저는 HTML 문서를 읽어 들여 DOM 트리를 생성한다. 이 DOM 트리는 메모리에 로드되며, 브라우저가 문서를 화면에 렌더링하는 데 사용된다.
  • JavaScript 코드는 이 DOM 트리에 접근하여 요소를 추가, 제거, 수정할 수 있다. 브라우저는 JavaScript를 실행하고, 이 JavaScript가 DOM을 조작할 수 있게 해준다.

2. 브라우저에서 DOM 조작

  • 브라우저는 JavaScript 엔진을 통해 JavaScript 코드를 실행한다. 예를 들어, 브라우저의 JavaScript 엔진(Chrome의 V8, Firefox의 SpiderMonkey 등)은 document.getElementById()와 같은 JavaScript 함수를 실행하여 DOM 요소에 접근하고 이를 변경할 수 있다.
  • JavaScript 코드가 DOM을 조작하면, 브라우저는 해당 변경 사항을 즉시 반영하여 사용자에게 보여주는 웹 페이지를 업데이트한다. 예를 들어, HTML 요소의 텍스트를 변경하거나 새로운 요소를 추가하는 등의 작업이 가능하다.

3. React.js와 DOM 조작

  • React.js는 Virtual DOM이라는 개념을 사용하여 효율적으로 DOM을 조작한다. React의 컴포넌트가 상태를 변경하면, React는 새로운 Virtual DOM을 생성하고 이전 Virtual DOM과 비교(diff)하여 실제 DOM에 필요한 최소한의 업데이트만 수행한다.
  • 이 과정에서 실제 DOM 조작은 브라우저에서 이루어지며, 브라우저의 JavaScript 엔진이 이 작업을 처리한다.

react native

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로 작성된 컴포넌트는 보통 Create React App(CRA)으로 설정된 Babel과 Webpack을 통해 표준 JavaScript로 변환되며, 이 변환된 JavaScript 코드는 React 라이브러리를 통해 브라우저의 DOM에 반영된다.
  • React Native는 작성된 컴포넌트를 네이티브 코드 호출로 변환하여 iOS와 Android에 전달하는 역할을 한다. 즉, 일종의 인터페이스로서 운영체제(iOS, Android)와 컴포넌트 사이에서 동작한다. 따라서 React Native로 코드를 작성하면, iOS에서는 Objective-C/Swift 코드로, Android에서는 Java/Kotlin 코드로 변환되어 실행된다.

즉, 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를 사용할 수 없다.)

  1. 프로젝트에서 terminal을 열고 npx expo start를 입력하면 아래처럼 qr 코드 및 키보드 입력으로 android나 web에서 열 수 있는데 실제 휴대폰에서 보려면 expo앱을 play store에서 다운하고 expo에 회원가입한 계정으로 로그인 후 qr코드를 스캔하거나 링크를 입력하면 된다. w를 눌러서 웹에서 볼 수도 있다.

추가

다만 이렇게 설정하게 될 경우 기본적으로 typescript방식으로 설치가 된다. 따라서 template blank를 사용해서 기본적으로 js를 설치하여 사용할 수 있도록 설치하는 것이 필요하다.

🥧우선 npm install expo 를 통해 expo 를 설치하고 위 코드를 통해 expo 패키지를 생성한다.

expo 앱 생성

npx create-expo-app RoundNote --template blank

필요 패키지 install

npx expo install react-dom react-native-web @expo/metro-runtime

expo 앱 실행

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>
  );
}

AVD 설정

해당 사이트를 참고하였다. 다만 여기서 명령어를 인식하지 못해서 아래와 같이 입력하여 사용하였다.
%ANDROID_HOME%\emulator\emulator -avd expo

참고 자료

모두의 연구소
nomad coder

profile
안녕하세요. 개발에 이제 막 뛰어든 신입 개발자 입니다.

0개의 댓글