퍼포먼스가 뛰어난 React Native 앱 구축
I’m happy to translate the article for you, but I need the text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source line, formatting, and code blocks unchanged while translating the rest into Korean.
Source: …
Profile
성능을 개선하기 전에 앱의 어느 부분이 실제로 느린지 먼저 이해하세요.
- React Debugger – 비용이 많이 드는 재렌더링, 초기 로드 시간, 화면 마운트/언마운트 상태를 파악하는 데 도움이 됩니다.
그 가치를 과소평가하지 마세요; 성능을 크게 향상시킬 수 있습니다.

JavaScript를 넘어 네이티브 수준에서 앱을 프로파일링하고 싶다면 Xcode 또는 Android Studio를 사용할 수 있습니다. 네이티브 프로파일링을 통해 다음을 확인할 수 있습니다:
- 전체 메모리 사용량
- 특정 화면이나 작업에 대한 메모리 소비
- 네이티브 메모리 누수
- CPU 사용량
네이티브 프로파일링은 선택 사항이며, 앱이 무거운 작업(예: 비디오 렌더링이나 3D 그래픽)을 수행하지 않는다면 생략해도 됩니다.
Android Studio 또는 Xcode와 같은 IDE를 사용해 앱을 네이티브로 프로파일링할 수 있습니다. 이렇게 하면 전체 메모리 사용량, 네이티브 누수, CPU 부하에 대한 명확한 그림을 얻을 수 있습니다.


이 시점에서 앱의 어느 부분이 느린지에 대한 감을 잡았을 것입니다. 이제 무엇을 어떻게 최적화할지에 대해 논의해 보겠습니다.
대규모 리스트 렌더링
리스트를 렌더링하는 것은 어려울 수 있습니다. 간단한 아이템이라면 FlatList 또는 FlashList(Shopify)를 사용하세요. 두 가지 모두 중간 규모 리스트에 대한 직관적인 해결책입니다.
각 아이템을 렌더링하는 데 눈에 띄게 시간이 걸리는 경우(예: ~400 ms) 문제가 발생합니다. FlatList의 가상화는 사용자가 스크롤할 때 아이템을 추가·제거하는데, 이 과정에서 CPU가 가상화 작업에 바쁘면 눈에 보이는 빈칸이 나타날 수 있습니다.
해결책
| Library | 주요 기능 | 도움이 되는 이유 |
|---|---|---|
| FlashList | 아이템 재활용 | 렌더링된 아이템을 재사용하여 새 아이템을 생성하는 비용을 줄입니다. |
| LegendList | 반응성 및 선택적 재활용 | 변경 사항이 없을 때 아이템의 재렌더링을 방지하여 빈 공간을 없앱니다. |
| Legend‑State | 세밀한 반응성 | 불필요한 재렌더링 없이 실시간 데이터 업데이트를 위해 LegendList와 함께 작동합니다. |
LegendList는 대량의 아이템을 효율적으로 렌더링하기 위한 견고한 솔루션으로, 정확한 위치 지정과 선택적 재활용을 통해 빈 공간을 정밀하게 방지합니다. 세밀한 반응성이 필요한 시나리오(예: 실시간 데이터 피드)에서는 Legend‑State와 함께 사용하면 좋습니다.
Source:
초기 부팅 시간

부팅 시간은 앱이 기기에서 로드되고 실행되는 데 필요한 기간을 말합니다. 여기에는 JavaScript 번들을 RAM에 로드하고 실행하는 과정이 포함됩니다.
앱에 부피가 큰 JS 번들이 포함되어 있으면 사용자는 눈에 띄는 지연을 경험하게 되고, 이는 불만을 초래합니다.
번들 크기 및 실행 시간 감소 팁
- Hermes(또는 다른 JS 엔진)를 활성화하여 시작 속도를 높이세요.
- 코드 스플리팅(
import()문)으로 화면을 지연 로드하세요. - 사용되지 않는 의존성 제거(
npm prune,yarn autoclean). - **Metro의
inlineRequires**를 활성화하여 모듈 초기화를 연기하세요. - 자산 압축(이미지, 폰트) 및 가능한 경우 벡터 그래픽을 사용하세요.
npx react-native-bundle-visualizer로 번들 분석을 수행해 큰 모듈을 찾아내세요.

