New Architecture is here
React Native 0.76 버전이 이제 npm에서 제공된다. 이번 버전부터는 새로운 아키텍처가 기본으로 적용된다.
0.76 릴리스 블로그 포스트에서는 이번 버전에 포함된 주요 변경 사항을 소개했다. 이번 포스트에서는 새로운 아키텍처에 대한 개요와 이것이 React Native의 미래를 어떻게 바꾸는지 살펴본다.
새로운 아키텍처는 Suspense, Transitions, automatic batching, 그리고 useLayoutEffect
와 같은 모던 React 기능을 완벽히 지원한다. 또한 새로운 Native Module과 Native Component 시스템을 도입해 브릿지 없이 네이티브 인터페이스에 직접 접근할 수 있는 타입 안전한 코드를 작성할 수 있게 했다.
이번 릴리스는 2018년부터 진행해온 React Native의 전면 재작성 작업의 결과물이다. 대부분의 앱이 점진적으로 새로운 아키텍처로 마이그레이션할 수 있도록 특별히 신경 썼다. 2021년에는 새로운 아키텍처 워킹 그룹을 만들어 커뮤니티와 협력하며 전체 React 생태계가 원활하게 업그레이드될 수 있도록 노력했다.
대부분의 앱은 React Native 0.76을 다른 릴리스와 동일한 수준의 노력으로 적용할 수 있다. 가장 인기 있는 React Native 라이브러리들은 이미 새로운 아키텍처를 지원한다. 또한 새로운 아키텍처는 이전 아키텍처를 대상으로 한 라이브러리와의 하위 호환성을 가능하게 하는 자동 상호운용성 레이어를 포함한다.
지난 몇 년간 개발 과정에서 우리 팀은 새로운 아키텍처에 대한 비전을 공개적으로 공유해왔다. 이 발표들을 놓쳤다면 아래에서 확인할 수 있다:
- React Native EU 2019 - The New React Native
- React Conf 2021 - React 18 Keynote
- App.js 2022 - Bringing the New React Native Architecture to the OSS Community
- React Conf 2024 - Day 2 Keynote
새로운 아키텍처란 무엇인가
새로운 아키텍처는 React Native의 핵심 시스템을 완전히 재구성한 것이다. 여기에는 컴포넌트 렌더링 방식, 자바스크립트 추상화와 네이티브 추상화 간의 통신 방식, 그리고 여러 스레드 간 작업 스케줄링 방식이 포함된다. 대부분의 사용자는 이러한 시스템이 어떻게 동작하는지 깊이 생각할 필요가 없지만, 이번 변경 사항은 다양한 개선과 새로운 기능을 제공한다.
기존 아키텍처에서는 React Native가 비동기 브리지를 통해 네이티브 플랫폼과 통신했다. 컴포넌트를 렌더링하거나 네이티브 함수를 호출하려면 React Native가 네이티브 함수 호출을 직렬화한 후 브리지에 큐로 추가해야 했다. 이 작업은 비동기적으로 처리되었다. 이 아키텍처의 장점은 모든 작업이 백그라운드 스레드에서 이루어지기 때문에 렌더링 업데이트나 네이티브 모듈 함수 호출 시 메인 스레드가 블로킹되지 않는다는 점이었다.
하지만 사용자들은 네이티브 앱처럼 즉각적인 피드백을 기대한다. 즉, 사용자 입력에 대한 일부 업데이트는 동기적으로 렌더링되어야 하며, 진행 중인 렌더링 작업을 중단할 수도 있어야 한다. 기존 아키텍처는 비동기 방식만 지원했기 때문에, 이를 재구성해 비동기와 동기 업데이트를 모두 지원할 필요가 있었다.
또한 기존 아키텍처에서는 브리지를 통해 함수 호출을 직렬화하는 과정이 빠르게 병목 현상이 되었다. 특히 빈번한 업데이트나 큰 객체를 다룰 때 문제가 두드러졌다. 이로 인해 앱이 안정적으로 60 FPS 이상을 달성하기 어려웠다. 동기화 문제도 있었다. 자바스크립트와 네이티브 레이어가 동기화되지 않으면 이를 동기적으로 조정할 수 없어, 리스트가 빈 공간을 표시하거나 중간 상태 렌더링으로 인해 UI가 튀는 등의 버그가 발생했다.
마지막으로, 기존 아키텍처는 네이티브 계층 구조를 사용해 UI의 단일 복사본을 유지하고 이를 직접 뮤테이션했기 때문에 레이아웃을 단일 스레드에서만 계산할 수 있었다. 이로 인해 사용자 입력과 같은 긴급 업데이트를 처리할 수 없었고, 툴팁 위치 업데이트와 같은 레이아웃 효과에서 레이아웃을 동기적으로 읽을 수도 없었다.
이러한 문제들로 인해 React의 동시성 기능을 제대로 지원할 수 없었다. 이를 해결하기 위해 새로운 아키텍처는 다음 네 가지 주요 부분을 포함한다:
- 새로운 네이티브 모듈 시스템
- 새로운 렌더러
- 이벤트 루프
- 브리지 제거
새로운 모듈 시스템은 React Native 렌더러가 네이티브 레이어에 동기적으로 접근할 수 있게 해준다. 이를 통해 이벤트 처리, 업데이트 스케줄링, 레이아웃 읽기를 비동기 및 동기적으로 수행할 수 있다. 새로운 네이티브 모듈은 기본적으로 지연 로딩되므로 앱 성능이 크게 향상된다.
새로운 렌더러는 여러 스레드에서 진행 중인 여러 트리를 처리할 수 있다. 이를 통해 React는 메인 스레드나 백그라운드 스레드에서 여러 동시 업데이트 우선순위를 처리할 수 있다. 또한 더 반응성이 좋은 UI를 지원하기 위해 여러 스레드에서 레이아웃을 동기 또는 비동기적으로 읽을 수 있다.
새로운 이벤트 루프는 자바스크립트 스레드에서 작업을 명확한 순서로 처리할 수 있다. 이를 통해 React는 렌더링을 중단하고 이벤트를 처리할 수 있으므로, 긴급 사용자 이벤트가 낮은 우선순위의 UI 트랜지션보다 우선적으로 처리될 수 있다. 이벤트 루프는 웹 사양과도 일치하므로 마이크로태스크, MutationObserver
, IntersectionObserver
와 같은 브라우저 기능을 지원할 수 있다.
마지막으로, 브리지를 제거하면 시작 속도가 빨라지고 자바스크립트와 네이티브 런타임 간의 직접 통신이 가능해져 작업 전환 비용이 최소화된다. 또한 더 나은 오류 보고, 디버깅, 그리고 정의되지 않은 동작으로 인한 크래시를 줄일 수 있다.
새로운 아키텍처는 이제 프로덕션 환경에서 사용할 준비가 되었다. 이미 Meta의 Facebook 앱과 다른 제품에서 대규모로 사용 중이다. 우리는 Quest 디바이스를 위해 개발한 Facebook과 Instagram 앱에서 React Native와 새로운 아키텍처를 성공적으로 사용했다.
우리의 파트너들도 이미 몇 달 동안 새로운 아키텍처를 프로덕션 환경에서 사용하고 있다. Expensify와 Kraken의 성공 사례를 확인해보고, BlueSky의 새로운 릴리즈도 사용해보길 권한다.
새로운 네이티브 모듈 시스템
새로운 네이티브 모듈 시스템은 자바스크립트와 네이티브 플랫폼 간의 통신 방식을 완전히 재구성한 것이다. 이 시스템은 C++로 작성되어 여러 새로운 기능을 제공한다:
- 네이티브 런타임과의 동기식 접근
- 자바스크립트와 네이티브 코드 간의 타입 안전성
- 플랫폼 간 코드 공유
- 기본적으로 지연된 모듈 로딩
새로운 네이티브 모듈 시스템에서는 자바스크립트와 네이티브 레이어가 JavaScript Interface(JSI)를 통해 동기적으로 통신할 수 있다. 더 이상 비동기 브리지를 사용할 필요가 없다. 이제 커스텀 네이티브 모듈은 동기적으로 함수를 호출하고 값을 반환한 후, 그 값을 다른 네이티브 모듈 함수로 전달할 수 있다.
기존 아키텍처에서는 네이티브 함수 호출에 대한 응답을 처리하기 위해 콜백을 제공해야 했고, 반환된 값은 직렬화 가능해야 했다:
// ❌ 네이티브 모듈에서 동기식 콜백
nativeModule.getValue(value => {
// ❌ value는 네이티브 객체를 참조할 수 없음
nativeModule.doSomething(value);
});
새 아키텍처에서는 네이티브 함수에 동기적으로 호출할 수 있다:
// ✅ 네이티브 모듈에서 동기식 응답
const value = nativeModule.getValue();
// ✅ value는 네이티브 객체를 참조할 수 있음
nativeModule.doSomething(value);
새 아키텍처를 통해 C++ 네이티브 구현의 모든 기능을 활용할 수 있으며, 여전히 자바스크립트/타입스크립트 API에서 접근할 수 있다. 새로운 모듈 시스템은 C++로 작성된 모듈을 지원하므로, 한 번 작성한 모듈이 Android, iOS, Windows, macOS 등 모든 플랫폼에서 동작한다. C++로 모듈을 구현하면 더 세밀한 메모리 관리와 성능 최적화가 가능하다.
또한 Codegen을 사용하면 자바스크립트 레이어와 네이티브 레이어 간에 강력한 타입 계약을 정의할 수 있다. 크로스 플랫폼 앱에서 크로스 바운더리 타입 오류는 가장 흔한 크래시 원인 중 하나다. Codegen은 이러한 문제를 해결할 뿐만 아니라 보일러플레이트 코드도 자동으로 생성한다.
마지막으로, 모듈은 이제 지연 로딩된다. 모듈은 앱 시작 시가 아니라 실제로 필요할 때 메모리에 로드된다. 이를 통해 앱 시작 시간을 줄이고, 앱이 복잡해져도 시작 시간을 낮게 유지할 수 있다.
react-native-mmkv와 같은 인기 라이브러리는 이미 새로운 네이티브 모듈로 마이그레이션해 혜택을 보고 있다:
"새로운 네이티브 모듈은
react-native-mmkv
의 설정, 자동 연결, 초기화를 크게 단순화했습니다. 새로운 아키텍처 덕분에react-native-mmkv
는 이제 순수 C++ 네이티브 모듈로, 모든 플랫폼에서 동작합니다. 새로운 Codegen은 MMKV를 완전히 타입 안전하게 만들어,NullPointerReference
문제를 해결했고, 네이티브 모듈 함수를 동기적으로 호출할 수 있어 커스텀 JSI 접근을 새로운 네이티브 모듈 API로 대체할 수 있었습니다."Marc Rousavy,
react-native-mmkv
창시자
새로운 렌더러
네이티브 렌더러도 완전히 재작성했으며, 이를 통해 여러 이점을 얻었다:
- 업데이트를 다른 스레드에서 다른 우선순위로 렌더링할 수 있다.
- 레이아웃을 동기적으로 읽을 수 있으며, 다른 스레드에서도 접근 가능하다.
- 렌더러는 C++로 작성되었고 모든 플랫폼에서 공유된다.
업데이트된 네이티브 렌더러는 이제 뷰 계층 구조를 불변의 트리 구조로 저장한다. 이는 UI가 직접 변경될 수 없는 방식으로 저장됨을 의미하며, 스레드 안전한 업데이트 처리를 가능하게 한다. 이를 통해 여러 진행 중인 트리를 처리할 수 있으며, 각 트리는 사용자 인터페이스의 다른 버전을 나타낸다. 결과적으로, UI를 블로킹하지 않고 백그라운드에서 업데이트를 렌더링할 수 있다(예: 트랜지션 중) 또는 메인 스레드에서 렌더링할 수 있다(예: 사용자 입력에 대한 응답).
다중 스레드를 지원함으로써, React는 낮은 우선순위의 업데이트를 중단하고 사용자 입력에 의해 생성된 긴급 업데이트를 렌더링한 후, 필요에 따라 낮은 우선순위 업데이트를 재개할 수 있다. 새로운 렌더러는 또한 레이아웃 정보를 동기적으로 읽을 수 있으며, 다른 스레드에서도 접근 가능하다. 이를 통해 낮은 우선순위 업데이트에 대한 백그라운드 계산이 가능하고, 필요할 때 동기적으로 읽을 수 있다(예: 툴팁 위치 조정).
마지막으로, 렌더러를 C++로 재작성함으로써 모든 플랫폼에서 공유할 수 있게 되었다. 이는 iOS, Android, Windows, macOS 및 기타 React Native 지원 플랫폼에서 동일한 코드가 실행되도록 보장하며, 각 플랫폼별로 재구현할 필요 없이 일관된 렌더링 기능을 제공한다.
이는 다양한 플랫폼 비전을 향한 중요한 단계이다. 예를 들어, View Flattening은 깊은 레이아웃 트리를 피하기 위한 Android 전용 최적화였다. 새로운 렌더러는 공유된 C++ 코어를 통해 이 기능을 iOS로 가져왔다. 이 최적화는 자동으로 이루어지며 설정이 필요 없고, 공유 렌더러와 함께 무료로 제공된다.
이러한 변경 사항을 통해 React Native는 이제 Suspense와 Transitions와 같은 Concurrent React 기능을 완전히 지원하며, 사용자 입력에 빠르게 반응하는 복잡한 사용자 인터페이스를 더 쉽게 구축할 수 있다. 앞으로 이러한 새로운 기능을 활용해 FlatList와 TextInput과 같은 내장 컴포넌트에 더 많은 개선 사항을 적용할 계획이다.
Reanimated와 같은 인기 라이브러리는 이미 새로운 렌더러를 활용하고 있다:
"개발 중인 Reanimated 4는 새로운 애니메이션 엔진을 도입했으며, 이 엔진은 새로운 렌더러와 직접 작동하여 애니메이션을 처리하고 다른 스레드에서 레이아웃을 관리할 수 있다. 새로운 렌더러의 설계는 이러한 기능을 수많은 우회 방법 없이 구축할 수 있게 해준다. 또한, C++로 구현되고 플랫폼 간에 공유되기 때문에 Reanimated의 많은 부분을 한 번만 작성할 수 있어 플랫폼별 문제를 줄이고 코드베이스를 최소화하며, out-of-tree 플랫폼의 도입을 간소화한다."
이벤트 루프
새로운 아키텍처를 통해 이 RFC에 설명된 대로 명확히 정의된 이벤트 루프 처리 모델을 구현할 수 있었다. 이 RFC는 HTML 표준에 명시된 사양을 따르며, React Native가 JavaScript 스레드에서 작업을 어떻게 수행해야 하는지 설명한다.
명확히 정의된 이벤트 루프를 구현함으로써 React DOM과 React Native 간의 차이를 줄일 수 있었다. 이제 React Native 애플리케이션의 동작이 React DOM 애플리케이션의 동작에 더 가까워져, 한 번 배우고 어디서든 작성하기 쉬워졌다.
이벤트 루프는 React Native에 다음과 같은 이점을 제공한다:
- 렌더링을 중단하고 이벤트와 작업을 처리할 수 있는 기능
- 웹 표준과의 더 밀접한 일치
- 더 많은 브라우저 기능을 위한 기반
이벤트 루프를 통해 React는 업데이트와 이벤트를 예측 가능하게 정렬할 수 있다. 이를 통해 React는 긴급한 사용자 이벤트로 낮은 우선순위의 업데이트를 중단할 수 있으며, 새로운 렌더러는 이러한 업데이트를 독립적으로 렌더링할 수 있게 해준다.
또한 이벤트 루프는 타이머와 같은 이벤트 및 작업의 동작을 웹 표준과 일치시켜 React Native가 웹에서 사용자가 익숙한 방식으로 더 잘 작동하게 하고, React DOM과 React Native 간의 코드 공유를 더 용이하게 한다.
또한 마이크로태스크, MutationObserver
, IntersectionObserver
와 같은 더 준수하는 브라우저 기능을 구현할 수 있게 해준다. 이러한 기능은 아직 React Native에서 사용할 준비가 되지 않았지만, 앞으로 이를 제공하기 위해 노력하고 있다.
마지막으로, 이벤트 루프와 새로운 렌더러 변경 사항은 레이아웃을 동기적으로 읽는 것을 지원하여 React Native가 useLayoutEffect
를 통해 레이아웃 정보를 동기적으로 읽고 동일한 프레임에서 UI를 업데이트할 수 있도록 한다. 이를 통해 사용자에게 요소를 표시하기 전에 올바르게 위치를 지정할 수 있다.
자세한 내용은 useLayoutEffect
를 참고한다.
브릿지 제거
새로운 아키텍처에서는 React Native가 브릿지에 의존하지 않도록 완전히 제거했다. 대신 JSI(JavaScript Interface)를 사용해 JavaScript와 네이티브 코드 간의 직접적이고 효율적인 통신을 구현했다.
브릿지를 제거하면 브릿지 초기화 과정을 건너뛰어 앱 시작 시간을 단축할 수 있다. 예를 들어, 기존 아키텍처에서는 JavaScript에 전역 메서드를 제공하기 위해 시작 시 JavaScript 모듈을 초기화해야 했고, 이로 인해 앱 시작 시간이 약간 지연되었다.
// ❌ 느린 초기화
import {NativeTimingModule} from 'NativeTimingModule';
global.setTimeout = timer => {
NativeTimingModule.setTimeout(timer);
};
// App.js
setTimeout(() => {}, 100);
새로운 아키텍처에서는 C++에서 직접 메서드를 바인딩할 수 있다.
// ✅ C++에서 직접 초기화
runtime.global().setProperty(runtime, "setTimeout", createTimer);
// App.js
setTimeout(() => {}, 100);
이러한 개선은 특히 시작 시 발생하는 JavaScript 크래시에 대한 오류 보고를 더욱 정확하게 만들고, 정의되지 않은 동작으로 인한 크래시를 줄인다. 크래시가 발생할 경우, 새로운 React Native DevTools를 통해 디버깅이 간소화되며 새로운 아키텍처를 지원한다.
브릿지는 이전 버전과의 호환성을 위해 남겨두었으며, 점진적으로 새로운 아키텍처로 전환할 수 있도록 한다. 앞으로 브릿지 코드는 완전히 제거될 예정이다.
점진적 마이그레이션
대부분의 앱은 다른 릴리스와 동일한 노력으로 0.76 버전으로 업그레이드할 수 있다.
0.76으로 업그레이드하면 새로운 아키텍처와 React 18이 기본적으로 활성화된다. 하지만 동시성 기능을 사용하고 새로운 아키텍처의 모든 이점을 얻으려면 앱과 라이브러리가 새로운 아키텍처를 완전히 지원하도록 점진적으로 마이그레이션해야 한다.
처음 업그레이드할 때 앱은 새로운 아키텍처에서 실행되며, 이전 아키텍처와의 자동 호환성 레이어가 적용된다. 대부분의 앱은 변경 없이 작동하지만, 알려진 제한 사항이 있다. 호환성 레이어는 커스텀 Shadow Node나 동시성 기능에 접근하는 것을 지원하지 않는다.
동시성 기능을 사용하려면 앱이 Concurrent React를 지원하도록 업데이트해야 한다. 이를 위해 React의 규칙을 따라야 한다. JavaScript 코드를 React 18과 그 의미론에 맞게 마이그레이션하려면 React 18 업그레이드 가이드를 참고한다.
전체 전략은 기존 코드를 깨뜨리지 않고 새로운 아키텍처에서 앱을 실행하는 것이다. 그런 다음 자신의 속도에 맞춰 앱을 점진적으로 마이그레이션할 수 있다. 모든 모듈이 새로운 아키텍처로 마이그레이션된 새로운 부분에서는 즉시 동시성 기능을 사용할 수 있다. 기존 부분에서는 몇 가지 문제를 해결하고 모듈을 마이그레이션한 후 동시성 기능을 추가해야 할 수 있다.
가장 인기 있는 React Native 라이브러리와 협력하여 새로운 아키텍처를 지원하도록 했다. 주간 다운로드 수가 20만 회 이상인 모든 라이브러리(약 10%)를 포함해 850개 이상의 라이브러리가 이미 호환된다. reactnative.directory 웹사이트에서 라이브러리의 호환성을 확인할 수 있다:
업그레이드에 대한 자세한 내용은 아래 업그레이드 방법을 참고한다.
새로운 기능
새로운 아키텍처는 React 18, 동시성 기능, 그리고 React Native의 useLayoutEffect
를 완벽하게 지원한다. React 18의 전체 기능 목록은 React 18 블로그 포스트를 참고하면 된다.
트랜지션
트랜지션은 React 18에서 도입된 새로운 개념으로, 긴급 업데이트와 비긴급 업데이트를 구분한다.
- 긴급 업데이트는 타이핑이나 클릭과 같은 직접적인 상호작용을 반영한다.
- 트랜지션 업데이트는 UI를 한 화면에서 다른 화면으로 전환한다.
긴급 업데이트는 물리적 객체의 동작에 대한 직관과 일치하도록 즉각적인 응답이 필요하다. 반면, 트랜지션은 사용자가 화면에 모든 중간 값을 볼 것으로 기대하지 않기 때문에 다르게 처리된다. 새로운 아키텍처에서 React Native는 긴급 업데이트와 트랜지션 업데이트를 별도로 렌더링할 수 있다.
일반적으로 최상의 사용자 경험을 위해, 단일 사용자 입력은 긴급 업데이트와 비긴급 업데이트를 모두 발생시켜야 한다. ReactDOM과 유사하게, press
나 change
와 같은 이벤트는 긴급하게 처리되어 즉시 렌더링된다. 입력 이벤트 내부에서 startTransition
API를 사용하면 어떤 업데이트가 "트랜지션"인지 React에 알리고, 이를 백그라운드로 연기할 수 있다:
import {startTransition} from 'react';
// 긴급: 슬라이더 값 표시
setCount(input);
// 내부의 상태 업데이트를 트랜지션으로 표시
startTransition(() => {
// 트랜지션: 결과 표시
setNumberOfTiles(input);
});
긴급 이벤트와 트랜지션을 분리하면 더 반응성이 뛰어난 사용자 인터페이스와 직관적인 사용자 경험을 제공할 수 있다.
다음은 트랜지션을 사용하지 않은 기존 아키텍처와 트랜지션을 사용한 새로운 아키텍처를 비교한 내용이다. 각 타일이 단순한 배경색을 가진 뷰가 아니라, 이미지와 렌더링 비용이 높은 다른 컴포넌트를 포함한 복잡한 컴포넌트라고 가정해 보자. useTransition
을 사용하면 앱이 업데이트로 인해 지연되거나 뒤처지는 것을 방지할 수 있다.


