Skip to main content

New Architecture is here

· 47 min read
The React Team
The React Team
@reactjs / @reactnative

React Native 0.76 버전이 이제 npm에서 제공된다. 이번 버전부터는 새로운 아키텍처가 기본으로 적용된다.

0.76 릴리스 블로그 포스트에서는 이번 버전에 포함된 주요 변경 사항을 소개했다. 이번 포스트에서는 새로운 아키텍처에 대한 개요와 이것이 React Native의 미래를 어떻게 바꾸는지 살펴본다.

새로운 아키텍처는 Suspense, Transitions, automatic batching, 그리고 useLayoutEffect와 같은 모던 React 기능을 완벽히 지원한다. 또한 새로운 Native ModuleNative Component 시스템을 도입해 브릿지 없이 네이티브 인터페이스에 직접 접근할 수 있는 타입 안전한 코드를 작성할 수 있게 했다.

이번 릴리스는 2018년부터 진행해온 React Native의 전면 재작성 작업의 결과물이다. 대부분의 앱이 점진적으로 새로운 아키텍처로 마이그레이션할 수 있도록 특별히 신경 썼다. 2021년에는 새로운 아키텍처 워킹 그룹을 만들어 커뮤니티와 협력하며 전체 React 생태계가 원활하게 업그레이드될 수 있도록 노력했다.

대부분의 앱은 React Native 0.76을 다른 릴리스와 동일한 수준의 노력으로 적용할 수 있다. 가장 인기 있는 React Native 라이브러리들은 이미 새로운 아키텍처를 지원한다. 또한 새로운 아키텍처는 이전 아키텍처를 대상으로 한 라이브러리와의 하위 호환성을 가능하게 하는 자동 상호운용성 레이어를 포함한다.

지난 몇 년간 개발 과정에서 우리 팀은 새로운 아키텍처에 대한 비전을 공개적으로 공유해왔다. 이 발표들을 놓쳤다면 아래에서 확인할 수 있다:

새로운 아키텍처란 무엇인가

새로운 아키텍처는 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와 새로운 아키텍처를 성공적으로 사용했다.

우리의 파트너들도 이미 몇 달 동안 새로운 아키텍처를 프로덕션 환경에서 사용하고 있다. ExpensifyKraken의 성공 사례를 확인해보고, 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 플랫폼의 도입을 간소화한다."

Krzysztof Magiera, Reanimated 창시자

이벤트 루프

새로운 아키텍처를 통해 이 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과 유사하게, presschange와 같은 이벤트는 긴급하게 처리되어 즉시 렌더링된다. 입력 이벤트 내부에서 startTransition API를 사용하면 어떤 업데이트가 "트랜지션"인지 React에 알리고, 이를 백그라운드로 연기할 수 있다:

import {startTransition} from 'react';

// 긴급: 슬라이더 값 표시
setCount(input);

// 내부의 상태 업데이트를 트랜지션으로 표시
startTransition(() => {
// 트랜지션: 결과 표시
setNumberOfTiles(input);
});

긴급 이벤트와 트랜지션을 분리하면 더 반응성이 뛰어난 사용자 인터페이스와 직관적인 사용자 경험을 제공할 수 있다.

다음은 트랜지션을 사용하지 않은 기존 아키텍처와 트랜지션을 사용한 새로운 아키텍처를 비교한 내용이다. 각 타일이 단순한 배경색을 가진 뷰가 아니라, 이미지와 렌더링 비용이 높은 다른 컴포넌트를 포함한 복잡한 컴포넌트라고 가정해 보자. useTransition을 사용하면 앱이 업데이트로 인해 지연되거나 뒤처지는 것을 방지할 수 있다.

슬라이더 입력에 따라 많은 뷰(타일)를 렌더링하는 앱을 보여주는 동영상. 슬라이더를 빠르게 0에서 1000으로 조정하면 뷰가 일괄적으로 렌더링된다.
이전: 트랜지션으로 표시하지 않고 타일을 렌더링한 경우.
슬라이더 입력에 따라 많은 뷰(타일)를 렌더링하는 앱을 보여주는 동영상. 슬라이더를 빠르게 0에서 1000으로 조정하면 뷰가 일괄적으로 렌더링된다. 이전 동영상에 비해 일괄 렌더링 횟수가 줄어든다.
이후: 트랜지션을 사용해 오래된 상태의 진행 중인 렌더링을 중단하고 타일을 렌더링한 경우.

