왜 React Native인가? : 리액트 네이티브부터 알아보자

동작 원리, 구조(레이어), 프로젝트 파일의 구조, 상태 관리, 데이터 흐름, 컴포넌트 구조, 동작 예시에 대해서 알아봅시다
Dec 13, 2024
왜 React Native인가? : 리액트 네이티브부터 알아보자
 

1️⃣ React Native의 기본 동작 원리

React Native는 JavaScript 런타임네이티브 브릿지를 통해 동작한다.
 

1-1) JavaScript 런타임

  • React Native는 모바일 앱의 비즈니스 로직과 UI 정의를 JavaScript에서 작성합니다.
  • 앱 로직이 JavaScript 런타임에서 실행되며, 이를 네이티브 코드(Android, iOS)에 전달합니다.
  • JavaScript 엔진 : JavaScriptCore에서 Hermes로
    • 초기 React Native는 JavaScriptCore를 기본 JavaScript 엔진으로 사용했습니다. 그러나 모바일 환경의 성능 제한으로 인해 Meta에서 Hermes 엔진을 개발했습니다.
    • Hermes는 React Native에 최적화된 오픈소스 JavaScript 엔진입니다. 많은 앱에서 Hermes를 사용하면 JavaScriptCore에 비해 시작 시간이 개선되고 메모리 사용량이 감소하며 앱 크기가 작아집니다. Hermes는 React Native에서 기본적으로 사용되며 이를 활성화하기 위한 추가 구성이 필요하지 않습니다.
 

1-2) 브릿지(Bridge)

  • React Native는 JavaScript 코드와 네이티브 코드 간의 통신을 담당하는 브릿지를 사용합니다.
  • JavaScript와 네이티브 간의 비동기 메시지 교환으로 동작합니다.
    • 예: JavaScript에서 Button 클릭 이벤트를 처리하고, 네이티브에서 이를 화면에 반영.
 

1-3) 네이티브 렌더링

notion image
  • React Native는 네이티브 컴포넌트를 사용하여 화면을 렌더링합니다. 이로 인해 네이티브 수준의 퍼포먼스를 유지할 수 있습니다.
 

궁금증💭 : 컴포넌트가 매핑될 때 왜 UIKit과 Android View 시스템을 사용❓

React Native의 컴포넌트는 UIKitAndroid View 시스템에 직접 매핑된다.
  • 네이티브 프레임워크(UIKit과 Android View 시스템)를 사용하는 주된 이유는 호환성안정성 때문
  • 광범위한 버전 지원(오래된 버전부터 현재 버전까지 안정적으로 작동)
  • 성숙한 API(오랜 기간 검증된 UI 렌더링 메커니즘)
  • 성능 최적화(각 플랫폼의 하드웨어와 깊이 통합된 렌더링 시스템)
 

궁금증💭 : 그러면 최신 프레임워크(SwiftUI, Jetpack Compose)랑 매핑되지 않는 이유❓

### Claude 답변 1. 개발 철학의 차이 SwiftUI와 Compose는 선언적 UI 패러다임을 완전히 새로운 방식으로 접근 React Native의 기존 브릿지 아키텍처와 근본적인 설계 차이 2. 기술적 복잡성 이러한 최신 프레임워크는 각 플랫폼의 고유한 상태 관리, 렌더링 시스템을 깊이 활용 React Native의 현재 아키텍처로는 이를 완벽하게 추상화하기 어려움 3. 성능과 호환성 문제 새로운 프레임워크의 고유 기능들을 JavaScript 브릿지를 통해 완전히 지원하기 어려움 성능 오버헤드와 기능 제한의 우려 4. React Native의 기존 접근 방식 기존 UIKit과 Android View 시스템을 통해 안정적이고 일관된 크로스 플랫폼 경험 제공 새로운 프레임워크로 전환할 경우 발생할 수 있는 호환성 및 마이그레이션 리스크 5. 진화하는 아키텍처 React Native의 New Architecture(Fabric, TurboModules)는 점진적으로 이러한 제한을 해결하려 노력 중 ### 결론 이러한 이유로 React Native는 여전히 기존의 안정적이고 검증된 UIKit과 Android View 시스템을 선호합니다.
 

참고 자료 🚀 : 토스가 꿈꾸는 React Native 기술의 미래

토스Tech 아티클에서도 엔진에 대한 언급이 있다. 내가 궁금했던 부분(왜 리액트 네이티브를 사용하는가)에 대한 내용도 있어서 이 포스팅을 보는 분들이라면 봐도 좋을 것 같다.
 
 
 

2️⃣ React Native의 구조

2-1) JavaScript 레이어

  • React 컴포넌트: 화면을 구성하는 기본 단위
    • 예: <View>, <Text>, <Button>, <ScrollView>.
  • JavaScript 런타임: JavaScript 코드가 실행되는 환경(Node.js와 비슷)
 

2-2) Bridge 레이어

JavaScript 코드와 네이티브 플랫폼(Android, iOS) 간의 중개 역할
  • 비동기 방식으로 동작.
  • JSON 메시지를 사용해 네이티브 코드와 데이터를 주고받음
 

2-3) Native 레이어

