본문으로 건너뛰기

React Native at Airbnb

무료2019-08-31#Tool#React Native企业应用#React Native案例#Why not React Native#RN is died#RN and Flutter

Airbnb 에서 React Native 의 흥망성쇠

시작하며

Airbnb 는 2016 년에 React Native 라는 큰 배에 올랐으며, 매우 대표적인 선구자였습니다:

In 2016, we took a big bet on React Native. Two years later, we're ready to share our experience with the world and show what's next.

그러나 2018 년 초에 React Native 종료를 발표했습니다:

Due to a variety of technical and organizational issues, we will be sunsetting React Native and putting all of our efforts into making native amazing.

React Native 를 전면 수용하는 것에서 Native 로 회귀하기까지, 이 기간 동안 무슨 일이 일어났을까요?

React Native 에 내기를 걸다

인력이 부족하여 다른 길을 찾을 수밖에 없었습니다:

Back then, we recognized how important mobile was becoming to our business but simply didn't have enough mobile engineers to reach our goals.

그리고 새로운 선택은 React Native 였습니다:

We saw React Native as an opportunity to open up mobile development to more engineers as well as ship code more quickly by leveraging its cross-platform nature.

Facebook 이 React Native 를 만든初衷 과 마찬가지로, Airbnb 도 React Native 기술을 활용하여 더 빠르게 움직이고, 하나의 제품 기능을 위해 두 개의 모바일 플랫폼 코드를 개발할 필요가 없기를 바랐습니다. 그러나底线으로서, 도입하는 이 새로운 기술도 Native 의既定 품질 기준에 도달하기를 바랐습니다

실제로 React Native 는 확실히 Airbnb 의 첫 기대에 도달했습니다:

Many of these features were built at a time where we simply did not have enough native engineers to achieve our goals.

그러나 이익만 있고 해가 없는 것은 아니며, 깊은 응용 속에서 두 가지 난제를 발견했습니다:

  • Native 의 복잡한 기능과의 통합: 공유 요소 트랜지션 애니메이션, 패럴랙스 효과, 지오펜싱 등

  • Native 의 기존 인프라와의 협력: 네트워크, 실험 테스트, 국제화 등

기쁨과 고통

However, its benefits didn't come without significant pain points.

Airbnb 의 실천 경험에 따르면, React Native 의 장점은 다음과 같습니다:

  • 크로스플랫폼: 나아가 3 엔드 디자인 언어의 통일, 및 Web 과 Native 의 코드 높은复用 실현

  • JS 생태계 적합: Redux, ESLint, Prettier, reselect, jest 등의 JS 생태계에 원활하게 접속

  • 개발 효율: 컴파일을 기다릴 필요 없이, Flexbox 레이아웃도 습득하기 쉬움

  • Native 확장: 모든 Native 기능을 React Native 에 브릿지할 수 있으며, 동시에 Native 의 기존 인프라도 통합 가능

  • 허용 가능한 성능: 애니메이션은 Native 와 마찬가지로 부드럽고, 경험은 대부분의 시나리오를 만족하며, 성능을 신경 쓸 일이 거의 없음

크로스플랫폼 특성이 가져오는 코드复用와 3 엔드 통일의 가능성은 대체 불가능한 장점이며, JavaScript 런타임을 지원함으로써 JS 생태계에 진입하여 Hot Reloading 등의 컴파일 불필요 경험을 획득하고, 개발 효율 향상을 실현합니다

실제로, 널리 주목받는 성능 문제는 상상만큼 느리지 않습니다:

We frequently saw mobile engineers look at JS and think"slower than Java". However, moving business logic and layout off of the main thread actually improves render performance in many cases.

능력의 경계에 닿는 시나리오에서는 Native Bridge 를 통해 제한을 깨뜨릴 수 있습니다:

Because everything in React Native can be bridged by native code, we were ultimately able to build many things we weren't sure were possible at the beginning such as Shared element transitions, Lottie, Native networking stack, i18n, experimentation, etc.

