원문: React Native 0.87 - Strict TypeScript API, Metro Update, Swift Package Manager, AGP 9 Support
블로그 번역은 최초 발표 당시의 설명을 보존합니다. 본문의 “최신 버전”, 지원 상태, 출시 예정 안내도 발표 당시 기준입니다.
0.87.x 패치 내역을 별도로 정리했습니다. 확인한 가장 최근 정식 패치는 0.87.1입니다.
오늘 React Native 0.87을 릴리스하게 되어 기쁩니다!
이번 릴리스에서는 Strict TypeScript API가 기본 JavaScript API가 되고, Metro가 0.87로 올라가며, Swift Package Manager(SwiftPM) 실험 지원이 추가됩니다. 또한 최소 툴체인 요구사항이 올라갑니다 — Node.js 22, Android Gradle Plugin 9, Kotlin 2.0+.
React Native의 공개 JavaScript API가 이제 Strict TypeScript API가 됩니다. 0.80에서 deep import의 deprecation과 함께 opt-in 프리뷰로 처음 제공되었고, 0.87부터 모든 프로젝트의 기본값이 됩니다.
생태계 전반에 걸친 변화이며, API 표면 전체에 의도된 호환성 깨짐을 동반합니다. 그 대가로 얻는 것은 다음과 같습니다.
react-native가 루트에서 export하는 것으로 한정되며, 내부 파일 변경이 더 이상 여러분의 breaking change가 되지 않습니다. 0.87부터 React Native의 JS API는 의도했을 때만 바뀝니다.새 타입이 실제로 어떻게 보이는지 — TextInput 컴포넌트에 마우스를 올렸을 때입니다.
이제 대부분의 심볼에 문서 주석이 포함되어, 호버만으로 훨씬 많은 정보를 한눈에 확인할 수 있습니다.
react-native/Libraries/*)는 이제 타입 에러이며, 마이그레이션이 필요합니다.ViewInstance, TextInputInstance) — 문서.0.80 프리뷰 이후 커뮤니티·파트너들과 함께 API를 다듬어 왔습니다. 루트 export를 확정하고 주요 라이브러리들과의 비호환 문제를 해결했습니다.
많은 앱이 에러가 거의 없거나 전혀 없이 0.87로 올라갈 수 있을 것입니다. 마이그레이션 가이드에 각 breaking change가 정리되어 있습니다.
에이전트 기반 업그레이드를 한다면 /migrate-to-strict-api 스킬을 활용할 수 있습니다. 기존 ESLint fixer 위에 직접적인 마이그레이션 지침이 담겨 있습니다.
모든 앱과 라이브러리가 당장 마이그레이션할 수 있는 것은 아니라는 점을 고려해, 사용자용 opt-out 스위치를 유지합니다.
이 opt-out은 임시 다리입니다. React Native 0.88까지 사용할 수 있으며, 그다음 릴리스에서 레거시 TypeScript 타입을 제거할 계획입니다.
이전 타입으로 잠시 되돌리려면 tsconfig.json에 "react-native-legacy-deep-imports" 커스텀 컨디션을 추가하세요.
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
...
+ "customConditions": ["react-native", "react-native-legacy-deep-imports"] }
}
이번 릴리스에서 Metro가 0.84에서 0.87로 업데이트됩니다.
metro.config.mts)을 정식 지원합니다. 반대로 .es6 확장자와 YAML 설정 지원은 제거되었습니다.React Native 0.87은 iOS에서 CocoaPods의 대안으로 Swift Package Manager를 실험적으로 지원합니다. opt-in이며 기존 방식에 추가되는 형태로, CocoaPods가 여전히 기본이자 지원되는 경로입니다. SwiftPM 경로는 React Native가 이미 배포 중인 사전 빌드 XCFramework를 그대로 사용합니다.
이 새 방식은 Xcode만 있으면 됩니다. Ruby도, Bundler도, CocoaPods도 필요 없습니다.
기존 앱이나 새 앱에서 시험해보려면:
cd ios
# deintegrate는 프로젝트에서 CocoaPods를 제거합니다
npx react-native spm --deintegrate이 명령은 프로젝트를 갈아엎는 게 아니라 기존 .xcodeproj에 Swift 패키지 참조를 주입합니다. 서명(signing), capability, 빌드 페이즈는 그대로 유지됩니다. npx react-native spm deinit으로 변경을 정확히 되돌릴 수 있습니다.
이 명령은 한 번만 실행합니다. 최초 설정 이후에는 의존성이 바뀌어도 다시 실행하지 않습니다. 네이티브 패키지를 설치하거나 제거한 뒤 빌드하면, 프로젝트가 변경을 감지해 오토링킹을 다시 수행합니다. 의존성이 바뀔 때마다 pod install을 기억해야 하는 단계가 없습니다.
알려진 제약:
Package.swift를 제공해야 합니다. 없다면 npx react-native spm scaffold로 해당 라이브러리의 podspec에서 생성할 수 있습니다.npx react-native spm을 한 번 실행하세요. pod install에 해당하는 단계입니다.전체 설계와 마이그레이션 계획은 RFC #0994를 참고하세요.
SwiftPM 통합을 제대로 지원하려면 React Native 자체의 사전 컴파일 바이너리를 배포하는 방식을 다시 생각해야 했습니다. SwiftPM은 XCFramework 구조와 헤더 위치에 대해 CocoaPods보다 훨씬 엄격하기 때문입니다.
그래서 새로운 XCFramework 두 개가 보일 수 있습니다.
ReactNativeHeaders.xcframeworkReactNativeDependenciesHeaders.xcframework둘 다 헤더 전용 프레임워크입니다. 이 변경 덕분에 헤더가 표준 프레임워크·헤더 검색 경로 방식으로 해석되고, 모든 네임스페이스가 물리적으로 정확히 한 곳에만 존재하게 됩니다. 헤더 내용 자체는 소스 pod과 바이트 단위로 동일합니다. 사용자 입장에서 바뀌는 것은 네임스페이스 없는 angle include 하나뿐입니다. 네임스페이스 없이 React Native 헤더를 import하고 있었다면 다음과 같이 추가하세요.
- #import <RCTAppDelegate.h>+ #import <React/RCTAppDelegate.h>
AGP 9 지원이 추가된 첫 React Native 릴리스입니다.
AGP 9.0은 Gradle 빌드에 여러 API 변경과 호환성 깨짐을 가져오는 메이저 릴리스입니다.
특히 이번 릴리스에서는 AGP 9에 포함된 내장 Kotlin과 새 DSL API를 끄는 것을 권장합니다. 업그레이드 헬퍼에도 안내되어 있듯, android/gradle.properties에 다음 플래그를 추가하면 됩니다.
# AGP 9에 포함된 내장 kotlin과 새 DSL 동작을 끕니다.
# AGP 10.x부터는 이 opt-out이 제거됩니다.
android.builtInKotlin=false
android.newDsl=false생태계 전반의 AGP 9 도입 진행 상황은 RFC #1006에서 확인할 수 있습니다.
Libraries/로의 deep import는 "react-native-legacy-deep-imports"로 되돌리지 않는 한 접근할 수 없습니다 (자세히).src/private/로의 deep import가 제거되었습니다.*Properties 타입 별칭(예: ViewProperties)은 Strict API에서 접근할 수 없습니다. *Props 쪽을 사용하세요 (자세히)..es6 확장자 JavaScript 설정 파일 지원이 제거되었습니다.InteractionManager가 제거되었습니다. requestIdleCallback을 사용하세요.Modal의 animated prop이 제거되었습니다.StatusBar의 backgroundColor, translucent, networkActivityIndicatorVisible prop과 해당 setter 메서드들이 제거되었습니다.ScrollView의 keyboardShouldPersistTaps에 불리언 값을 넣는 방식이 제거되었습니다.useTurboModules 기능 플래그가 제거되었습니다(TurboModules는 항상 활성화).useColorScheme()이 ColorSchemeName | null을 반환하며, 더 이상 'unspecified'를 반환하지 않습니다.NativeDialogManagerAndroid export와 (문서화되지 않았던) Touchable 루트 export가 제거되었습니다. 대신 ViewProps를 확장하세요.NativeMethods / NativeMethodsMixin 타입이 제거되었습니다(HostInstance 사용).@react-native/core-cli-utils가 더 이상 배포되지 않습니다(레퍼런스 구현으로 저장소 안에는 남아 있습니다).react-native/rn-get-polyfills가 제거되었습니다. @react-native/js-polyfills를 사용하세요.@react-native/jest-preset은 이제 패키지로 설치해서 사용해야 합니다.react-devtools 패키지에 WebSocket으로 연결하는 방식 지원이 제거되었습니다. React Native DevTools를 사용하세요.다음 API들은 deprecated 되었으며 이후 릴리스에서 제거될 예정입니다.
react-native/Libraries/Core/InitializeCore → react-native/setup-env 사용 (자세히)@react-native/assets-registry → react-native의 AssetRegistry와 새로운 @react-native/asset-utils 사용ImageBackground → View 안에 absolute 포지션 Image를 두는 방식 사용NativeMethods 인터페이스 → HostInstance 사용Appearance.setColorScheme('unspecified') → 'auto' 사용DrawerLayoutAndroid → react-native-drawer-layout 사용, UIBlock / UIManagerModule.addUIBlock / prependUIBlock → UIManagerListener나 View Command 사용, DefaultReactActivityDelegate의 new-arch-flag 생성자들TimingModule, RCTTurboModuleEnabled() / RCTEnableTurboModule()React Native 0.87에는 74명의 컨트리뷰터가 만든 265개의 커밋이 담겨 있습니다. 모든 분들의 노고에 감사드립니다!
이번 릴리스에서 특히 큰 기여를 해주신 커뮤니티 멤버들께 특별히 감사를 전합니다.
이제 0.87이 React Native의 최신 안정 버전이며, 0.84.x는 지원 종료(unsupported) 상태가 됩니다. 자세한 내용은 React Native 지원 정책을 참고하세요.
기존 프로젝트에서는 React Native Upgrade Helper로 버전 간 코드 변경 사항을 확인하고, 함께 업그레이드 문서도 참고하세요.
npx @react-native-community/cli@latest init MyProject --version latestExpo 프로젝트에서는 React Native 0.87을 expo@canary 릴리스로 사용할 수 있습니다.
공식 GitHub 릴리스와 CHANGELOG의 변경 항목을 한국어로 정리했습니다. 기록이 짧거나 비어 있는 버전은 공식 태그 비교로 보충하고 그 근거를 표시했습니다. 각 항목은 해당 패치의 변경 사항입니다.
| 버전 | 배포일 | 주요 내용 |
|---|---|---|
| 0.87.1 | 2026-08-27 | SwiftPM 빌드·Hermes 불일치와 Animated 타입 수정 |
250829098.0.17로 갱신했습니다.Animated.Value.addListener()의 콜백 인수를 any에서 { value: number }로 명시했습니다.Animated.event()의 반환 타입을 any 대신 이벤트 처리 함수로 명시했습니다.add_rn_third_party_dependencies에서 공백이 있는 헤더 검색 경로의 따옴표를 유지합니다.spm.modules 이름 때문에 모듈을 조용히 제외하던 동작을 수정했습니다.react-native.config.js의 spm.name을 읽도록 수정했습니다.spm.modules.publicHeaderFiles를 제거했습니다.react-native.config.js의 default export를 올바르게 읽습니다.SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG를 설정합니다.Wrong bytecode version으로 앱이 종료되던 문제를 수정했습니다.출처: 공식 릴리스 0.87.1 · 공식 CHANGELOG