최종 생각
Performance optimisation is an iterative process:
- 프로파일링 → 병목 현상을 식별합니다.
- 대상별 수정 적용 (리스트 가상화, 번들 축소, 네이티브 프로파일링).
- 재‑프로파일링하여 개선 사항을 확인합니다.
위 단계들을 따라 하면 고성능 및 중급 기기 모두에서 반응이 빠른 React Native 앱을 제공할 수 있습니다. Happy coding!
번들 크기
- webpack‑bundle‑analyzer 와 같은 도구를 사용하여 번들에서 가장 큰 비중을 차지하는 부분을 확인합니다.
- 무거운 서드파티 의존성을 식별하고 더 가벼운 대안으로 교체합니다.
Note: 웹과 달리 React Native는 기본적으로 전체 코드 스플리팅을 지원하지 않습니다.
- 코드 스플리팅을 지원하는 Repack 번들러를 시도해 볼 수 있습니다(추가 설정 필요).
Best practice:
- 이미지, SVG 등 미디어 자산을 JavaScript 번들에 포함하지 마세요.
- 원격에 호스팅하고 expo‑image와 같은 라이브러리를 사용해 캐시합니다.
지연 로딩의 착각
Huddle01 Meet 앱을 만들 때 Android 기기에서 눈에 띄는 지연을 발견했습니다. 원인은? 모든 bottom‑sheet 컴포넌트를 한 번에 렌더링하는 것이었습니다.
해결책
{showSheet && <BottomSheet />}
- 현재 보이는 시트만 렌더링합니다.
- Android 기기(특히 저가·중가 모델)는 메모리와 CPU가 제한적이므로 조건부 렌더링을 하면 부드러움이 크게 향상됩니다.
경험 법칙: 초기에 보이지 않는 UI는 렌더링하지 마세요.
이 기법을 저는 **“지연 로딩의 착각”**이라고 부릅니다. 현명하게 사용하고 Intersection Observer API(또는 React‑Native 대응 API)와 결합해 화면 밖 컴포넌트가 마운트되는 것을 완전히 방지하세요.
Synthetic‑Sugar Trade‑offs
- “멋진” JavaScript 라이브러리 중 구문 설탕만 제공하는 것은 피하세요.
- 기억하세요: JS는 React‑Native 앱 실행 시간의 약 80 %를 차지하므로, 추가 라이브러리는 성능에 악영향을 줄 수 있습니다.
Recommendations
- 무거운 서드파티 패키지보다 커스텀 구현을 선호하세요.
- 저가형 Android 기기에서는 CSS‑in‑JS 라이브러리를 건너뛰세요. 단, 정말 가벼운 경우(예: react‑native‑unistyle)는 제외합니다.
- 측정 후에 의존성을 추가하세요 – 런타임 오버헤드는 성능의 가장 큰 적입니다.
대상 사용자(예: $100대 스마트폰)가 절대 사용하지 않을 기능에 최적화하지 마세요.
명령형 UI 업데이트
React의 선언형 모델은 훌륭하지만, 때때로 전체 재렌더링은 비용이 많이 듭니다.
setNativeProps(link)는 React 렌더링을 트리거하지 않고 네이티브 뷰를 변경할 수 있게 해줍니다.- 절제해서 사용하세요; React 상태와 UI가 동기화되지 않을 수 있습니다.
Typical use‑case: 저사양 기기에서 다크/라이트 모드를 전환할 때. React 상태를 통해 전체 UI를 업데이트하면 눈에 띄는 지연이 발생할 수 있습니다; 명령형 업데이트가 더 빠를 수 있지만, React 상태를 수동으로 동기화해야 합니다.
애니메이션
- react‑native‑reanimated 은 애니메이션 작업을 UI 스레드로 오프로드하여 고성능 디바이스에 적합합니다.
- 저사양 Android 폰에서는 추가 스레드 오버헤드가 역효과를 내어 애니메이션이 끊기거나 작동하지 않을 수 있습니다.
가이드라인
- 주요 사용자가 저사양 하드웨어를 사용한다면 vanilla React‑Native animations (
AnimatedAPI)를 사용하여 스레드 경쟁을 최소화하세요.
GPU 리소스 활용

