오늘 React Native 0.77을 출시하게 되어 기쁩니다!
이번 릴리스에는 display: contents, boxSizing, mixBlendMode, outline 관련 속성을 지원하여 더욱 강력한 레이아웃 옵션을 제공하는 등 새로운 스타일링 기능, 최신 Android 디바이스와 호환되도록 Android 16KB 페이지 지원 등 여러 가지 기능이 추가되었습니다. 또한 커뮤니티 템플릿을 Swift로 마이그레이션하여 현대화하는 한편, Objective-C를 선호하는 개발자를 위해 Objective-C와의 호환성을 계속 지원하고 유지해 나가고 있습니다.
React Native 0.77은 React Native를 웹과 일치시키려는 우리의 목표를 더욱 진전시켰습니다. 앱의 레이아웃, 크기 조정 및 블렌딩을 더 잘 제어할 수 있도록 새로운 CSS 속성에 대한 지원이 추가되었습니다. 이러한 변경 사항은 복잡한 레이아웃을 단순화하고, 텍스처를 추가하고, 앱의 접근성을 높이는 데 도움이 될 수 있습니다.
정보
이 모든 새로운 기능은 New Architecture에서만 사용할 수 있습니다.
display: contents 로 더 간단한 레이아웃display: contents 프로퍼티를 사용하면 요소가 레이아웃 구조에서 사라지지만 자식 요소는 여전히 부모 요소의 직접적인 자식인 것처럼 렌더링할 수 있습니다. 레이아웃에 영향을 주지 않고 자식 요소에 스타일을 적용하려는 스타일링 목적, 이벤트를 처리해야 하는 래퍼 컴포넌트를 만들 때 또는 ShadowTree와 상호작용해야 하는 경우에 유용할 수 있습니다.
기술적으로 말하자면, display: contents 는 레이아웃 상자를 생성하지 않고 요소를 렌더링하지만 요소의 하위 요소의 레이아웃 상자는 유지합니다. display: contents 이 있는 요소는 뷰 계층 구조에서 효과적으로 평탄화됩니다.
위젯을 눌렀을 때 알림을 표시하려는 이 예제를 살펴보겠습니다. 컨테이너 뷰 안에 빨간색 위젯이 있습니다.
// Container.jsx
function Container() {
return (
<View style={styles.container}>
<Widget />
</View>
);
}

