React Native 0.74 - Yoga 3.0, Bridgeless New Architecture, and more
오늘 React Native 0.74를 출시한다. 이번 릴리스에서는 Yoga 3.0, New Architecture에서 기본으로 적용되는 Bridgeless, New Architecture에서의 onLayout
업데이트 배치 처리, 그리고 새로운 프로젝트의 기본 패키지 매니저로 Yarn 3를 추가했다.
또한, 더 이상 사용되지 않는 API를 제거했다. PropTypes
를 제거하고 PushNotificationIOS
에 대한 주요 변경 사항을 적용했다. 안드로이드에서는 SDK 23(Android 6.0)이 이제 최소 지원 버전이다.
주요 내용
주요 변경 사항
- Android 최소 SDK 버전 업그레이드 (Android 6.0)
- PushNotificationIOS API 변경 (Deprecated)
- 더 이상 사용되지 않는
PropTypes
제거 - Flipper React Native 플러그인 제거
- 기타 주요 변경 사항
주요 내용
Yoga 3.0
새로운 레이아웃 동작
React Native 0.74에는 Yoga 3.0이 포함되어 있다. Yoga 3.0은 스타일링을 더 예측 가능하게 만들어 레이아웃을 개선하며, 웹을 위해 작성된 컴포넌트의 렌더링을 지원한다.
React Native는 여전히 일부 잘못된 레이아웃 동작을 의도적으로 유지한다. 이를 수정하면 실제로 많은 컴포넌트에 영향을 미칠 수 있기 때문이다. 향후 버전에서 레이아웃 준수성을 더 세밀하게 설정할 수 있도록 개선할 예정이다.
React Native는 이전에 row-reverse
컨테이너에 설정된 margin
, padding
, border
를 다룰 때 left
/right
(그리고 start
/end
) 가장자리를 반전시켰다. 이제 이러한 속성의 동작이 웹과 일치한다. 이전에 가장자리가 반전되는 것에 의존하던 코드는 올바르게 렌더링하기 위해 업데이트해야 할 수 있다.
스타일 | 이전 | 이후 |
---|---|---|
|
align-content: 'space-evenly'
지원
Yoga 3.0은 alignContent: 'space-evenly'
를 지원한다. space-evenly
는 다중 행 플렉스 컨테이너에서 행 간의 간격을 균등하게 배치하며, 행과 컨테이너의 가장자리 사이에도 동일한 간격을 적용한다.