- react‑native‑skia 은 JavaScript에서 직접 GPU에 그래픽을 그릴 수 있게 해주어, 실시간 이미지 조작 및 셰이더 효과를 가능하게 합니다.
- react‑native‑filament (Margelo 제공) 은 네이티브 GPU에서 전체 3D 씬을 렌더링합니다 – “포켓몬 GO‑스타일” 경험을 떠올려 보세요.
Why it matters: 무거운 시각 작업을 GPU에 오프로드하면 JavaScript 스레드에 대한 부담이 줄어들어, 제약이 있는 디바이스에서도 UI가 더 부드러워집니다.
C++ 매직 & 새로운 아키텍처
React Native의 새로운 아키텍처(TurboModules, Fabric, JSI)는 성능이 중요한 코드를 **C++**로 작성하고 거의 제로에 가까운 오버헤드로 JavaScript에 노출할 수 있게 합니다.
- 자주 호출되는 네이티브 모듈에는 TurboModules를 사용하세요.
- JSI(JavaScript Interface)를 활용해 브리지 병목 없이 C++와 JS를 연결합니다.
결과: 네이티브‑to‑JS 통신이 빨라지고 지연 시간이 감소하며 디바이스 자원을 더 효율적으로 활용할 수 있습니다.
저사양 Android 최적화를 위한 빠른 체크리스트
| ✅ | 작업 |
|---|---|
| 1 | 번들 크기를 분석하고, 무거운 의존성을 제거합니다. |
| 2 | expo-image 로 캐시하면서 미디어 자산을 원격으로 호스팅합니다. |
| 3 | 보이는 컴포넌트만 렌더링합니다 (조건부 렌더링, Intersection Observer). |
| 4 | 불필요한 “문법 설탕” 라이브러리를 피하고, 추가하기 전에 측정합니다. |
| 5 | React 상태와 동기화할 수 있을 때만 setNativeProps를 사용합니다. |
| 6 | 저사양 디바이스에서는 Reanimated보다 기본 Animated API를 선호합니다. |
| 7 | react-native-skia 또는 react-native-filament 로 그래픽을 GPU에 오프로드합니다. |
| 8 | C++ 수준 성능을 위해 새로운 아키텍처(TurboModules, Fabric, JSI)를 채택합니다. |
React Native, JSI, 그리고 C++의 힘
**JSI (JavaScript Interface)**는 기존 브리지를 사용할 필요성을 없애고 JavaScript 런타임에서 네이티브 API에 직접 접근할 수 있게 합니다. C++로 작성되었으며, 네이티브 코드를 호출하는 고성능·저오버헤드 방식을 제공합니다.
React Native의 핵심 기여자이자 가장 뛰어난 C++ 엔지니어 중 한 명인 **Marc Mrousavy**와 그의 팀은 JSI 모듈을 완전히 C++로 구현한 여러 강력한 라이브러리를 공개했습니다.
- react‑native‑quick‑crypto – 네이티브 측에서 모든 무거운 작업을 수행하는 C++ 구현으로, JavaScript 스레드를 완전히 논블로킹 상태로 유지합니다.
- Nitro Modules – 고도로 최적화된 JSI를 사용하고 엔드‑투‑엔드 타입 안전성을 제공하는 새로운 네이티브 모듈 작성 방식입니다. 벤치마크는 **여기**에서 확인하세요.
왜 지금 C++가 중요한가
AI‑지원 개발 덕분에 특정 요구사항에 맞는 네이티브 모듈을 생성하는 것이 그 어느 때보다 쉬워졌습니다. Nitro Modules는 이 과정을 가속화해 더 빠르고 견고한 네이티브 코드를 만들 수 있게 합니다.
네이티브와 JavaScript 사이의 경계가 흐려지고 있습니다. C++는 맞춤형 네이티브 구현을 손쉽게 작성할 수 있게 해 주는 다리 역할을 하며, React Native가 달성할 수 있는 한계를 넓혀 줍니다.
결론
지난 5년은 React Native에게 황금기였습니다. 지원하는 커뮤니티의 도움으로 이제 우리는 진정한 “write once, run anywhere” 코드베이스를 갖게 되었습니다. 우리가 더 창의적으로 될수록 기존 기술의 한계를 뛰어넘어야 합니다. React Native는 여전히 일부 분야에서 제약이 있을 수 있지만 계속 개선될 것입니다. 미래의 후속 버전이 오늘 우리가 직면한 도전을 궁극적으로 극복할 수도 있습니다. React Native와 Flutter와 같은 크로스‑플랫폼 기술이 발전하는 모습을 보는 것은 흥미롭습니다.
이 블로그를 읽어 주셔서 감사합니다. 댓글 섹션에 언제든지 질문을 남겨 주세요.
새해 복 많이 받으세요!