자세한 내용은 동시성 렌더러 및 기능 지원을 참고한다.
자동 배칭
새로운 아키텍처로 업그레이드하면 React 18의 자동 배칭 기능을 활용할 수 있다.
자동 배칭은 React가 렌더링 시 더 많은 상태 업데이트를 묶어서 처리하도록 해 중간 상태의 렌더링을 방지한다. 이를 통해 React Native는 개발자의 추가 코드 없이도 더 빠르고 지연 현상에 덜 민감하게 동작할 수 있다.


기존 아키텍처에서는 더 많은 중간 상태가 렌더링되며, 슬라이더가 멈춘 후에도 UI가 계속 업데이트된다. 새로운 아키텍처는 자동으로 업데이트를 묶어 처리함으로써 중간 상태를 줄이고 렌더링을 더 빨리 완료한다.
자세한 내용은 동시성 렌더러 및 기능 지원을 참고한다.
useLayoutEffect
이벤트 루프와 동기적으로 레이아웃을 읽는 기능을 기반으로, 새로운 아키텍처에서는 React Native에서 useLayoutEffect
를 제대로 지원한다.
이전 아키텍처에서는 뷰의 레이아웃 정보를 읽기 위해 비동기 onLayout
이벤트를 사용해야 했다. 이로 인해 레이아웃이 읽히고 업데이트되기 전까지 최소 한 프레임 동안 레이아웃이 잘못 표시되는 문제가 발생했다. 예를 들어 툴팁이 잘못된 위치에 배치되는 등의 문제가 있었다.
// ❌ 커밋 후 비동기 onLayout
const onLayout = React.useCallback(event => {
// ❌ 레이아웃을 읽기 위한 비동기 콜백
ref.current?.measureInWindow((x, y, width, height) => {
setPosition({x, y, width, height});
});
}, []);
// ...
<ViewWithTooltip
onLayout={onLayout}
ref={ref}
position={position}
/>;
새로운 아키텍처는 useLayoutEffect
에서 동기적으로 레이아웃 정보에 접근할 수 있도록 이 문제를 해결한다.
// ✅ 커밋 중 동기 레이아웃 이펙트
useLayoutEffect(() => {
// ✅ 레이아웃을 읽기 위한 동기 호출
const rect = ref.current?.getBoundingClientRect();
setPosition(rect);
}, []);
// ...
<ViewWithTooltip ref={ref} position={position} />;
이 변경으로 인해 동기적으로 레이아웃 정보를 읽고 같은 프레임 내에서 UI를 업데이트할 수 있다. 따라서 사용자에게 요소가 표시되기 전에 정확한 위치에 배치할 수 있다.