자세한 내용은 동시성 렌더러 및 기능 지원을 참고한다.

자동 배칭

새로운 아키텍처로 업그레이드하면 React 18의 자동 배칭 기능을 활용할 수 있다.

자동 배칭은 React가 렌더링 시 더 많은 상태 업데이트를 묶어서 처리하도록 해 중간 상태의 렌더링을 방지한다. 이를 통해 React Native는 개발자의 추가 코드 없이도 더 빠르고 지연 현상에 덜 민감하게 동작할 수 있다.

슬라이더 입력에 따라 많은 뷰를 렌더링하는 앱을 보여주는 동영상. 슬라이더 값을 0에서 1000으로 조정하면 UI가 천천히 1000개의 뷰를 렌더링한다.
이전: 레거시 렌더러로 빈번한 상태 업데이트를 렌더링하는 모습.
슬라이더 입력에 따라 많은 뷰를 렌더링하는 앱을 보여주는 동영상. 슬라이더 값을 0에서 1000으로 조정하면 UI가 이전 예제보다 더 빠르게 1000개의 뷰를 렌더링하며 중간 상태가 적다.
이후: 자동 배칭으로 빈번한 상태 업데이트를 렌더링하는 모습.

기존 아키텍처에서는 더 많은 중간 상태가 렌더링되며, 슬라이더가 멈춘 후에도 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++ 기능, 동기 메서드 호출, 코드 생성기를 통한 타입 안전성 등의 이점을 얻을 수 없다. 네이티브 컴포넌트를 마이그레이션하지 않으면 동시성 기능을 사용할 수 없다. 가능한 한 빨리 모든 네이티브 컴포넌트와 네이티브 모듈을 새로운 아키텍처로 마이그레이션할 것을 권장한다.

note

향후 릴리스에서는 인터페이스가 제거될 예정이며, 모든 모듈이 새로운 아키텍처를 지원해야 한다.