iOS와 Android의 네이티브 UI 및 기능으로, 플랫폼 고유의 컴포넌트와 API를 사용
  • iOS: UIKit 컴포넌트 (UILabel, UIButton 등)
  • Android: Android View 컴포넌트 (TextView, Button 등)
 

궁금증💭 : 브릿지 레이어, 네이티브 레이어를 알아야 하는 이유❓

### ChatGPT 답변 React Native가 단순히 JavaScript로만 동작하는 것이 아니라, 네이티브 플랫폼(Android/iOS)의 기능과 통합되기 때문입니다. 특히, 복잡한 기능이나 최적화를 위해 네이티브 코드를 작성해야 할 때 이 구조를 이해하고 있어야 합니다.
(포스팅 하면서 느낀건데 크로스 플랫폼 개념에 대한 이해가 없어서 이런 궁금증이 생긴 것 같다ㅎㅎ)
  • JavaScript만으로 할 수 없는 기능 구현
    • React Native는 대부분의 네이티브 기능을 JavaScript로 추상화했지만, 모든 네이티브 기능을 포함하지는 않음
    • 예: 특정 기기의 하드웨어 센서(지문 인식, BLE, NFC 등)를 사용해야 할 때
    • 이럴 때, 네이티브 모듈(Android: Java/Kotlin, iOS: Swift/Objective-C)을 작성하고 브릿지 레이어를 통해 JavaScript와 통신해야 함
  • 성능 최적화
    • 브릿지 레이어는 비동기 방식으로 동작하므로, 대량의 데이터 교환이나 반복 작업에서는 성능 병목이 발생할 수 있어서 고성능 처리가 필요하면 네이티브 코드로 직접 구현하는 것이 더 효율적
  • 파일 구조와 맞물린 네이티브 통합
    • React Native의 파일 구조는 JavaScript와 네이티브(Android/iOS)의 코드가 공존함
    • 따라서 네이티브 코드 파일이 어디에 위치하고, 어떤 역할을 하는지 이해하면 문제 해결과 확장에 유리함
React Native는 대부분 JavaScript 코드만으로 충분히 개발 가능하지만, 네이티브 코드와의 상호작용을 이해하면 더욱 강력한 앱을 만들 수 있다.
 

3️⃣ React Native의 주요 파일과 구조

MyReactNativeApp/ ├── android/ # Android 네이티브 프로젝트 (Java/Kotlin) ├── ios/ # iOS 네이티브 프로젝트 (Swift/Objective-C) ├── node_modules/ # JavaScript 라이브러리 ├── App.js # 메인 React Native 컴포넌트 ├── package.json # 프로젝트 의존성 및 스크립트 정의 ├── index.js # 앱 엔트리 포인트 └── babel.config.js # Babel 설정 파일
  • App.js
    • React Native 앱의 메인 화면 정의
    • React 컴포넌트를 사용하여 UI 구성
  • index.js
    • 앱 실행을 위한 진입점
    • App.js를 네이티브로 연결
  • iOS/Android 폴더
    • 각각의 플랫폼별 네이티브 프로젝트 파일
    • 네이티브 코드를 추가하거나 수정할 때 사용
 
 

4️⃣ React Native에서 상태 관리와 데이터 흐름

React Native는 React와 동일한 데이터 흐름 방식을 따릅니다.
 

4-1) 단방향 데이터 흐름

  • 상태(state)와 속성(props)를 통해 컴포넌트 간 데이터를 전달
  • 상태 변경은 컴포넌트의 UI를 리렌더링합니다
import React, { useState } from 'react'; import { View, Text, Button } from 'react-native'; const CounterApp = () => { const [count, setCount] = useState(0); return ( <View> <Text>Count: {count}</Text> <Button title="Increase" onPress={() => setCount(count + 1)} /> </View> ); }; export default CounterApp;
notion image

4-2) 글로벌 상태 관리

Redux, MobX, 또는 React의 Context API를 사용하여 글로벌 상태 관리가 가능합니다.
 
 
 

5️⃣ React Native의 컴포넌트 구조

React Native는 UI를 컴포넌트로 나눠 관리합니다. 모든 화면과 UI는 컴포넌트로 구성됩니다.
 

5-1) 기본 컴포넌트

React Native는 플랫폼에 독립적인 기본 컴포넌트를 제공합니다:
  • View: UI의 컨테이너
  • Text: 텍스트 표시
  • Button: 버튼
  • Image: 이미지 표시
  • FlatList/SectionList: 리스트 렌더링
 

5-2) 스타일링

React Native는 CSS와 유사한 스타일링을 제공합니다.
  • StyleSheet 객체를 사용
  • Flexbox 기반 레이아웃 지원
import { StyleSheet } from 'react-native'; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, text: { fontSize: 18, color: 'blue', }, });
notion image
 

6️⃣ React Native의 동작 예시

1. 사용자가 앱을 실행 2. index.js에서 JavaScript 코드를 로드 3. App.js의 React Component를 렌더링 4. JavaScript 런타임이 컴포넌트를 네이티브 UI로 변환 5. 네이티브 API 호출(예: 카메라, 위치 정보)을 통해 기능 수행
 
 
 
 
여기까지는 리액트 네이티브에 대한 것을 알아보았고 다음 포스팅엔 왜 RN을 사용하는지에 대해서 알아본 바를 포스팅하려고 합니다,,
Share article

code-with-me