React Native는 React 원리를 사용하여 iOS와 Android용 진정한 네이티브 앱을 만들 수 있게 해줍니다. 이 포괄적인 가이드는 당신의 React 웹 전문 지식을 React Native에 매핑하여 중요한 차이점과 모바일 특화 패턴을 강조합니다.

1. 환경 설정 및 개발 도구

Expo CLI와 React Native CLI 선택하기

첫 번째로 마주할 결정은 개발 접근 방식을 선택하는 것입니다. Expo CLI는 빠른 프로토타이핑과 간단한 앱에 완벽한 관리형 워크플로우를 제공하며, 네이티브 코드를 건드리지 않고도 사전 구성된 빌드 파이프라인과 OTA 업데이트를 제공합니다. 풍부한 사전 빌드 라이브러리 생태계를 포함하지만 커스텀 네이티브 모듈 접근을 제한하고 번들 크기를 증가시킵니다. React Native CLI는 네이티브 코드와 빌드 프로세스에 대한 완전한 제어를 제공하여 커스텀 네이티브 통합이나 성능 최적화가 필요한 프로덕션 앱에 이상적이지만, 더 복잡한 설정과 네이티브 개발 지식이 필요합니다.

대부분의 새 프로젝트의 경우 Expo로 시작하고 필요한 경우 나중에 eject하세요. 복잡한 요구사항이 있는 프로덕션 앱은 처음부터 React Native CLI를 사용해야 합니다.

개발 환경 구성

React Native 설정은 웹 개발과 크게 다릅니다. macOS에서는 iOS 개발을 위한 Xcode와 Android를 위한 Android Studio, 그리고 Node.js, Watchman, 플랫폼별 SDK가 필요합니다. iOS 시뮬레이터는 개발과 완벽하게 통합되는 반면, Android는 적절한 하드웨어 가속으로 AVD(Android Virtual Device)를 구성해야 합니다.

Metro 번들러는 웹팩을 대체하여 React Native용으로 특별히 최적화된 JavaScript 번들러입니다. Fast Refresh, 플랫폼 인식 코드 분할, Hermes JavaScript 엔진 통합 등의 기능을 제공합니다. 웹팩의 복잡한 구성과 달리 Metro는 합리적인 기본값으로 즉시 작동합니다:

// metro.config.js - 일반적인 구성
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');

const config = {
  resolver: {
    assetExts: ['db', 'mp3', 'ttf'],
    sourceExts: ['js', 'jsx', 'ts', 'tsx', 'svg'],
  },
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);

필수 디버깅 도구

React Native 디버깅은 브라우저 DevTools와 다릅니다. Flipper는 레이아웃 검사, 네트워크 모니터링, 데이터베이스 탐색, 성능 프로파일링을 하나의 통합 도구에서 제공하는 주요 디버깅 플랫폼입니다. React Native DevTools는 모바일 개발에 최적화된 컴포넌트 트리 시각화와 훅 디버깅을 제공합니다. JavaScript 디버깅을 위한 Chrome DevTools 통합이 존재하지만 원격 실행으로 인해 성능에 영향을 줍니다.

2. 핵심 컴포넌트와 API 매핑

HTML에서 React Native 컴포넌트로

가장 큰 초기 조정은 컴포넌트 어휘 변경입니다. 모든 <div><View>가 되고, 모든 텍스트는 <Text> 컴포넌트가 필요하며(원시 문자열 불가), <img><Image>로 변환됩니다. 이는 단순한 구문이 아니라 네이티브 렌더링 아키텍처를 반영합니다:

// React Web
<div className="container">
  <h1>Welcome</h1>
  <p>Hello world</p>
  <img src="photo.jpg" alt="Photo" />
  <button onClick={handleClick}>Click me</button>
</div>

// React Native
<View style={styles.container}>
  <Text style={styles.title}>Welcome</Text>
  <Text>Hello world</Text>
  <Image source={{uri: 'photo.jpg'}} style={styles.image} />
  <TouchableOpacity onPress={handleClick}>
    <Text>Click me</Text>
  </TouchableOpacity>
</View>

중요한 차이점: React Native에서는 View 컴포넌트 내부에 텍스트를 직접 배치할 수 없습니다. 모든 텍스트는 Text 컴포넌트로 감싸야 합니다. 터치 처리는 onClick 핸들러 대신 명시적인 터치 가능 컴포넌트(TouchableOpacity, TouchableHighlight, Pressable)가 필요합니다.

리스트는 다른 사고방식이 필요합니다

ScrollView는 모든 자식을 즉시 렌더링하므로 작은 리스트에만 적합합니다. FlatList는 가상화를 구현하여 보이는 항목만 렌더링합니다. 50개 이상의 항목이 있는 모든 리스트에 필수적입니다:

// 대용량 리스트에 절대 이렇게 하지 마세요
<ScrollView>
  {items.map(item => <Item key={item.id} data={item} />)}
</ScrollView>

// 성능을 위해 항상 FlatList를 사용하세요
<FlatList
  data={items}
  renderItem={({item}) => <Item data={item} />}
  keyExtractor={item => item.id}
  getItemLayout={(data, index) => ({
    length: ITEM_HEIGHT,
    offset: ITEM_HEIGHT * index,
    index,
  })}
/>

3. 스타일링 시스템 기초