스타트업, 제발 React Native 쓰세요 (솔직한 2년 사용기)
1. 돈 없으면 선택지는 하나다
창업 초기, 통장 잔고는 바닥이었고 앱은 만들어야 했습니다. iOS 개발자(Swift) 한 명, Android 개발자(Kotlin) 한 명을 채용할 여력 따위는 없었죠. 평균 연봉만 따져도 1년에 1억 이상이 깨지는 일이니까요.
선택지는 하나였습니다. 크로스 플랫폼(Cross Platform). Flutter와 React Native 중 고민하다가, 제가 웹(React) 개발자 출신이라 React Native(RN)를 골랐습니다.
"JavaScript로 앱을 만든다고? 느리지 않을까? 페이스북(Meta)이 만들었다지만 믿어도 될까?" 걱정 반, 기대 반으로 시작했습니다. 그리고 2년이 지났습니다.
2. 꿈같은 생산성 (The Good)
처음엔 천국이었습니다. "이게 된다고?" 소리가 절로 나왔으니까요.
1) Hot Reloading은 마약이다
iOS 네이티브 개발을 해보신 분은 압니다. 버튼 색 하나 바꾸고 확인하려면 '빌드' 버튼 누르고 1분 동안 멍때려야 합니다.
React Native는 Cmd + S를 누르자마자 0.5초 만에 시뮬레이터 화면이 바뀝니다.
이 피드백 루프의 속도가 개발자의 생산성을 10배로 만듭니다.
2) 코드 재사용 95%
"안드로이드는 뒤로가기 버튼 처리를 따로 해야겠지?" 아뇨, 거의 안 합니다. 비즈니스 로직, API 호출, 상태 관리(Zustand), 유틸리티 함수 등 95% 이상의 코드를 iOS와 Android가 완벽하게 공유합니다. UI도 Flexbox로 통일되어 있어서, 스타일 조금만 손보면(Safe Area 정도) 양쪽 다 예쁘게 나옵니다. 하나를 만들면 둘이 생기는 1+1 행사 같습니다.
3) 웹 개발자가 앱을 만든다 (채용의 용이성)
새로운 모바일 개발자를 뽑을 필요가 없습니다.
기존 웹 프론트엔드 개발자에게 "자, 이게 <div> 대신 <View>를 쓰는 거야"라고 일주일만 가르치면 바로 실제 투입이 가능합니다.
인력 구하기 힘든 스타트업에겐 이게 킬러 기능(Killer Feature)입니다.
3. 지옥의 문이 열리다 (The Bad)
하지만 앱이 복잡해지면서, 저는 RN을 저주하기 시작했습니다.
1) 버전 업그레이드 지옥
어느 날 React Native 버전을 올리려고 패기롭게 npm update를 쳤습니다.
그리고 프로젝트가 일주일 동안 켜지지 않았습니다.
RN은 자바스크립트 코드와 네이티브 코드(Objective-C, Java)를 본드칠로 붙여놓은 형태입니다. 버전이 안 맞으면 이 본드가 떨어져 나갑니다. 빨간 에러 메시지를 복사해서 구글링하면 2019년 스택오버플로우 답변만 나오고... 새벽 4시에 사무실에서 울 뻔했습니다.
2) "제 폰에선 되는데요?" (안드로이드의 저주)
안드로이드 기기의 파편화(Fragmentation)는 상상을 초월합니다. 제 갤럭시 S24에선 잘 되는데, 고객의 3년 된 샤오미 폰에서는 버튼이 눌리지 않고, 화웨이 폰에서는 앱이 켜지자마자 꺼집니다. 결국 자바스크립트만 하려던 저는 Android Studio를 켜고, 알지도 못하는 Gradle 설정과 Java 코드를 디버깅하고 있었습니다. "이럴 거면 그냥 네이티브 배울 걸..." 하는 현타가 옵니다.
3) 성능의 한계 (Bridge)
RN은 자바스크립트 스레드와 네이티브 스레드가 브릿지(Bridge)를 통해 JSON 메시지를 주고받으며 통신합니다. 리스트를 빠르게 스크롤하거나, 복잡한 애니메이션을 돌리면 이 브릿지가 막혀서 프레임 드랍(버벅임)이 생깁니다. 물론 지금은 New Architecture (Fabric/TurboModules)가 나와서 C++로 직접 통신하므로 많이 좋아졌지만, 여전히 순정 네이티브의 그 '쫀득한' 맛을 내려면 최적화 노력이 필요합니다.
4. 해결사 등판: Expo
이런 단점들에도 불구하고, 타임머신을 타고 돌아가도 저는 React Native를 선택할 겁니다. 대신 이번엔 순정 RN이 아니라 Expo를 쓸 겁니다.
예전의 Expo는 "장난감" 취급을 받았습니다. 네이티브 모듈을 못 썼으니까요. 하지만 지금의 Expo(EAS)는 괴물입니다.
1) CNG (Continuous Native Generation)
이제 개발자는 ios/ 폴더와 android/ 폴더를 아예 안 만듭니다.
npx expo prebuild 명령어 한 방이면, 설정 파일(app.json)을 읽어서 네이티브 폴더를 그때그때 생성해 줍니다.
이게 무슨 뜻이냐? 버전 업그레이드 지옥에서 해방된다는 뜻입니다.
2) OTA (Over The Air) 업데이트
앱스토어 심사는 까다롭고 오래 걸립니다. (최소 1~2일) 치명적인 버그가 생겼을 때, Expo Updates를 쓰면 심사 없이 자바스크립트 코드를 사용자 폰으로 몰래 쏘아서 고칠 수 있습니다. 이 기능 하나만으로도 Expo를 쓸 이유는 충분합니다.
5. 테크니컬 딥다이브 - 새로운 아키텍처 (New Architecture)
많은 분들이 "RN은 느리다"고 알고 계십니다. 과거에는 Bridge라는 통로를 통해 JS와 Native가 JSON 문자열을 주고받았기 때문입니다. 초당 60프레임으로 스크롤할 때, 수많은 JSON 메시지가 브릿지를 꽉 막아서 버벅거렸죠.
하지만 React Native 0.68+부터 도입된 New Architecture는 완전히 다릅니다.
- JSI (JavaScript Interface): 브릿지를 태우지 않고, C++ 레벨에서 자바스크립트가 직접 네이티브 함수를 호출합니다. (웹 브라우저가 DOM을 제어하는 방식과 같습니다)
- Fabric: 새로운 렌더링 시스템입니다. React의 동시성 모드(Concurrent Mode)를 지원하여, UI 렌더링 우선순위를 조절합니다.
- TurboModules: 앱이 켜질 때 모든 네이티브 모듈을 로드하지 않고, "필요할 때" 로드합니다. (Lazy Loading). 앱 실행 속도(TTI)가 획기적으로 빨라집니다.
이제 RN의 성능은 네이티브와 거의 구별할 수 없는 수준에 도달했습니다.
6. Flutter와 비교한다면?
저는 두 프레임워크를 모두 실제로 검토했었습니다.
Flutter의 장점:
- Skia 엔진: 네이티브 UI 컴포넌트를 쓰지 않고, 캔버스에 직접 그림을 그립니다. 그래서 iOS/Android 간 디자인 통일성이 100%입니다.
- Dart: 언어 자체가 UI에 최적화되어 있고, 정적 타입이라 안정적입니다.
RN(Expo)의 장점:
- OTA 업데이트: 심사 없이 버그 픽스를 배포하는 기능은 비즈니스에 있어 핵무기급입니다. (Flutter는 이게 정책상 어렵습니다)
- 인력 풀: 자바스크립트 개발자는 널렸지만, 다트 개발자는 희귀 포켓몬입니다.
결국 "비즈니스 생존" 관점에서는 React Native가 더 유리한 선택이라 판단했습니다.
7. 마무리 - 스타트업의 무기
기술 스택은 종교가 아닙니다. 비즈니스 도구입니다.
- 당신이 스타트업이라면: 무조건 React Native (with Expo) 쓰세요. 속도가 생명입니다.
- 복잡한 쇼핑몰/SNS: React Native로 충분합니다. (토스, 당근마켓, 인스타그램도 RN을 씁니다)
- 고사양 3D 게임/영상 편집 앱: 제발 네이티브(Swift/Kotlin)로 가세요. RN으로 하면 피 봅니다.
React Native는 완벽하지 않습니다. 하지만 "가장 적은 리소스(돈/시간)로 가장 빠르게 시장에 진입하는" 최고의 무기임은 확실합니다. Flutter도 좋지만, 이미 React를 아는 웹 개발자가 세상에 넘쳐나는데 굳이 Dart를 새로 배울 이유가 있을까요?
Startups, Please Use React Native (My Honest 2-Year Review)
1. No Money, One Option
Early-stage startup. Zero cash. Need an app. I couldn't afford hiring one iOS dev (Swift) AND one Android dev (Kotlin). Their combined salaries would burn half our runway.
The only option: Cross Platform. Between Flutter and React Native, I chose React Native because I was a web (React) dev.
"Apps with JavaScript? Won't it be slow? Can we trust Meta?" I started with half worry, half hope. And now, 2 years later.
2. Productivity Heaven (The Good)
At first, it was bliss. I found myself saying, "Wait, this actually works?"
1) Hot Reloading is a Drug
If you've done iOS native dev, you know the pain. Change a button color, press Build, wait 1 minute.
In React Native, Cmd + S updates the screen in 0.5s.
This speed of the Feedback Loop boosts developer productivity by 10x.
2) 95% Code Reuse
"Do I need to handle the Android Back Button separately?" Rarely. Business logic, API calls, state management (Zustand), and utilities are shared 100% between iOS and Android. The UI is unified with Flexbox, so with minor tweaks (like Safe Area), it looks great on both. It feels like a "Buy 1 Get 1 Free" deal.
3) Web Devs Build Apps (Hiring is Easy)
You don't need to hunt for expensive mobile specialists.
Grab a web frontend dev, tell them "Use <View> instead of <div>," and they are ready for production in a week.
For startups struggling to hire, this is a Killer Feature.
3. Hell Opens Up (The Bad)
But as the app grew complex, I started cursing RN.
1) Version Upgrade Hell
One day, I bravely ran npm update to upgrade RN.
The project didn't open for a week.
RN is like gluing JavaScript code and Native code (Obj-C, Java) together. If versions mismatch, the glue fails. Googling red errors only gives StackOverflow answers from 2019... I almost cried in the office at 4 AM.
2) "It Works on My Machine" (The Android Curse)
Android fragmentation is nightmare fuel. It works perfectly on my Galaxy S24, but on a customer's 3-year-old Xiaomi, buttons don't click, and on a Huawei, it crashes on launch. Eventually, I found myself opening Android Studio, debugging Gradle configs and Java code I didn't understand. "I should've just learned Native..." I thought.
3) Performance Limits (The Bridge)
RN communicates between the JS Thread and Native Thread via a Bridge, passing JSON messages. If you scroll a list too fast or run complex animations, this bridge gets clogged, causing frame drops (jank). Although the New Architecture (Fabric/TurboModules) now uses C++ for direct communication, achieving that "buttery smooth" native feel still requires optimization effort.
4. The Savior: Expo
Despite the pain, if I could go back in time, I'd choose React Native again. But this time, I would use Expo.
Old Expo was considered a "toy" because it blocked Native Modules. But modern Expo (EAS) is a beast.
1) CNG (Continuous Native Generation)
Now, you never touch ios/ or android/ folders.
npx expo prebuild generates these folders on demand from your config (app.json).
This means Freedom from Version Upgrade Hell.
2) OTA (Over The Air) Updates
6. The Deep Dive: How Expo Changed the Game
Why is EAS (Expo Application Services) such a big deal?
Before EAS, if you needed a native library (like a specific KakaoTalk Login SDK), you had to "eject" from Expo.
Running npm run eject was a one-way ticket to hell. It exposed all the native folders, and you lost the convenience of Expo.
But with CNG (Continuous Native Generation) and Config Plugins, you never eject.
You write a small plugin code in JS that tells EAS:
"Hey, when you build this app on the cloud, please inject this line into AndroidManifest.xml and add this pod to Podfile."
This means your project stays pure JavaScript. The native complexity is offloaded to the build server. This is the equivalent of "Serverless" for mobile development.
7. The Future: New Architecture (Fabric & TurboModules)
React Native had a bottleneck: the Bridge. Every scroll event, every touch had to be serialized to JSON, sent across the bridge, and deserialized. This is why animations could stutter.
But the New Architecture (enabled by default in new versions) fixes this.
- JSI (JavaScript Interface): JS can call C++ methods directly. No JSON serialization.
- Fabric: The new Rendering System. UI updates are synchronous and prioritized.
- TurboModules: Native modules are lazy-loaded. The app starts faster.
With these updates, RN performance is practically indistinguishable from Native for 99% of apps.
8. React Native vs Flutter: The Final Verdict
I've tried both. Here is the realistic breakdown.
React Native
- Pros:
- JavaScript Ecosystem: Access to millions of npm packages.
- Hiring: Easy to find React devs.
- OTA Updates: CodePush / Expo Updates are life-savers.
- Cons:
- Upgrades: Still scary (though Expo helps).
- Styles: Different on iOS/Android sometimes.
Flutter
- Pros:
- Pixel Perfect: Renders its own pixels (Skia engine). Looks exactly the same on both OS.
- Performance: Compiled to native ARM code. Fast.
- DX: CLI tools and Widget docs are amazing.
- Cons:
- Dart: You have to learn a new language.
- No OTA: You cannot push code updates without App Store review (strict policy).
- Libraries: The ecosystem is smaller than npm.
My Take: If your team knows JS, stick to React Native (Expo). The cost of switching context to Dart is higher than the performance gain.
9. Essential Libraries for 2024
If you start a RN project today, ignore the old tutorials. Use this modern stack:
- Navigation: Expo Router. It brings Next.js-style file-system routing to mobile. (Built on top of React Navigation).
- Styling: NativeWind (TailwindCSS for RN) or Tamagui (High performance UI kit).
- Animations: React Native Reanimated 3. It runs animations on the UI thread (60fps guaranteed).
- Data Fetching: TanStack Query. Same as web.
- Forms: React Hook Form. Same as web.
The ecosystem has converged. If you know the modern React Web stack, you already know 80% of the React Native stack.