onLayout
에서 비동기적으로 레이아웃을 읽어 툴팁의 위치가 지연되었다.
useLayoutEffect
에서 동기적으로 레이아웃을 읽어 툴팁의 위치를 표시하기 전에 업데이트한다.더 자세한 정보는 동기 레이아웃과 이펙트 문서를 참고한다.
Suspense 완전 지원
Suspense는 아직 표시할 준비가 되지 않은 컴포넌트 트리의 일부에 대해 로딩 상태를 선언적으로 지정할 수 있게 한다:
<Suspense fallback={<Spinner />}>
<Comments />
</Suspense>
몇 년 전에 제한된 버전의 Suspense를 소개했고, React 18에서 완전한 지원이 추가되었다. 지금까지 React Native는 Suspense에 대한 동시성 렌더링을 지원하지 못했다.
새 아키텍처는 React 18에서 도입된 Suspense의 완전한 지원을 포함한다. 이제 React Native에서 Suspense를 사용해 컴포넌트의 로딩 상태를 처리할 수 있으며, 로딩 상태가 표시되는 동안 일시 중단된 콘텐츠를 백그라운드에서 렌더링할 수 있다. 이를 통해 사용자 입력이 화면에 보이는 콘텐츠에 더 높은 우선순위를 가질 수 있다.
자세한 내용은 React 18의 Suspense RFC를 참고한다.
업그레이드 방법
0.76 버전으로 업그레이드하려면 릴리스 포스트에 나온 단계를 따르면 된다. 이번 릴리스는 React 18로도 업그레이드되므로, React 18 업그레이드 가이드도 함께 참고해야 한다.
구조와의 호환성을 위한 인터페이스 덕분에 대부분의 앱은 이 단계만으로도 새로운 아키텍처로 업그레이드할 수 있다. 하지만 새로운 아키텍처의 모든 기능을 활용하고 동시성 기능을 사용하려면 커스텀 네이티브 모듈과 네이티브 컴포넌트를 새로운 네이티브 모듈 및 네이티브 컴포넌트 API를 지원하도록 마이그레이션해야 한다.
커스텀 네이티브 모듈을 마이그레이션하지 않으면 공유 C++ 기능, 동기 메서드 호출, 코드 생성기를 통한 타입 안전성 등의 이점을 얻을 수 없다. 네이티브 컴포넌트를 마이그레이션하지 않으면 동시성 기능을 사용할 수 없다. 가능한 한 빨리 모든 네이티브 컴포넌트와 네이티브 모듈을 새로운 아키텍처로 마이그레이션할 것을 권장한다.
향후 릴리스에서는 인터페이스가 제거될 예정이며, 모든 모듈이 새로운 아키텍처를 지원해야 한다.
앱
여러분이 앱 개발자라면, 새로운 아키텍처(New Architecture)를 완벽하게 지원하려면 라이브러리, 커스텀 네이티브 컴포넌트, 그리고 커스텀 네이티브 모듈을 업그레이드해야 한다.
우리는 가장 인기 있는 React Native 라이브러리와 협력하여 새로운 아키텍처를 지원할 수 있도록 했다. reactnative.directory 웹사이트에서 라이브러리 호환성을 확인할 수 있다.
만약 앱이 의존하는 라이브러리가 아직 호환되지 않는다면, 다음 방법을 고려해 볼 수 있다:
- 해당 라이브러리에 이슈를 열고 작성자에게 새로운 아키텍처로 마이그레이션을 요청한다.
- 라이브러리가 더 이상 유지되지 않는다면, 동일한 기능을 제공하는 대체 라이브러리를 고려한다.
- 해당 라이브러리가 마이그레이션되는 동안 새로운 아키텍처에서 옵트아웃한다.
앱에 커스텀 네이티브 모듈이나 커스텀 네이티브 컴포넌트가 있다면, 상호 운용성 레이어 덕분에 문제없이 동작할 것이다. 하지만 새로운 네이티브 모듈과 네이티브 컴포넌트 API로 업그레이드하여 새로운 아키텍처를 완전히 지원하고 동시성 기능을 도입하는 것을 권장한다.
다음 가이드를 따라 모듈과 컴포넌트를 새로운 아키텍처로 마이그레이션할 수 있다:
라이브러리 관리자를 위한 안내
라이브러리 관리자라면, 먼저 라이브러리가 인터옵 레이어와 호환되는지 테스트해야 한다. 호환되지 않는다면 New Architecture Working Group에 이슈를 등록한다.
새 아키텍처를 완전히 지원하려면, 가능한 한 빨리 라이브러리를 새로운 Native Module과 Native Component API로 마이그레이션하는 것을 권장한다. 이를 통해 사용자가 새 아키텍처의 모든 기능을 활용하고 동시성 기능을 지원할 수 있다.
다음 가이드를 참고해 모듈과 컴포넌트를 새 아키텍처로 마이그레이션할 수 있다:
옵트아웃
어떤 이유로든 새로운 아키텍처가 애플리케이션에서 제대로 동작하지 않는다면, 다시 활성화할 준비가 될 때까지 옵트아웃할 수 있다.
새로운 아키텍처에서 옵트아웃하려면:
- 안드로이드에서는
android/gradle.properties
파일을 수정하고newArchEnabled
플래그를 비활성화한다.
-newArchEnabled=true
+newArchEnabled=false
- iOS에서는 다음 커맨드를 실행해 의존성을 재설치한다:
RCT_NEW_ARCH_ENABLED=0 bundle exec pod install
감사의 말
새로운 아키텍처를 OSS 커뮤니티에 전달하기 위해 수년에 걸친 연구와 개발이 필요했다. 이 결과를 이루는 데 도움을 준 React 팀의 현재와 과거 멤버들에게 깊은 감사를 표한다.
또한 이 프로젝트를 가능하게 해준 모든 파트너들에게도 큰 감사를 드린다. 특히 다음과 같은 기업과 개인에게 특별한 감사를 전한다:
- Expo: 새로운 아키텍처를 초기에 도입하고, 가장 인기 있는 라이브러리 마이그레이션 작업을 지원해준 데 대해.
- Software Mansion: 생태계에서 중요한 라이브러리를 유지보수하고, 초기에 새로운 아키텍처로 마이그레이션하며, 다양한 문제를 조사하고 수정하는 데 도움을 준 데 대해.
- Callstack: 생태계에서 중요한 라이브러리를 유지보수하고, 초기에 새로운 아키텍처로 마이그레이션하며, Community CLI 작업을 지원해준 데 대해.
- Microsoft:
react-native-windows
와react-native-macos
를 비롯한 여러 개발자 도구에 새로운 아키텍처 구현을 추가한 데 대해. - Expensify, Kraken, BlueSky, Brigad: 새로운 아키텍처를 선도적으로 도입하고, 다양한 문제를 보고해 모두를 위해 수정할 수 있게 해준 데 대해.
- 새로운 아키텍처를 테스트하고, 일부 문제를 수정하며, 명확하지 않은 사항에 대해 질문을 열어 해결할 수 있게 해준 모든 독립 라이브러리 관리자와 개발자들에게.
여러분의 노력과 기여가 없었다면 이 프로젝트는 성공할 수 없었다. 다시 한 번 진심으로 감사드린다.