여러분이 앱 개발자라면, 새로운 아키텍처(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-windowsreact-native-macos를 비롯한 여러 개발자 도구에 새로운 아키텍처 구현을 추가한 데 대해.
  • Expensify, Kraken, BlueSky, Brigad: 새로운 아키텍처를 선도적으로 도입하고, 다양한 문제를 보고해 모두를 위해 수정할 수 있게 해준 데 대해.
  • 새로운 아키텍처를 테스트하고, 일부 문제를 수정하며, 명확하지 않은 사항에 대해 질문을 열어 해결할 수 있게 해준 모든 독립 라이브러리 관리자와 개발자들에게.

여러분의 노력과 기여가 없었다면 이 프로젝트는 성공할 수 없었다. 다시 한 번 진심으로 감사드린다.

React Native 0.76 - New Architecture by default, React Native DevTools, and more

· 18 min read
Blake Friedman
Blake Friedman
Software Engineer at Meta
Riccardo Cipolleschi
Riccardo Cipolleschi
Software Engineer at Meta
Frank Calise
Frank Calise
Software Engineer at Infinite Red
Gabriel Donadel Dall'Agnol
Gabriel Donadel Dall'Agnol
Software Engineer at Expo

오늘, 우리는 React Native 0.76을 출시하게 되어 매우 기쁘게 생각한다.

이번 릴리스는 React Native의 주요 이정표다. 기본적으로 새로운 아키텍처를 활성화하고 React Native DevTools를 소개한다. 이는 우리 팀의 6년 간의 노력과 놀라운 개발자 커뮤니티의 지원이 결실을 맺은 결과다.

주요 내용

주요 변경 사항

React Native 0.75 - 레이아웃에서 퍼센트 값 지원, 새로운 아키텍처 안정화, 템플릿 및 init 업데이트 등

· 26 min read
Gabriel Donadel Dall'Agnol
Gabriel Donadel Dall'Agnol
Software Engineer at Expo
Siddharth Kulkarni
Siddharth Kulkarni
Software Engineer at Coinbase
Thibault Malbranche
Thibault Malbranche
Lead Mobile Engineer at Brigad
Blake Friedman
Blake Friedman
Software Engineer at Meta
Riccardo Cipolleschi
Riccardo Cipolleschi
Software Engineer at Meta
Nicola Corti
Nicola Corti
Software Engineer at Meta

오늘, React Native 0.75 버전을 출시하게 되어 기쁘게 생각합니다!

이번 릴리스에서는 % 값을 지원하는 Yoga 3.1, 새로운 아키텍처를 위한 여러 안정화 수정, 그리고 React Native 프레임워크 사용을 권장하는 내용을 포함한 여러 기능을 제공합니다.

주요 내용

주요 변경 사항

React Native 앱 개발을 위한 프레임워크 활용

· 8 min read
Nicola Corti
Nicola Corti
Software Engineer at Meta

React Conf에서 우리는 React Native 앱을 시작하기 위한 최적의 도구에 대한 가이드를 업데이트했다. 바로 React Native 프레임워크다. 이는 프로덕션 준비가 된 앱을 구축하는 데 필요한 모든 API를 제공하는 도구 상자다.

Expo와 같은 React Native 프레임워크를 사용하는 것이 이제 새로운 앱을 만드는 권장 방식이다.

이 블로그 포스트에서는 React Native 프레임워크가 무엇인지, 그리고 새로운 프로젝트를 시작하는 React Native 개발자에게 어떤 의미인지 자세히 설명한다.

React Native 0.74 - Yoga 3.0, Bridgeless New Architecture, and more

· 21 min read
Hur Ali
Hur Ali
Software Engineer at Callstack
Alan Hughes
Alan Hughes
Software Engineer at Expo
Alfonso Curbelo
Alfonso Curbelo
Software Engineer at Coinbase
Alex Hunt
Alex Hunt
Software Engineer at Meta
Nicola Corti
Nicola Corti
Software Engineer at Meta

오늘 React Native 0.74를 출시한다. 이번 릴리스에서는 Yoga 3.0, New Architecture에서 기본으로 적용되는 Bridgeless, New Architecture에서의 onLayout 업데이트 배치 처리, 그리고 새로운 프로젝트의 기본 패키지 매니저로 Yarn 3를 추가했다.

또한, 더 이상 사용되지 않는 API를 제거했다. PropTypes를 제거하고 PushNotificationIOS에 대한 주요 변경 사항을 적용했다. 안드로이드에서는 SDK 23(Android 6.0)이 이제 최소 지원 버전이다.

주요 내용

주요 변경 사항

React Native 0.73 - 디버깅 개선, 안정적인 심볼릭 링크 지원 등

· 20 min read
Marek Fořt
Marek Fořt
Software Engineer at Shopify
Thibault Malbranche
Thibault Malbranche
Lead Mobile Engineer at Brigad
Hur Ali
Hur Ali
Software Engineer at Callstack
Luna Wei
Luna Wei
Software Engineer at Meta
Alex Hunt
Alex Hunt
Software Engineer at Meta

오늘 React Native 0.73을 출시한다. 이번 릴리스에서는 Hermes를 통한 디버깅 개선, 안정적인 심볼릭 링크 지원, Android 14 지원, 그리고 새로운 실험적 기능을 추가했다. 또한 레거시 디버깅 기능을 더 이상 사용하지 않을 예정이며, 새로운 아키텍처의 다음 기둥인 Bridgeless Mode를 선보인다!

주요 내용

주요 변경 사항

React Native 0.72 - 심링크 지원, 개선된 에러 처리 등

· 12 min read
Lorenzo Sciandra
Lorenzo Sciandra
Senior Software Engineer at Microsoft
Marek Fořt
Marek Fořt
Software Engineer at Shopify
Riccardo Cipolleschi
Riccardo Cipolleschi
Software Engineer at Meta
Luna Wei
Luna Wei
Software Engineer at Meta

오늘 0.72 버전을 출시한다!

이번 릴리스에서는 Metro를 위한 많은 요청을 받은 기능들, 더 나은 에러 처리, 그리고 개발자 경험 개선 사항들이 추가되었다. 이 작업의 상당 부분은 2022 커뮤니티 설문조사에서 받은 피드백을 기반으로 우선순위가 정해졌다. 참여해 준 모든 분들께 감사드린다!

주요 내용

주요 변경 사항

React Native에서 패키지 내보내기 지원

· 17 min read
Alex Hunt
Alex Hunt
Software Engineer at Meta

React Native 0.72 버전이 출시되면서, 자바스크립트 빌드 도구인 Metro는 이제 package.json"exports" 필드에 대한 베타 지원을 포함한다. 이 기능을 활성화하면 다음과 같은 기능이 추가된다:

이 글에서는 패키지 익스포트가 어떻게 작동하는지, 그리고 이러한 변경 사항이 React Native 앱 개발자나 패키지 관리자에게 어떤 의미를 가지는지 설명한다.

React Native 0.71-RC0 Android 장애 사후 분석

· 14 min read
Nicola Corti
Nicola Corti
Software Engineer at Meta
Lorenzo Sciandra
Lorenzo Sciandra
Senior Software Engineer at Microsoft

이제 0.71 버전이 공개되었으므로, 2022년 11월 4일 React Native와 Expo의 첫 0.71 릴리스 후보를 출시하면서 발생한 Android 빌드 문제에 대한 주요 정보를 공유하려 한다.

이 문제를 해결하는 데 기여한 개발자들은 최근 사후 분석 회의에 참여해 발생한 일, 이를 통해 배운 점, 그리고 앞으로 유사한 장애를 방지하기 위해 취할 조치에 대해 자세히 논의했다.

React Native 0.71: 기본 타입스크립트 지원, 플렉스 박스 갭 기능 추가 등

· 21 min read
Matt Carroll
Matt Carroll
Developer Advocate at Meta
Nick Gerleman
Nick Gerleman
Software Engineer at Meta
Nicola Corti
Nicola Corti
Software Engineer at Meta
Lorenzo Sciandra
Lorenzo Sciandra
Senior Software Engineer at Microsoft

오늘 React Native 버전 0.71을 출시한다. 이번 버전은 다양한 기능을 포함하고 있다:

이 글에서는 0.71 버전의 주요 기능을 살펴본다.

info

전체 변경 사항은 CHANGELOG.md에서 확인할 수 있다.

타입스크립트 기본 지원

이번 릴리스에서는 React Native의 타입스크립트 경험을 개선했다.

0.71 버전부터 React Native CLI로 새로운 앱을 생성하면 기본적으로 타입스크립트 프로젝트가 만들어진다. 새로운 프로젝트는 tsconfig.json이 미리 설정되어 있어 IDE에서 바로 타입이 지정된 코드를 작성할 수 있다.

또한 react-native 패키지에서 더 정확한 타입스크립트 선언을 내장형으로 제공한다. 이제 @types/react-native가 필요 없으며, 타입 정보는 React Native 릴리스와 동기화되어 업데이트된다.

마지막으로, 모든 예제에 타입스크립트를 적용하도록 문서를 업데이트했다.

note

React Native 0.71로 업그레이드한 후에는 package.jsondevDependencies에서 @types/react-native를 제거하는 것을 권장한다.

이 변경 사항에 대한 자세한 내용은 마이그레이션 단계와 Flow 사용자에게 미치는 영향 등을 포함한 이전 포스트 First-class Support for TypeScript를 참고한다.

플렉스 박스 gap으로 레이아웃 간소화하기

React Native를 사용하면 플렉스 박스를 통해 다양한 화면 크기에 맞춰 컴포넌트를 유연하게 배치할 수 있다. 브라우저에서는 플렉스 박스 속성인 gap, rowGap, columnGap을 지원하며, 이를 통해 플렉스 박스 내 모든 아이템 사이의 간격을 지정할 수 있다.

이 기능은 React Native에서 오랫동안 요청되어 왔으며, 0.71 버전부터 픽셀 값으로 정의된 gap을 초기 지원한다. 향후 버전에서는 퍼센트와 같은 더 다양한 값을 지원할 예정이다.

이 기능의 유용성을 이해하기 위해, 크기가 다양한 카드로 구성된 반응형 레이아웃을 구축하는 상황을 상상해 보자. 각 카드는 부모 컨테이너의 가장자리에 맞닿아 있고, 카드 간 간격은 10px로 설정되어 있다. 이런 레이아웃을 자식 요소의 마진으로 구현하려면 복잡한 과정이 필요하다.

다음은 각 자식 요소에 margin: 10 스타일을 적용한 레이아웃을 보여준다:

두 개의 다이어그램. 왼쪽에는 세 개의 박스가 있으며, 모든 면에 마진이 적용되어 박스 주변에 간격이 생겼다. 오른쪽에는 동일한 다이어그램이 강조�되어 모든 면에 마진이 적용된 것을 보여준다.

마진은 모든 자식 요소의 가장자리에 균일하게 적용되며, 플렉스 박스에서 마진 겹침 현상이 발생하지 않는다. 이로 인해 카드 외부에 간격이 생기고, 내부에는 원하는 간격의 두 배가 생긴다. 이를 해결하기 위해 비균일 마진을 적용하거나, 부모에 음수 마진을 사용하거나, 의도한 간격을 반으로 줄이는 등의 방법을 사용할 수 있지만, 더 간단한 방법이 있다.

플렉스 gap을 사용하면 컨테이너에 gap: 10을 설정하여 카드 내부 간격을 10px로 쉽게 조정할 수 있다:

두 개의 다이어그램. 왼쪽에는 세 개의 박스가 있으며, 플렉스 박스 gap 속성으로 인해 박스의 내부 면에만 마진이 적용되었다. 오른쪽에는 동일한 다이어그램이 강조되어 내부 면에만 마진이 적용된 것을 보여준다.

플렉스 박스 gap에 대한 더 자세한 정보는 CSS Tricks의 블로그 포스트를 참고하라.

웹 표준에서 영감 받은 접근성, 스타일, 이벤트용 프로퍼티

이번 릴리스에서는 웹 표준에서 영감을 받아 React Native의 API를 여러 플랫폼에 맞춰 정렬한 새로운 프로퍼티를 추가했다. 이 새로운 프로퍼티는 순수하게 추가적인 기능이므로, 기존의 접근성, 동작, 스타일 프로퍼티와 관련된 마이그레이션이나 동작 변경은 예상되지 않는다.

새로 도입된 프로퍼티 별칭의 경우, 기존에 다른 이름으로 존재하는 프로퍼티와 함께 지정되면 새로운 별칭 프로퍼티 값이 우선 적용된다. 예를 들어, 이번 릴리스에서는 웹의 src 프로퍼티와 일치시키기 위해 Image 컴포넌트에 source 대신 src 프로퍼티 별칭을 추가했다. srcsource가 모두 제공되면 새로운 src 프로퍼티가 사용된다.

note

React Native를 웹 표준에 맞추는 배경에 대해 더 알고 싶다면, 이 제안관련 논의를 확인해 보자.

접근성

기존 React Native 접근성 프로퍼티에 대한 별칭으로 ARIA 프로퍼티를 도입했다.

이제 모든 React Native 코어 컴포넌트에서 다음 프로퍼티를 사용할 수 있다: aria-label, aria-labelledby, aria-modal, id, aria-busy, aria-checked, aria-disabled, aria-expanded, aria-selected, aria-valuemax, aria-valuemin, aria-valuenow, 그리고 aria-valuetext.

또한 웹과 동일한 동작을 하는 다음 프로퍼티도 추가했다: aria-hidden, aria-live, role, 그리고 tabIndex.

자세한 내용은 이 이슈를 참고한다.

컴포넌트별 동작

핵심 컴포넌트의 prop 이름을 동등한 DOM prop 이름과 일치시키기 위해 몇 가지 새로운 props가 도입되었다.

  • Image: alt, tintColor, crossOrigin, height, referrerPolicy, src, srcSet, width
  • TextInput: autoComplete, enterKeyHint, inputMode, readOnly, rows

자세한 내용은 이 이슈를 참고한다.

스타일

특정 CSS 스타일에 맞추기 위해 다음과 같은 스타일 기능이 확장되었다:

  • aspectRatio는 이제 문자열 값을 지원한다.
  • fontVariant는 이제 공백으로 구분된 문자열 값을 지원한다.
  • fontWeight는 이제 숫자 값을 지원한다.
  • transform는 이제 문자열 값을 지원한다.

기존 React Native 스타일을 대체하기 위해 다음과 같은 별칭이 추가되었다:

자세한 내용은 이 이슈를 참고한다.

이벤트

마지막으로 PointerEvents의 옵트인 구현을 추가했다.

활성화하면 View의 다음 핸들러가 호버를 지원한다:

  • onPointerOver, onPointerOut
  • onPointerEnter, onPointerLeave

이 이벤트는 Pressability에서도 구현되어 새로운 호버 지원을 옵트인할 수 있다.

이 기능을 활성화하려면 다음 플래그를 true로 설정한다:

import ReactNativeFeatureFlags from 'react-native/Libraries/ReactNative/ReactNativeFeatureFlags';

// w3c PointerEvent 구현의 JS 측 활성화
ReactNativeFeatureFlags.shouldEmitW3CPointerEvents = () => true;

// Pressibility에서 PointerEvent 구현을 기반으로 호버 이벤트 활성화
// shouldEmitW3CPointerEvents도 true여야 함
ReactNativeFeatureFlags.shouldPressibilityUseW3CPointerEventsForHover =
() => true;
note

AndroidiOS 네이티브 설정에서 React 기능 플래그도 활성화해야 한다.

자세한 내용은 전용 PointerEvents 포스트를 참고한다.

PropTypes 복원하기

React Native의 ViewPropTypesText.propTypes 같은 PropTypes는 0.66 버전에서 더 이상 사용되지 않게 되었고, 접근할 경우 경고 메시지가 출력되었다. 이후 0.68 버전에서 완전히 제거되면서, 최신 버전으로 업그레이드하는 많은 개발자들이 오류를 경험하기 시작했다.

조사를 통해 우리는 커뮤니티가 경고 메시지에 대해 조치를 취하지 못한 몇 가지 문제를 발견했다. 첫째, 경고 메시지가 항상 명확한 조치를 제시하지 않아 사람들이 이를 무시하는 경우가 많았다(이슈 1, 이슈 2). 둘째, 경고 메시지가 LogBox.ignoreLogs에 의해 잘못 필터링되고 있었다. 이 두 문제는 모두 해결되었지만, 개발자들이 더 많은 시간을 가지고 더 이상 사용되지 않는 코드를 업그레이드할 수 있도록 하기 위해 이번 릴리스에서 React Native의 PropTypes를 다시 추가한다.

이번 업데이트로 인해 개발자들이 코드를 업그레이드하고 PropTypes 사용을 피하기 위해 마이그레이션하는 것이 더 쉬워질 것이다. 또한 deprecated-react-native-prop-types 패키지도 0.71 버전의 모든 props에 맞게 업데이트되었다. 앞으로 우리는 다시 PropTypes를 더 이상 사용되지 않게 만들고 제거할 계획이다. 이번 제거 작업을 다시 진행할 때는 커뮤니티에서 훨씬 적은 문제가 발생할 것으로 예상한다.

caution

이번 변경의 일환으로 LogBox.ignoreLog의 콘솔 필터링 기능도 제거한다. 이는 이전에 Logbox.ignoreLog로 필터링했던 로그들이 업그레이드 후 다시 콘솔에 나타나기 시작한다는 의미이다.

이는 더 이상 사용되지 않는 경고와 같은 로그를 발견하고 수정할 수 있도록 하기 위한 의도된 변경이다.

개발자 경험 개선

React DevTools

이번 릴리스에서는 웹에서 사용하던 두 가지 인기 있는 React DevTools 기능을 React Native로 가져왔다.

"클릭하여 검사하기"는 React DevTools의 왼쪽 상단에 있는 옵션으로, 앱에서 아이템을 클릭하면 DevTools에서 해당 요소를 검사할 수 있다. Chrome의 엘리먼트 검사기와 유사한 기능이다.

컴포넌트 하이라이트는 DevTools에서 선택한 엘리먼트를 앱에서 강조 표시해준다. 이를 통해 화면의 어떤 요소가 어떤 React 컴포넌트와 매칭되는지 쉽게 확인할 수 있다.

다음은 두 기능이 동작하는 모습을 보여주는 예제다:

위에서 설명한 동작을 보여주는 비디오. 왼쪽에는 아이폰 시뮬레이터에서 실행 중인 React Native 앱이 있고, 오른쪽에는 React DevTools가 있다. 두 워크플로우에서 DevTools의 아이템을 클릭하면 앱에서 해당 컴포넌트가 강조 표시된다.

Hermes

React Native 0.70에서 Hermes를 React Native의 기본 엔진으로 설정했다.

React Native 0.71에서는 Hermes에 몇 가지 주목할 만한 개선 사항을 추가했다:

  • 소스 맵 개선: Metro를 통해 네트워크로 소스 맵을 로드함으로써, 최신 버전의 Chrome Dev Tools에서 Flipper 외부에서도 소스 맵을 사용할 수 있는 기능을 복구했다.
  • JSON.parse 성능 개선: 이 버전에서는 JSON.parse의 성능을 최대 30%까지 향상시키는 최적화를 포함했다.
  • .at() 지원 추가: Hermes는 이제 String, TypedArray, Array에 대해 .at()을 지원한다.

전체 변경 사항 목록은 Road to 71 이슈에서 확인할 수 있다.

새로운 아키텍처

이번 릴리스에서는 사용자 피드백과 보고를 바탕으로 실험적인 새로운 아키텍처 경험을 개선했다.

  • 빌드 시간 단축: 새로운 배포 모델은 Maven Central을 사용해 안드로이드에서의 빌드 시간을 크게 줄이고, 윈도우에서 발생하는 여러 빌드 문제를 해결하며, 새로운 아키텍처와 더 원활한 경험을 제공한다. 자세히 알아보기.
  • C++ 코드 작성 최소화: 이제 앱에 C++ 코드를 추가하지 않고도 새로운 아키텍처를 활성화할 수 있다. CLI 앱 템플릿에서 모든 C++ 코드와 CMake 파일을 제거했다. 자세히 알아보기.
  • iOS 앱 설정의 더 나은 캡슐화: iOS에서는 안드로이드와 유사한 접근 방식을 따르고, 새로운 아키텍처 설정 로직 대부분을 RCTAppDelegate 클래스에 캡슐화했다. 이를 통해 향후 업그레이드 시 수동으로 변경해야 할 부분을 줄일 수 있다.
  • iOS에서의 더 나은 의존성 관리: 라이브러리 관리자를 위해 패키지 podspec 내부에서 호출할 수 있는 새로운 install_module_dependencies 함수를 추가했다. 이 함수는 새로운 아키텍처에 필요한 모든 의존성을 설치한다.
  • 버그 수정 및 더 나은 IDE 지원: 사용자들이 새로운 아키텍처 워킹 그룹에서 보고한 여러 버그와 문제(예: 안드로이드에서의 더 나은 IDE 지원)를 해결했다.

새로운 아키텍처는 여전히 실험적인 API 경험이다. 우리는 도입을 더 쉽게 만들기 위해 변경 사항을 반복적으로 개선하고 있다. 새로운 아키텍처 문서에서 간소화된 단계를 시도해 보고, 새로운 아키텍처 워킹 그룹에 피드백을 남겨주길 바란다.

주요 수정 사항

  • 스택 프레임 축소 기능 개선: React Native의 내부 프레임 목록을 업데이트했다. 이제 LogBox가 React Native의 내부 프레임 대신 여러분의 코드를 더 자주 표시한다. 이를 통해 문제를 더 빠르게 디버깅할 수 있다.
  • 빌드 시간 개선: Hermes의 현재 및 새로운 아키텍처에서 iOS와 Android 모두 빌드 시간을 개선하기 위해 assets를 Maven Central로 이전했다.
  • Android 템플릿 개선: Android 템플릿을 대폭 정리했으며, 이제 React Native Gradle Plugin에 완전히 의존한다. 템플릿 내부나 웹사이트의 새로운 전용 페이지에서 설정 방법을 확인할 수 있다.

주요 변경 사항

  • 콘솔 로깅 변경 사항: LogBox.ignoreLog가 더 이상 콘솔 로그를 필터링하지 않는다. 이제 LogBox에서 무시하도록 설정한 로그도 콘솔에 표시된다. 자세한 내용은 이 코멘트를 참고한다.

  • AsyncStorage와 MaskedViewIOS 제거: 이 두 컴포넌트는 0.59 버전부터 더 이상 사용되지 않았으며, 이제 완전히 제거된다. 대체제는 React Native Directory에서 커뮤니티 패키지를 확인한다.

  • JSCRuntime가 react-jsc로 이동: react-jsi가 이제 react-jsc와 react-jsi로 분리된다. JSCRuntime을 사용한다면 react-jsc를 의존성으로 추가해야 한다 (facebook/react-native@6b129d8).

감사의 말

이번 릴리즈는 70명 이상의 기여자가 1000개가 넘는 커밋을 추가한 덕분에 가능했다.

특히 다음과 같은 주요 React Native 프로젝트에 기여한 분들에게 감사의 말을 전한다:

마지막으로, 이번 릴리즈를 완성한 @cortinico, @kelset, @dmytrorykun, @cipolleschi, 그리고 @titozzz에게도 감사드린다!

지금 바로 0.71.0을 사용해 보세요!

React Native CLI 사용자는 기존 프로젝트를 업데이트하거나 npx react-native init MyProject로 새 프로젝트를 생성하는 방법을 업그레이드 문서에서 확인할 수 있습니다.

React Native 버전 0.71은 Expo SDK 버전 48에서 지원됩니다.

info

0.71은 현재 React Native의 최신 안정 버전이며, 0.68.x 버전은 더 이상 지원되지 않습니다. 자세한 내용은 React Native의 지원 정책을 참고하세요.