이제 실험적인 포인터 이벤트를 사용하여 그 아래의 컴포넌트를 눌렀을 때 사용자에게 경고하는 것을 목표로 하는 새로운 Alerting 래퍼 컴포넌트를 만들어 보겠습니다. 명확성을 위해 이 컴포넌트의 배경은 파란색으로 만들었습니다. 아래 컴포넌트와 비슷하게 보일 수 있습니다.
// Container.jsx
function Alerting({children}) {
return (
<View
style={{backgroundColor: 'blue'}}
onPointerDown={() => alert('Hello World!')}>
{children}
</View>
}
function Container() {
return (
<View style={styles.container}>
<Alerting>
<Widget />
</Alerting>
</View>
);
}
이것은 우리가 원하는 대로 작동하지 않습니다. Alerting은 하위 Widget과 별도로 자체 경계를 가진 새 레이아웃 상자를 추가합니다. 래핑하는 요소의 스타일에 따라 시각적 및 기능적으로 상당한 변화가 발생할 수 있습니다. 이 예제에서는 빨간색 "Hello World" 상자만 탭했을 때 경고를 울리도록 하려고 할 때, 파란색 배경은 alert으로 탭에 반응합니다.

이 작업을 다시 시도하면 Alerting의 View 래퍼에 display: contents 를 설정하면서 사용자가 Widget의 원래 범위 내에서 누를 때만 알림이 표시됩니다. 이는 Alerting이 더 이상 자체 상자를 추가하지 않지만 Widget에서 버블링된 포인터 이벤트를 계속 관찰할 수 있기 때문입니다.
// Container.jsx
function Alerting({children}) {
return (
<View
style={{display: 'contents'}}
onPointerDown={() => alert('Hello World!')}>
{children}
</View>
);
}
// ... function Container ...

boxSizing 프로퍼티는 요소의 다양한 크기 조정 프로퍼티(width, height, minWidth, minHeight 등)가 계산되는 방식을 정의합니다. boxSizing 이 border-box 인 경우 이러한 크기는 요소의 테두리 상자에 적용됩니다. content-box 인 경우 요소의 콘텐츠 상자에 적용됩니다. 기본값은 border-box이며, 이는 웹의 기본값과 다릅니다. 이 프로퍼티의 작동 방식에 대해 자세히 알아보려면 웹 문서를 참조하세요.
경고
border-box는 지금까지 기본값으로 사용되어 왔으며,content-box를 추가하기 전까지는 유일한boxSizing값이었습니다. 기본값을 변경하면 여러 레이아웃이 갑자기 깨질 수 있는 breaking change이었을 것입니다. 이전 버전과의 호환성을 보장하기 위해border-box를 기본값으로 유지하기로 결정했습니다.
border-box 와 content-box 의 차이점을 이해하려면 두 View 모두 padding: 20 과 borderWidth: 10 이 있는 다음 예제를 살펴보십시오. border-box 를 사용할 때는 크기 조정에 border와 padding을 고려하고, content-box 를 사용할 때는 content만 고려합니다.

mixBlendMode 프로퍼티를 사용하면 stacking context에서 요소가 다른 요소와 색상을 혼합하는 방식을 제어할 수 있습니다. 각 블렌딩 함수에 대한 전체 개요는 MDN 문서를 확인하세요.
혼합되는 항목을 보다 세밀하게 제어할 수 있도록 isolation 프로퍼티도 추가했습니다. View 에 isolation: isolate 프로퍼티를 설정하면 View 가 강제로 stacking context를 형성합니다. 따라서 일부 상위 View 에 이 프로퍼티를 설정하여 mixBlendMode 가 있는 일부 하위 View 가 isolated View 를 넘어 블렌딩되지 않도록 할 수 있습니다.
mixBlendMode Values
normal: 요소는 블렌딩하지 않고 배경 위에 그려집니다.multiply: 소스 색상에 대상 색상을 곱하여 대상을 대체합니다.screen: 배경 및 소스 색상 값의 보수를 곱한 다음 결과를 보색합니다.overlay: 배경색 값에 따라 색상을 곱하거나 가립니다.darken: 배경색과 소스 색상 중 더 어두운 색상을 선택합니다.lighten: 배경 및 소스 색상 중 더 밝은 색상을 선택합니다.color-dodge: 배경 색상을 밝게 하여 소스 색상을 반영합니다. 검정색으로 칠하면 변화가 없습니다.hard-light: 소스 색상 값에 따라 색상을 곱하거나 스크린합니다. 이 효과는 배경에 강한 스포트라이트를 비추는 것과 유사합니다.soft-light: 소스 색상 값에 따라 색상을 어둡게 또는 밝게 합니다. 이 효과는 배경에 확산 스포트라이트를 비추는 것과 유사합니다.difference: 두 구성 색상 중 밝은 색상에서 어두운 색상을 뺍니다.exclusion: difference 모드와 비슷한 효과를 내지만 대비가 더 낮습니다.hue: 소스 색의 색조와 배경 색의 채도 및 명도를 사용하여 색상을 만듭니다.saturation: 소스 색의 채도와 배경 색의 색조 및 광도를 사용하여 색상을 만듭니다.color: 소스 색상의 색조와 채도 및 배경 색상의 광도를 사용하여 색상을 만듭니다. 이렇게 하면 배경의 회색 레벨이 유지되며 흑백 이미지에 색을 입히거나 컬러 이미지에 색조를 입힐 때 유용합니다.luminosity: 소스 색의 광도와 배경 색의 색조 및 채도를 사용하여 색을 만듭니다. 이렇게 하면 color 모드의 효과와 반대의 효과가 생성됩니다.
또한 outlineWidth, outlineStyle, outlineSpread 및 outlineColor 를 도입했습니다. 이러한 outline 프로퍼티는 각각의 border 프로퍼티와 매우 유사하게 작동하지만 padding box 주변이 아닌 border box 주변에 렌더링됩니다. 이러한 프로퍼티를 사용하면 레이아웃에 영향을 주지 않고 outline을 그려서 요소를 강조할 수 있습니다.
자세한 내용은 MDN 문서를 확인하세요.

이전 릴리스에서 이미 Android 15를 지원하기 위한 몇 가지 작업을 수행했습니다. Android 15의 눈에 띄는 변경 사항 중 하나는 targetSdk 35로 앱을 빌드할 때 강제적인 edge-to-edge 디스플레이입니다.
이를 무시하면 앱의 UI가 손상될 수 있으므로 이를 처리하는 방법에 대한 이전 권장 사항을 참조하시기 바랍니다.
참고
앱에서 react-native-safe-area-context를 사용하는 경우 라이브러리가 이미 강제적인 edge-to-edge를 처리하고 있습니다.
Android 15는 16KB 메모리 페이지 크기를 지원하여 앱 등의 성능을 향상시킬 수 있지만, 이전의 4KB 기반 앱은 향후 기기에서 호환되지 않을 수 있습니다. 현재 개발자가 일부 기기에서 테스트하여 16KB 페이지 크기가 OS 기본값이 될 것에 대비할 수 있는 옵션 기능입니다.
0.77 릴리스에서 React Native는 16KB 페이지 크기를 완벽하게 지원하며, 개발자는 이를 사용하여 16KB 디바이스용 앱을 테스트하고 출시할 수 있습니다.
16KB 지원에 대한 자세한 내용은 공식 Android 개발자 사이트를 참조하세요.
이 버전에서는 React Native 0.75에서 도입된 react-native init 명령어의 지원이 완전히 중단됩니다.
다시 한 번 말씀드리지만, 더 이상 react-native init 명령어를 사용할 수 없게 됩니다.
npx create-expo-appnpx @react-native-community/cli init을 사용하여 커뮤니티 CLI를 직접 호출이 버전에서는 Metro에서 'a' 및 'i' 키보드 단축키를 제거했습니다. 이 단축키는 run-android 및 run-ios 커뮤니티 CLI 명령을 호출하는 데 사용되었습니다. 이러한 키보드 단축키는 개발자 경험을 악화시키고 거의 사용되지 않았습니다. 또한 터미널 출력을 조율하는 데는 프레임워크가 더 적합하다고 생각합니다.
이 변경 사항에 대한 자세한 내용은 이 전용 게시물에서 확인할 수 있습니다.
정보
Expo를 사용하는 프로젝트는 이 변경 사항의 영향을 받지 않습니다.
이 변경을 통해 세 개의 파일(main.m, AppDelegate.h 및 AppDelegate.mm)을 하나의 새로운 AppDelegate.swift로 대체하여 커뮤니티 템플릿을 간소화할 수 있었습니다.
업그레이드 헬퍼에서 다음과 같이 Objective-C에서 Swift로 변경된 것을 확인할 수 있습니다.

Swift로 마이그레이션할 필요가 없습니다. iOS 커뮤니티 템플릿의 Objective-C++ 변형은 계속 지원됩니다(여전히 RCTAppDependencyProvider를 통합해야 함). 새 프로젝트는 iOS 앱 언어로 Swift를 사용하여 생성되지만, 필요한 경우 언제든지 Objective-C로 다시 마이그레이션할 수 있습니다.
제한 사항
앱에 C++로 작성된 일부 로컬 모듈이 있는 경우 이 가이드에 표시된 대로 Swift에 등록할 수 없습니다.
앱이 이 범주에 속하는 경우, AppDelegate를 Swift로 마이그레이션하지 말고 앱에 Objective-C++를 계속 사용하세요.
React Native 코어는 iOS와 Android 및 기타 플랫폼 간의 코드 공유를 장려하기 위해 대부분 C++를 사용하여 개발되었습니다. Swift와 C++ 간의 상호 운용성은 아직 성숙하지도 안정적이지도 않습니다. 이 간극을 메우고 Swift로 마이그레이션할 수 있는 방법을 모색하고 있습니다.
RCTAppDependencyProvider
React Native 0.77에서는 앱이 서드파티 종속성을 로드하는 방식이 약간 변경되었습니다. 이는 커뮤니티 템플릿에 새로 추가된 줄로, 누락될 경우 런타임 문제가 발생할 수 있습니다. 앱에 반드시 추가하세요.
이에 해당하는 Objective-C 라인은 다음과 같습니다.
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
+++ #import <ReactAppDependencyProvider/RCTAppDependencyProvider.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"<Your app Name>";
+++ self.dependencyProvider = [RCTAppDependencyProvider new];
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
// remaining of the AppDelegate
우리는 React Native 디버깅의 모든 측면이 안정적으로 작동하고 최신 브라우저 도구의 기능과 일치하기를 원합니다. 이 품질 기준을 충족하기 위해 원래 0.76에서 더 이상 사용되지 않던 Metro를 통한 로그 전달이 0.77에서 제거되었습니다.
이 통합은 기기에서 디버깅 대상과 통신하기 위해 커스텀 접근 방식에 의존했습니다. 이번 변경으로 Chrome Chrome DevTools Protocol(CDP)로만 전환합니다.
자세한 내용은 JavaScript 로그가 Metro를 떠나는 이유를 참조하세요.
ScrollView에서 고정 헤더의 position이 고려됩니다.ReactFabricInternals 모듈이 제거됩니다.NativeModules 객체를 사용할 수 있습니다.serverBaseUrl을 지정해야 합니다.AppRegistry 에서 useConcurrentRoot 에 대한 타입을 제거했습니다.NativeMethods TypeScript 정의에서 refs 프로퍼티를 제거했습니다.ReadableArray의 Non-primitive getters가 선택 사항으로 올바르게 타입 지정됩니다.ReactHost.createSurface() 메서드를 null로 설정할 수 없습니다.DevSupportManagerBase.getCurrentContext() 를 DevSupportManagerBase.getCurrentReactContext() 로 변경합니다.또한 여러 API가 제거되거나 가시성이 제한되어 더 이상 액세스할 수 없게 되었습니다. 이러한 API는 내부용이며 React Native 개발자가 직접 사용할 필요가 없습니다. 아래에서 전체 목록을 확인할 수 있습니다.
제거된 Android API 목록
다음 패키지는 이제 내부 패키지이며 더 이상 액세스할 수 없습니다.
com.facebook.react.views.progressbarcom.facebook.react.views.safeareaviewcom.facebook.react.modules.accessibilityinfocom.facebook.react.modules.appstatecom.facebook.react.modules.clipboardcom.facebook.react.modules.devmodulecom.facebook.react.modules.reactdevtoolssettingscom.facebook.react.views.unimplementedview다음 클래스는 이제 내부에 있거나 제거되었으므로 더 이상 액세스할 수 없습니다.
BackHandler.removeEventListenerBaseViewManagerInterfaceBindingImplCompositeReactPackageDebugOverlayTagsDefaultDevSupportManagerFactory 의 create() 메서드 DevToolsReactPerfLoggerFabricComponentsImageStoreManagerInteropModuleRegistryNativeModulePerfLoggerNoopPrinterNotThreadSafeViewHierarchyUpdateDebugListenerOkHttpCallUtilPrinterHolderPrinterReactDebugOverlayTagsReactNativeFlipperReactViewBackgroundManagerReactViewGroup.getBackgroundColor()ReactVirtualTextShadowNodeReactVirtualTextViewManagerSimpleSettableFutureSwipeRefreshLayoutManagerTaskCompletionSourcejsBundleLoaderRCTConstants.RCTGetMemoryPressureUnloadLevelpartialBatchDidFlushRCTRuntimeExecutorUseNativeViewConfigsInBridgelessModeUseTurboModuleInteropForAllTurboModulesCGColorRef의 사용을 UIColor로 대체RCTAppDelegate가 RCTDependencyProvider를 사용해야 합니다.React 19?
React 19는 2024년 12월 6일에 출시되었습니다. 그 당시에는 이미 React Native 0.77의 브랜치를 잘라냈고 React Native 0.77의 RC를 세 번이나 릴리스했습니다. 이번 릴리스에서 React 19를 소개하기에는 React Native 0.77 릴리스가 너무 늦었습니다.
React 19는 React Native 0.78에서 제공될 예정이며, 이미 이 버전에 대한 브랜치를 잘라냈습니다. 다음 명령으로 새 앱을 생성하여 사용해 볼 수 있습니다.
npx @react-native-community/cli init YourReact19App --version 0.78.0-rc.0