React Native 빌드 생태계 핵심 용어 정리

한 문장 요약

JS 코드 → Metro(번들) → Gradle(빌드) → 네이티브 코드와 합쳐서 → APK


전체 빌드 흐름

┌──────────────────────────────────────────────────────────┐
│                   소스코드 작성                             │
│    JS/TS (React Native)  +  C/C++ (네이티브 공용 라이브러리)   │
└────────────────┬────────────────────────┬────────────────┘
                 │                        │
                 ▼                        ▼
        ┌────────────────┐      ┌──────────────────┐
        │  JS 툴체인      │      │  NDK r28+         │
        │  Babel 트랜스파일│      │  C/C++ 크로스 컴파일 │
        │  Metro 번들링   │      │  → .so 파일        │
        └────────┬───────┘      └────────┬─────────┘
                 │                        │
                 └──────────┬─────────────┘
                            ▼
                  ┌──────────────────┐
                  │  빌드 체인         │
                  │  Gradle + AGP    │
                  │  build.gradle    │
                  └────────┬─────────┘
                           ▼
                      ┌─────────┐
                      │   APK   │
                      └────┬────┘
                           ▼
                    adb → 기기 설치 → 앱 스모크 테스트

1. 플랫폼 / 환경

용어핵심 설명
RNJS로 iOS/Android 앱을 만드는 프레임워크
AGPAndroid Gradle Plugin — Gradle이 Android용으로 동작하게 하는 플러그인
targetSDK”이 Android 버전까지 테스트됨” 선언 숫자 (예: 34 = Android 14)
NDK r28+Native Development Kit 버전 28 이상. C/C++ 코드를 Android용으로 크로스 컴파일하는 도구모음. 16KB page-size 대응에 필수
16KB page-sizeAndroid 15+에서 메모리 페이지 크기 4KB → 16KB 변경. .so 파일이 이에 맞게 정렬돼야 함. NDK r28+로 재컴파일 필요
ARM 빌드Android 기기의 CPU 아키텍처(arm64-v8a)에 맞게 네이티브 코드를 컴파일하는 것

2. 빌드 시스템

용어핵심 설명
GradleAndroid 빌드 자동화 도구. APK 생성까지의 전 과정을 조율
build.gradleGradle 설정 파일. 의존성, SDK 버전, 빌드 옵션 선언. 프로젝트 루트와 앱 모듈 두 곳에 존재
빌드 체인소스코드 → JS 번들링 → 네이티브 컴파일 → APK 패키징까지의 전체 파이프라인
wrapper (gradlew)Gradle을 로컬 설치 없이 프로젝트별 버전으로 실행하는 래퍼 스크립트
assembleDebug디버그용 APK를 빌드하는 Gradle 태스크 (./gradlew assembleDebug)
adbPC와 Android 기기를 연결해 APK 설치, 로그 확인 등을 하는 CLI 도구

3. JS 툴체인

package.json  (의존성 정의)
       │
       ▼
   [Babel]  ← 트랜스파일러
   최신 JS 문법 → 구형 런타임 호환 코드로 변환
       │
       ▼
   [Metro]  ← 번들러
   수백 개의 파일 → 하나의 번들(JS 파일)
       │
       ▼
   번들 (앱이 실제 실행하는 JS)
용어핵심 설명
package.jsonnpm/yarn 의존성과 스크립트를 정의하는 파일. 라이브러리 버전 관리의 기준점
Babel최신 JS 문법(ES2022+, JSX)을 구형 런타임에서도 돌아가게 변환하는 트랜스파일러
MetroReact Native 전용 번들러. JS 파일들을 하나로 묶어 앱에 전달
번들러수백 개의 JS 파일을 하나(또는 몇 개)의 파일로 합치는 도구
번들번들러가 만들어낸 결과물. 앱이 실제로 실행하는 JS 파일

4. 네이티브 코드

네이티브 코드 = CPU가 직접 실행하는 기계어(바이너리) 형태의 코드. JS처럼 런타임이 해석하지 않고, 해당 기기의 CPU에 맞게 미리 컴파일된 코드.

JS vs 네이티브 코드

JS (React Native)
  소스 → Metro 번들 → Hermes 엔진이 해석하며 실행
  특징: 유연함, 핫리로드 가능, 상대적으로 느림

네이티브 코드 (C/C++)
  소스 → NDK r28+ 크로스 컴파일 → CPU가 직접 실행
  특징: 빠름, 플랫폼 종속, 카메라/센서 등 OS 직접 접근

네이티브 코드 관련 용어

용어핵심 설명
네이티브 라이브러리C/C++로 컴파일된 .so 파일. JS에서 직접 다루기 어려운 기능을 처리
.so 파일Android의 네이티브 공유 라이브러리. Windows의 .dll과 같은 개념
JNIJava/Kotlin에서 C/C++ 네이티브 코드를 호출하는 인터페이스
JSIRN 새 아키텍처에서 JS가 네이티브를 직접 호출하는 방식. 브릿지 불필요
ABICPU 아키텍처마다 다른 바이너리 규약. arm64-v8a(기기), x86_64(에뮬레이터)
크로스 컴파일PC(x86)에서 Android 기기(ARM)용 코드를 만드는 것. NDK가 담당
gRPCC 기반 고성능 RPC 프레임워크. 네이티브 라이브러리 형태로 포함

.so 파일과 16KB page-size 문제

앱 A  ─┐
앱 B  ──┼──→  camera.so  (공통 기능 파일)
앱 C  ─┘