완벽해 보입니다. 그러나 다른 측면에서는 React Native 는 확실히 많은 고통을 가져왔습니다, 예를 들어:

  • 자체 성숙도 부족: Android, iOS 만큼 성숙하지 않으며, 불확실한 능력 경계 리스크 존재

  • JS 언어의 부족: 약타입으로 인해 리팩토링이 어렵고 오류 발생极易 (초기에는 TypeScript 지원 이 제공되지 않았음)

  • 라이브러리 구축 문턱 높음: React Native 라이브러리 작성에는 3 개 플랫폼을 숙지해야 하며,否则플랫폼 특정 문제가 발생하기 쉽고, 개발자에 대한 요구가 매우 높음

  • 일부 기능 지원도 불량: 예를 들어 무거운 Native Bridge API, 초기 제공된 접근성 API 불건전, 긴 List 지원이 Native 방안만큼 성숙·유연하지 않음, 제스처 지원, JS 런타임 환경에 플랫폼 차이……심지어 오랫동안 Android 64 비트를 지원하지 않음 (2019 년 3 월의 0.59 버전에서ようやく Android 64 비트 지원)

  • 첫 화면 성능 치명적 결함: 초 단위 런타임 초기화 오버헤드, 및 수백 밀리초의 전치 첫 화면 렌더링 시간, 플래시 스크린 등 시나리오의 성능 요구를 전혀 만족할 수 없음

  • 추가 부담: React Native 도입은 패키지 크기를 8~12MB 증가시킴을 의미하며, 동시에 생태계가 아직 성숙하지 않아, 개발 중 일반적으로 인프라와 기능 이터레이션 병행 필요

기술 자체의 성숙도 부족과, (라이브러리 구축의 높은 문턱으로 인한) ��픈소스 생태계 발전 지연으로 인해, 실제 사용에서는 빠르게 패치가 필요한 시나리오에 대응하기 위해, 보통 자체 React Native 를 유지해야 하며, 이 부분 유지 비용은 경시할 수 없음:

We had to maintain our own fork of React Native where we could merge fixes. For these case, a one-line fix on Android or iOS wound up taking days of figuring out how to add it to React Native, cherry picking it, then filing an issue on React Native core and following up on it over the coming weeks.

다른 측면에서, Native 가 수년간 축적한 인프라 (크래시 모니터링 등) 는 모두 React Native 에서 재구축 (재작성 또는 브릿지) 해야 하며,否则개발 경험과 효율은 따라가지 못합니다:

Because React Native is relatively new and rare in the industry, we had to build a significant amount of infrastructure.

첫 화면 성능의 주요 난점은 다음과 같습니다:

  • 초기화 시간: React Native 런타임 초기화 오버헤드는 피할 수 없으며, 대규모 애플리케이션에서는 (2018 년의) 하이엔드 장비에서도 수 초 필요

  • 렌더링 시작의 전치 시간: JS 스레드, yoga 레이아웃 스레드를 거쳐, 충분한 정보를 얻은 후에야 메인 스레드에서 렌더링 시작 가능, 이 기간 동안 280~440ms 의 화이트 스크린 시간 존재

P.S.스레드 모델의 제한은 다른 문제도 가져왔습니다, 예를 들어:

Many of the limitations are difficult to overcome because of the threading. Adapter data can't be accessed synchronously so it is possible to see views flash in as they get asynchronously rendered while scrolling quickly. Text also can't be measured synchronously so iOS can't make certain optimizations with pre-computed cell heights.

팀 조직은 어떻게 크로스플랫폼화하는가?

We learned a ton about what React Native means for an engineering organization. Adopting it is much more complex than adding a new library or pattern to an existing platform.

기술도 조직 구조에 영향을 미쳤으며, 이러한 과제는 기술 문제보다 해결하기 더 어려울 수 있습니다

엔지니어에 대한 요구

  • 3 엔드 경험 균형: React Native 의 본질은 여전히 Native 이므로, Native 인프라가 필수적이며, 플랫폼 차이는 여전히 존재하여, 이로 인해 3 엔드 경험을 균형잡는 것이 매우 어려워짐

  • 팀 간 문제 위치 파악: React Native 자체가 빠르게 발전 변화 중이며, 인프라와 기능 이터레이션 병행, 게다가 모두 경험이 많지 않아, 문제 위치 파악이 매우 어려워지고, 심지어 문제가 어느 팀에 귀속되는지, 아니면 상류 React Native 에서 온 것인지 알 수 없음

  • 크로스플랫폼 복잡성 대응: 엔지니어는 대부분 1~2 개 플랫폼에 익숙하며, 구축 또는 디버깅 시 다른 플랫폼涉及 가능. 더 나쁜 것은, 이러한 크로스플랫폼 복잡성에 직면하여, 엔지니어가 문제를 어디서부터 조사해야 할지 전혀 모를 수 있음

  • 3 세트 개발 환경 준비: React Native 엔지니어는 3 세트의 최신 개발 환경을 갖춰야 하며, 각 세트 환경은那么容易하게 구축·학습·유지 업데이트할 수 없으며, 몇 주마다 몇 시간을 들여 이러한 환경을 업데이트해야 함