position: 'static'
지원
position: 'static'
은 새로운 아키텍처에서만 지원된다.
position: 'static'
으로 표시된 엘리먼트는 오프셋을 적용할 수 없으며, 절대적으로 위치가 지정된 엘리먼트의 포함 블록을 결정할 때 고려되지 않는다. 이를 통해 직접적인 부모가 아닌 조상 엘리먼트를 기준으로 엘리먼트를 위치시킬 수 있다.
|
녹색 <View>
가 left
와 top
을 선언했지만, 부모가 아닌 파란색 <View>
를 기준으로 위치가 지정된 것을 확인할 수 있다.
React Native는 position
이 설정되지 않았을 때 기본적으로 position: 'relative'
를 사용한다.
새로운 아키텍처: 기본적으로 브릿지리스
이번 릴리스에서는 새로운 아키텍처를 활성화할 때 브릿지리스 모드를 기본값으로 설정한다. 브릿지리스로 전환한 배경에 대해 더 알고 싶다면 이 글을 참고하면 된다. 전환 과정을 더 원활하게 만들기 위해 브릿지리스를 지원하는 인터옵 레이어를 개선했고, 여러 라이브러리와 협력해 첫날부터 브릿지리스에서 작동할 수 있도록 준비했다.
브릿지리스만이 아닌, 새로운 렌더러 인터옵 레이어도 개선했다. 가장 흥미로운 점은 이제 기본적으로 활성화된다는 것이다. 특정 컴포넌트를 지정하지 않아도 된다! 더 자세한 내용은 여기에서 확인할 수 있다.
마지막으로, 새로운 아키텍처에 대해 더 알고 싶다면 react-native-new-architecture 저장소에서 문서를 찾을 수 있다. 새로운 아키텍처가 기본값이 되면 이 정보는 reactnative.dev에 통합될 예정이다.
새로운 아키텍처: onLayout
업데이트 일괄 처리
onLayout
콜백에서 발생하는 상태 업데이트가 이제 일괄 처리된다. 이전에는 onLayout
이벤트에서 발생하는 각 상태 업데이트가 새로운 렌더링 커밋을 유발했다.
function MyComponent(props) {
const [state1, setState1] = useState(false);
const [state2, setState2] = useState(false);
return (
<View>
<View
onLayout={() => {
setState1(true);
}}>
<View
onLayout={() => {
// 이 이벤트가 실행될 때, state1의 새로운 값은 여기서 더 이상 관찰할 수 없다.
setState2(true);
}}>
</View>
</View>
);
}
0.74 버전부터 setState1
과 setState2
업데이트가 함께 일괄 처리된다. 이 변경 사항은 React의 예상 동작이며, 리렌더링 횟수를 줄일 수 있다.
이 변경 사항은 일괄 처리되지 않은 상태 업데이트에 의존한 코드를 깨뜨릴 수 있다. 이러한 코드를 리팩토링하려면 업데이터 함수 또는 이에 상응하는 방법을 사용해야 한다.
새 프로젝트를 위한 Yarn 3
Yarn 3은 이제 React Native Community CLI로 초기화된 새 프로젝트의 기본 JavaScript 패키지 관리자로 사용된다.
Yarn 3.x는 React Native 라이브러리와 호환성을 제공하는 nodeLinker: node-modules
모드로 사용된다. 이는 이전 기본값이었던 Yarn Classic(1.x, 지원 중단)을 대체한다. 기존 앱 내에서 Yarn 버전을 업그레이드하려면 이 가이드를 참고하면 된다.
$ yarn --help
━━━ Yarn Package Manager - 3.6.4 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
$ yarn <command>
Community CLI는 --pm
플래그를 통해 다른 패키지 관리자로 프로젝트를 초기화하는 기능도 지원한다(자세히 알아보기).
주요 변경 사항
Android 최소 SDK 버전 업그레이드 (Android 6.0)
React Native 0.74부터는 Android 최소 SDK 버전이 23(Android 6.0)으로 올라갔다. 이전 버전에서는 Android 5.0(API 21)이 최소 요구 사항이었다. 이 변경에 대한 자세한 내용은 여기에서 확인할 수 있다.
보너스: 안드로이드 앱 크기 줄이기
최소 SDK 버전 상향과 네이티브 빌드의 여러 개선 사항 덕분에 사용자 기기에서 앱 크기를 크게 줄일 수 있었다.
예를 들어, React Native 0.74로 새로 만든 앱은 사용자 기기에서 약 13% 적은 공간을 차지하며, 기기에서 약 4MB를 절약한다.
더 이상 사용되지 않는 PropTypes
제거
0.74 이전 버전까지 React Native는 2017년 React 15.5부터 더 이상 사용되지 않는 API인 PropTypes
를 포함하고 있었다. 이제 React Native에서 모든 내장 PropTypes
를 제거해 앱 크기를 줄이고(압축된 번들 기준 26.4kB) 메모리 오버헤드를 줄였다.
다음 PropTypes
속성들이 제거됐다: Image.propTypes
, Text.propTypes
, TextInput.propTypes
, ColorPropType
, EdgeInsetsPropType
, PointPropType
, ViewPropTypes
(커밋 참조).
앱이나 라이브러리가 PropTypes
에 의존한다면 TypeScript와 같은 타입 시스템으로 마이그레이션하는 것을 강력히 권장한다.
PushNotificationIOS API 변경 사항 (Deprecated)
React Native 0.74에서는 더 이상 사용되지 않는 PushNotificationIOS 라이브러리를 제거하기 위한 단계를 진행 중이다. 이번 릴리스에서는 기존 iOS API에 대한 참조를 제거하는 데 중점을 두었다. PushNotificationIOS는 Apple의 User Notifications 프레임워크로 마이그레이션되었으며, 알림을 스케줄링하고 처리하기 위한 새로운 API를 제공한다.
다음 릴리스(0.75)에서는 이 라이브러리를 완전히 제거할 예정이다. React Native 코어에서 제외하고 커뮤니티 패키지인 @react-native-community/push-notification-ios로 이전할 계획이다. 아직 PushNotificationIOS를 사용 중이라면 다음 릴리스 전에 마이그레이션을 완료해야 한다.
API 변경 사항
RCTPushNotificationManager
의 didRegisterUserNotificationSettings:
콜백은 아무 동작도 하지 않아 삭제되었다.
RCTPushNotificationManager
의 다음 콜백은 더 이상 사용되지 않으며 0.75 버전에서 제거될 예정이다:
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification;
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification;
이제 getInitialNotification()
을 사용해 앱을 실행한 알림을 가져오려면 RCTPushNotificationManager
에 initialNotification
을 명시적으로 설정해야 한다:
[RCTPushNotificationManager setInitialNotification:response.notification];
JS 측에서 Notification
의 속성이 변경되었다. alertAction
과 repeatInterval
은 더 이상 사용되지 않으며 0.75 버전에서 제거될 예정이다:
type Notification = {
...
// NEW: 알림을 표시할 때까지의 시간(초).
fireIntervalSeconds?: ?number,
// CHANGED: 알림 스케줄링에만 사용됨. `getScheduledLocalNotifications`나
// `getDeliveredNotifications`로 알림을 가져올 때는 null이 됨.
soundName?: ?string,
// DEPRECATED: iOS의 레거시 UILocalNotification에 사용되었음.
alertAction?: ?string,
// DEPRECATED: `fireDate`나 `fireIntervalSeconds`를 대신 사용.
repeatInterval?: ?string,
};
마지막으로, PushNotificationIOS.removeEventListener
의 handler
매개변수는 사용되지 않아 제거되었다.
💡 마이그레이션 방법
iOS
AppDelegate
는 UNUserNotificationCenterDelegate
를 구현해야 한다. 이 작업은 앱 시작 시 application:willFinishLaunchingWithOptions:
또는 application:didFinishLaunchingWithOptions:
에서 수행한다. (자세한 내용은 Apple Docs 참조)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
return YES;
}
앱이 포그라운드 상태일 때 알림이 도착하면 호출되는 userNotificationCenter:willPresentNotification:withCompletionHandler:
를 구현한다. completionHandler
를 사용해 알림을 사용자에게 표시할지 여부를 결정하고, RCTPushNotificationManager
에 알린다:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
// 이 코드는 PushNotificationIOS에서 'notification' 및 'localNotification' 이벤트를 트리거한다
[RCTPushNotificationManager didReceiveNotification:notification];
// 알림을 사용자에게 표시할지 여부와 방식을 결정한다
completionHandler(UNNotificationPresentationOptionNone);
}
알림을 탭했을 때의 동작을 처리하려면 userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
를 구현한다. 만약 userNotificationCenter:willPresentNotification:withCompletionHandler:
에서 포그라운드 알림을 표시하도록 설정했다면, RCTPushNotificationManager
에 알리는 작업은 이 콜백 중 하나에서만 수행해야 한다.
알림 탭으로 앱이 실행된 경우 setInitialNotification:
을 호출한다. 만약 알림이 userNotificationCenter:willPresentNotification:withCompletionHandler:
에서 처리되지 않았다면 didReceiveNotification:
도 호출한다:
- (void) userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
// 알림 탭으로 앱이 실행된 경우 이 조건이 참이 된다
if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
// getInitialNotification()을 사용해 JS 측에서 알림을 가져올 수 있도록 한다
[RCTPushNotificationManager setInitialNotification:response.notification];
}
// 이 코드는 PushNotificationIOS에서 'notification' 및 'localNotification' 이벤트를 트리거한다
[RCTPushNotificationManager didReceiveNotification:response.notification];
completionHandler();
}
마지막으로, 아래 메서드들을 삭제하고 해당 로직을 위의 콜백으로 옮긴다. 이 콜백들이 대신 호출될 것이다:
application:didReceiveLocalNotification:
[deprecated]application:didReceiveRemoteNotification:
[deprecated]application:didReceiveRemoteNotification:fetchCompletionHandler:
[deprecated되지 않았지만UNUserNotificationCenterDelegate
메서드로 대체됨]
application:didRegisterUserNotificationSettings:
와 RCTPushNotificationManager
의 didRegisterUserNotificationSettings:
사용도 모두 삭제한다.
예제: RNTester의 AppDelegate.mm
참조.
JS
alertAction
에 대한 모든 참조를 제거한다.removeEventListener
호출 시handler
인자를 제거한다.repeatInterval
사용을fireDate
또는fireIntervalSeconds
를 사용하여 여러 알림을 발생시키는 방식으로 대체한다.getScheduledLocalNotifications()
와getDeliveredNotifications()
에서 반환된Notification
에 접근할 때soundName
이 null이 될 수 있음을 유의한다.
Flipper React Native 플러그인 제거
Flipper를 사용해 React Native 레이아웃, 네트워크 요청, 기타 React Native 플러그인 기능을 검사하는 기능은 더 이상 지원되지 않는다. React Native 0.74 버전부터는 새로운 프로젝트에서 Flipper 네이티브 라이브러리와 설정 코드를 제거했다. 이를 통해 의존성이 줄어들고 로컬 설정이 더 빨라졌다. 자세한 내용은 원본 RFC를 참고한다.
앱에서 Flipper를 제거하는 변경 사항은 Upgrade Helper에서 확인할 수 있다. 기존 앱에서 Flipper를 유지하려면 해당 변경 사항을 무시하면 된다.
💡 Flipper 재통합 방법
Flipper는 여전히 Android 또는 iOS 앱 디버깅을 위한 독립적인 도구로 사용할 수 있다. Flipper 문서(Android 가이드, iOS 가이드)를 따라 수동으로 통합할 수 있다.
팀은 Android Studio와 Xcode의 네이티브 디버깅 도구로 전환하는 데 투자하는 것을 권장한다.
Flipper 대체하기
Flipper 기능을 대체할 수 있는 다양한 전용 디버깅 도구가 있다. 더 자세한 내용은 Jamon Holmgren이 작성한 훌륭한 글 React Native 앱에서 Flipper가 필요 없는 이유를 읽어보길 권한다.
JavaScript 디버깅
0.74 버전에서는 Hermes Debugger를 사용하는 것을 권장한다. 또한 Experimental New Debugger를 시도해 볼 수 있다. 이 디버거는 Expo에서 기본으로 제공된다. 현재 이 디버거는 초기 프리뷰 단계로, 알려진 이슈와 업데이트는 여기에서 확인할 수 있다.
주요 변경 사항
일반
- 스타일의
start
/end
가 항상 쓰기 방향을 참조하도록 변경 (#42251).
안드로이드
FabricUIManagerProvider
에서JSIModule*
제거 (#42059).- 이 API는 오픈소스에서 사용되지 않음 — 대신 TurboModules를 사용.
UIManagerModule.showPopupMenu
와UIManagerModule.dismissPopupMenu
를 더 이상 사용하지 않음 (#42441)- 이 API는
@react-native/popup-menu-android
npm 패키지로 이동되었으며, 0.75 버전에서 제거될 예정.
- 이 API는
iOS
- iOS 코드 생성 CLI에서
configFilename
과configKey
인자 제거 (#41533). bundleURL
처리 방식 변경 (#43994).- 이전에는
bundleURL
이 React Native가 시작될 때 인스턴스 변수로 설정되었으며, 이를 업데이트할 수 없었음. - 이제
bundleUrl
은 함수로 변경되어 필요할 때마다 재평가되며, 리프레시 시 다른 URL을 사용할 수 있게 됨. - 이 변경 사항은 앱이 시작된 후
bundleURL
변수를 변경하고 있었다면 영향을 미침. 이 경우, 변수를 업데이트하는 로직을AppDelegate
의bundleURL
함수로 이동해야 함.
- 이전에는
더 자세한 변경 사항은 전체 변경 로그에서 확인할 수 있다.
알려진 문제
iOS
- 여러 윈도우를 사용할 때 발생하는 특이한 케이스: 메인 윈도우가 비활성 상태일 때 시스템이 다이얼로그를 표시하려고 하면, 다이얼로그가 화면의 올바른 위치에 나타나지 않는다. 이 문제는 #44167에서 수정 중이며, 0.74.1 버전에 포함될 예정이다.
감사의 말
React Native 0.74에는 57명의 기여자가 1673개의 커밋을 작성했다. 모두의 노고에 감사드린다!
이번 릴리스 포스트에서 기능 문서화 작업에 참여한 추가 저자들에게도 감사드린다:
- Nick Gerleman - Yoga 3.0
- Joe Vilches - Yoga 3.0
- Riccardo Cipolleschi - New Architecture: Bridgeless by Default
- Samuel Susla - New Architecture: Batched
onLayout
updates - Tim Yung - Removal of Deprecated
PropTypes
- Ingrid Wang - API Changes to PushNotificationIOS (Deprecated)
0.74 버전으로 업그레이드
기존 프로젝트를 React Native 버전 간 코드 변경 사항을 확인하려면 React Native Upgrade Helper를 사용하고, 업그레이드 문서도 참고한다.
새 프로젝트를 생성하려면 다음 명령어를 사용한다:
npx react-native@latest init MyProject
Expo를 사용하는 경우, React Native 0.74는 Expo SDK 51에서 지원된다.
0.74는 현재 React Native의 최신 안정 버전이며, 0.71.x는 더 이상 지원되지 않는다. 자세한 내용은 React Native의 지원 정책을 참고한다. 0.71의 최종 종료 업데이트는 5월 초에 제공할 예정이다.