여러 앱이 같은 .so를 공유해 메모리/용량을 절약. Android 15+에서 페이지(RAM 메모리 데이터 처리 단위) 크기가 4KB → 16KB로 바뀌면서, 4KB 정렬로 컴파일된 구형 .so 파일을 새 Android 기기가 거부하는 문제 발생.

해결: NDK r28+로 16KB 정렬 방식으로 재컴파일 필요.

네이티브 lib 추가 업그레이드 시 체크리스트

확인 항목이유
NDK 버전 r28+16KB page-size 지원
ABI 필터 설정arm64-v8a 등 타겟 아키텍처 명시
16KB page-size 정렬Android 15+ 호환성
의존 라이브러리 버전 체인.so 하나 교체 시 연쇄 버전 충돌 가능
빌드 후 스모크 테스트실제 기기에서 크래시 여부 확인

네이티브 코드가 필요한 상황

상황이유
카메라, 블루투스, 센서OS API를 직접 접근해야 함
암호화, 이미지 처리성능이 중요한 연산
gRPC, SQLiteC 기반 라이브러리 재사용
16KB page-size 대응.so 파일의 메모리 정렬 규칙

5. RN 아키텍처

구 아키텍처 (Paper)             새 아키텍처 (New Architecture)

  JS                               JS
   │                                │
   │  비동기 브릿지                   │  JSI (직접 호출)
   │  (JSON 직렬화/역직렬화)          │  (메모리 공유)
   │                                │
  Native                           Native

  느린 통신, 직렬화 비용              빠른 통신, 동기 호출 가능
용어핵심 설명
Paper 아키텍처RN 구버전 렌더링 시스템. JS ↔ 네이티브 간 비동기 브릿지 사용. JSON 직렬화 비용 발생
newArchitectureRN 0.71+의 새 시스템. JSI로 브릿지 없이 직접 통신. reanimated 등이 이 방식을 활용
FlipperMeta의 모바일 디버거. 네트워크/레이아웃/로그 시각화. RN 0.73+부터 기본 제거
ReactNativeFlipperAndroid build.gradle에서 Flipper를 RN에 연결하는 설정 블록. 제거 시 관련 의존성도 함께 정리 필요
템플릿 드리프트버전 업그레이드를 거치며 공식 템플릿과 실제 프로젝트 설정이 달라진 상태. 빌드 오류의 주요 원인

6. 주요 라이브러리

라이브러리역할주의사항
react-native-safe-area-context노치/홈바 등 안전 영역 인식, UI가 가려지지 않게 처리RN 버전에 따라 호환 버전 다름
screens네이티브 수준의 화면 전환 성능 제공RN/아키텍처 버전에 맞게 고정 필요
svg벡터 이미지 렌더링네이티브 모듈 포함, 버전 호환 주의
reanimated고성능 애니메이션. 새 아키텍처에서 JS 스레드를 타지 않음newArchitecture 활성화 여부에 따라 동작 방식 다름
image-picker갤러리/카메라에서 사진 선택하는 네이티브 모듈iOS/Android 권한 설정 필요
splash-screen앱 시작 시 스플래시 이미지 표시네이티브 설정 파일 수정 필요

safe-area, screens, svg 버전: RN 버전과 아키텍처(Paper/New)에 따라 호환되는 버전이 다름. package.json에서 버전을 고정하고, 업그레이드 시 반드시 호환표 확인.


7. 앱 스모크 테스트

빌드 완료 후 핵심 기능이 최소한 동작하는지 빠르게 확인하는 테스트. 스크립트 없이 실제 기기/에뮬레이터에서 수동으로 실행.

빌드 완료 (assembleDebug)
       │
       ▼
adb install app-debug.apk
       │
       ▼
앱 실행 → 크래시 없이 뜨는가?
       │
       ├── 메인 화면 진입되는가?
       ├── 네트워크 요청 성공하는가?
       └── 네이티브 기능(카메라 등) 오류 없는가?

네이티브 lib 추가/업그레이드 후에는 반드시 실제 기기에서 스모크 테스트 필요. 에뮬레이터는 x86_64 ABI를 쓰므로 arm64 관련 문제를 잡지 못할 수 있음.


한눈에 보는 용어 지도

RN 프로젝트
├── JS 레이어
│   ├── package.json      (의존성 정의)
│   ├── Babel             (트랜스파일러)
│   └── Metro             (번들러) → 번들
│
├── 네이티브 레이어
│   ├── NDK r28+          (C/C++ 크로스 컴파일러)
│   ├── .so 파일          (네이티브 라이브러리)
│   ├── gRPC / SQLite     (C 기반 외부 라이브러리)
│   └── 16KB page-size    (정렬 규칙 — Android 15+)
│
├── 빌드 레이어
│   ├── build.gradle      (빌드 설정)
│   ├── AGP               (Android 빌드 플러그인)
│   ├── wrapper (gradlew) (버전별 Gradle 실행기)
│   ├── Gradle            (빌드 실행기) ← 빌드 체인 조율
│   └── APK               (최종 결과물) → adb → 기기
│
├── 아키텍처 레이어
│   ├── Paper             (구 아키텍처 — 비동기 브릿지)
│   ├── newArchitecture   (새 아키텍처 — JSI 직접 호출)
│   ├── Flipper           (디버거)
│   └── ReactNativeFlipper (build.gradle 내 Flipper 연결 설정)
│
└── 라이브러리 레이어
    ├── react-native-safe-area-context
    ├── screens / svg      (버전 호환 주의)
    ├── reanimated
    ├── image-picker
    └── splash-screen