React Native 는 플랫폼 차이를 완전히 가릴 수 없으므로, 엔지니어에게 이러한 차이를 이해하고, 신중하게 3 엔드 경험을 균형잡는 것이 요구됩니다. 크로스플랫폼으로 인한 복잡성은 직접 문제 조사 링크에 나타나며, 엔지니어는 팀 간, 기술 스택 간으로 문제를 위치 파악해야 할 수 있습니다

팀 조직이 직면한 과제

팀은 멤버 체감상의 몇 가지 문제에 직면할 수 있습니다, 예를 들어:

  • 태도 양극화: 실천 경험에 따르면, 엔지니어가 이 기술을 받아들이는 정도에는 양극화가 존재하며, 이를 3 엔드 통일의 은탄으로 여겨全力支持하는 자도 있고, 전혀 거부하여 조금도 사용하고 싶어하지 않는 자도 있음

  • 지각상의 이터레이션 속도 저하: 엔지니어의 시각에서 보면, Native 와 비교하여 React Native 로 특정 기능을 개발하는 데 1.5 배의 시간이 필요한 경우, 그는 여전히 더 많은 시간을 보냈다고 생각함, 사실 (멀티플랫폼) 총으로 보낸 시간이 감소했음에도 불구하고

혼합 기술 스택 하에서, 팀은 몇 가지 새로운 문제를 고려해야 합니다:

  • 팀을 어떻게划分하고, 어떻게 협력하는가?

  • 어떻게 효율적으로 기술 스택 간 디버깅하는가?

  • 어떻게 크로스플랫폼 테스트하고, 코드가 멀티플랫폼에서 정상 작동하는 것을 보증하는가?

  • 어떻게 새 기능을 어떤 기술로 구현할지 결정하는가?

  • 어떻게 팀 리소스를 모집하고 배분하는가?

실제로, 이러한 혼합 기술 스택은 확실히 인원 모집, 팀划分, 기술 구현, 트레이닝教学 등에 일련의 영향을 미쳤습니다:

  • 인원 모집:业界가 기업에 React Native 레이블을 붙여, 많은 엔지니어가 이ため加入을 주저하며, 인원 모집에 영향

  • 팀划分: 혼합 팀은 빈번하게 기술과 커뮤니케이션상의 문제에 직면함, 코드가 2 개로 나뉘어, 엔지니어가 더 이상 논리 흐름 전체에 익숙하지 않아, 비즈니스 로직, 모델, 상태 등을 공유하는 것이 매우 어려워짐. 이러한 문제는 리소스와 코드를 공유함으로써 해결할 수 있으나, 대多数팀은 아직 이러한 좋은 분위기를 형성하지 못함

  • 複数 기술 스택 균형: 어떤 코드를 Native 로 구현해야 하는지, 어느 것을 React Native 에 둘 것인지는, 权衡할 필요가 있음. 엔지니어는 보통 이것들을 고려하지 않고, 자신이 익숙한 기술 스택을 사용하는 경향이 있어, 일부 코드가 그렇게 이상적이지 않게 됨

  • 트레이닝教学: Native 의 10 년 이상 리소스 축적에 비교하여, React Native 관련 학습 리소스와 문서는 여전히 너무 적음, 기술 및 내부 인프라의教学트레이닝에 몇 가지 리소스를 투입할 필요가 있음

React Native 를 포기하고 Native 로 회귀

Although many teams relied on React Native and had planned on using it for the foreseeable future, we were ultimately unable to meet our original goals.

2 년의 실천 검증을 거쳐, React Native 가 첫 기대를 완전히 만족할 수 없음을 확인:

  • Move Faster: 순조로울 때는, 개발 속도가 확실히 비할 데 없으나, 다양한 기술상 및 조직상의 문제가 이 속도를 크게 늦춤

  • Native 의既定 품질 기준에 도달: React Native 의不断 성숙과 실천 중 축적한 경험은 몇 가지 성능 향상을 가져왔으나, 몇 가지 기술 문제 (초기화와 첫 화면 비동기 렌더링 등) 는 여전히 도전으로 가득 차 있으며, 내부 외부 리소스 부족이 이 어려움을 악화시킴

  • 하나의 제품 기능을 위해 플랫폼별로 두 세트의 모바일 코드를 개발할 필요 없음: React Native 코드는 거의 크로스플랫폼으로复用할 수 있으나, Airbnb App 에서는 이 부분 코드의 비율이 매우 작고, 게다가 대량의 인프라를 브릿지해야 하므로, 실제 결과는 Android, iOS, React Native 세 개 플랫폼에서 개발해야 함, Native 이중 플랫폼뿐만 아님

  • 개발 경험 향상: 개발 경험은 말하기 어렵고, 컴파일 시간 표현은 좋았으나, 디버깅 경험은 매우 나빴음

이상의种种으로 인해, 숙고 끝에, Airbnb 는 마지막으로 React Native 를 전면 포기하기로 결정:

When we balanced the positives against the pain points plus the current needs and resources of our Engineering organization, we decided that it wasn't right for us anymore.

구체적으로, 2018 년 6 월부터, 모든 기능 이터레이션은 React Native 기술을 고려하지 않으며, 관련 오픈소스 프로젝트도 유지하지 않고, 2018 년 말까지 고트래픽 비즈니스를 모두 Native 로 구현하도록 이전하며, React Native 가 가져오는 성능 부담 (시작 시 초기화 시간 등) 을 점차 제거할 계획

React Native 의啓發을 받은 Native 개발

React Native 의 지속 사용을 포기했으나, 이 2 년 동안, Airbnb 는 몇 가지 Native 에게 매우 가치 있는啓發을 받았습니다:

Today, we have a number of exciting projects in production or in the pipeline. Some of these projects were inspired by the best parts and learnings from our experience with React Native.

예를 들어:

  • Server-Driven Rendering: 동적 업데이트

  • Epoxy Components: 선언적 컴포넌트 정의, 지연 로딩, 가상 DOM 기반 업데이트 메커니즘

  • MvRx: 스레드 모델

  • 컴파일 속도 향상: 모듈화 컴파일

Server-Driven Rendering

서비스 구동의 Native 렌더링 (Server-Driven Rendering):

With these frameworks, the server sends data to the device describing the components to render, the screen configuration, and the actions that can occur. Each mobile platform then interprets this data and renders native screens or even entire flows using DLS components.

동적 업데이트 등 시나리오에서 사용:

Server-driven rendering frameworks have already provided huge value by allowing us to experiment with and update functionality instantly over-the-air.

Epoxy Component

Epoxy 는 Android 와 iOS 를 지원하는 선언적 Native 컴포넌트 방안:

Epoxy is a framework that enables easy heterogeneous RecyclerViews, UICollectionViews, and UITableViews.

그 중에서, React 의 가상 DOM 기반 컴포넌트 업데이트思路를 참고했습니다:

The key to React's performance is that those components are just a data model representation of the actual views/HTML you want to render. The component tree is then diffed and only the changes are dispatched. We built a similar concept for Epoxy.

MvRx

범용 개발 패턴 및 몇 가지 React 사상을 융합하여 형성된 Android 개발 프레임워크, MvRx:

MvRx is an opinionated yet flexible framework that was developed by taking common development patterns that we observed as well as the best parts of React.

컴파일 속도

모듈을 분할하여 컴파일 시간을 단축:

We built infrastructure on Android and iOS to enable you to compile only part of the app that includes a launcher and can depend on specific feature modules.

왜 이렇게 어려운가?

이로써, Airbnb 에서의 React Native 이야기는 종료되었습니다

React Native 에 내기를 거는 것에서, 기술, 팀 조직의 난제에遭遇하고,利弊를 权衡한 후 포기 결정, 마지막으로 전력을 다해 Native 시스템에 투입하고, React Native 의 몇 가지思路를 응용하기까지……왜 이렇게 어려운가? 대기업조차 이 새로운 기술을驾驭할 수 없는가?

객관적으로 말하면, Airbnb 가遭遇한 많은 어려움은 Native 와 React Native 의 혼합 응용에서 비롯된 것 (React Native 를 기존 Native App 에 통합):

We integrated React Native into large existing apps that continued to move at a very fast pace. Many of the difficulties we encountered were due to the hybrid model approach we took.

Facebook 은 2018 년 6 월 이 되어서야 대규모 리팩토링을 통해 혼합 응용 중에 존재하는 다양한 문제를 해결할 것을 계획:

We're working on a large-scale rearchitecture of React Native to make the framework more flexible and integrate better with native infrastructure in hybrid JavaScript/native apps.

이러한 문제 중의 많은 난점은 Airbnb 가 경험하고, 그것들과 끊임없이 투쟁해온 것이다.一些小規模企業과 비교하여, Airbnb 는 더 깊고 멀리까지 갈 능력이 있었으므로, 더 많은 큰 난제에遭遇했습니다:

However, our scale allowed us to take on and solve some difficult problems that smaller companies may not have had time to solve.

초기 신도인 Airbnb 는 포기를 선택했으나, React Native 는 계속 빠르게 발전하며, 날로 성숙해지고 있습니다:

Facebook and the broader React Native community are dedicated to making React Native work for hybrid apps at scale. React Native is progressing faster than ever.

따라서, 많은 다른 기업 (Pinterest, Instagram 등) 에게, React Native 는 여전히 훌륭하거나 최선의 선택입니다

참고 자료

댓글

아직 댓글이 없습니다

댓글 작성