React Native 0.87 Strict TypeScript 기본값 대응과 마이그레이션 실무

소스 코드 기반 자동 생성 타입 체계 전환에 따른 런타임 불일치 해결과 Metro 0.87 설정 가이드

RN 0.87 Strict TS 기본값 썸네일

핵심 요약

  1. React Native 0.87부터 Strict TypeScript API가 프레임워크 전반의 기본값으로 채택됐다.
  2. 수동 선언 파일(@types) 대신 네이티브 C++/Java/Obj-C 소스에서 직접 타입 선언이 추출된다.
  3. Metro 0.87은 TypeScript 및 ESM 설정 파일을 기본 지원하며 소스맵 생성 속도가 35% 향상됐다.
  4. 서드파티 네이티브 모듈의 타입 불일치를 해결하기 위한 타입 오버라이드 기법이 요구된다.

React Native 애플리케이션을 개발하고 유지보수할 때 가장 까다로운 버그 중 하나는 '타입 정의 파일(index.d.ts)과 네이티브 런타임의 실제 동작 사이의 미묘한 불일치'였습니다. 기존에는 사람이 수동으로 관리하는 DefinitelyTyped나 번들 타입 선언에 의존했기 때문에, 네이티브 계층의 인터페이스 변경 사항이 제때 반영되지 못해 런타임 크래시가 발생하는 경우가 잦았습니다.

React Native 0.87은 이러한 구조적 문제를 해결하기 위해 Strict TypeScript API를 기본 표준으로 채택했습니다. 소스 코드에서 네이티브 타입 시그니처를 자동으로 생성하고, Metro 0.87 번들러의 구조 개선을 통해 개발 생산성을 대폭 끌어올렸습니다. 본 가이드에서는 0.87 버전으로 마이그레이션할 때 점검해야 할 핵심 변경 사항과 실무 대응 절차를 다룹니다.

React Native 이전 버전 대비 0.87 핵심 변화 비교

0.87 릴리스는 네이티브 브릿지 계층의 완전한 타입 안전성과 빌드 도구 체인의 모던화를 목표로 설계되었습니다.

구분React Native 0.86 이하React Native 0.87실무 영향 및 기대 효과
TypeScript API 표준옵트인(Opt-in) 느슨한 타입 정의Strict TypeScript 기본 강제런타임 Undefined 속성 접근 사전 차단
타입 생성 파이프라인수동 d.ts 파일 관리 및 유지보수네이티브 모듈 소스 기반 Codegen 자동 추출네이티브-JS 계층 간 불일치 원천 제거
Metro 번들러 버전Metro 0.80.x (CJS 전용 설정)Metro 0.87 (TypeScript/ESM 설정 지원)번들러 설정 타입 지원 및 소스맵 생성 가속
iOS 패키지 관리 체계CocoaPods 단일 경로CocoaPods 기본 + SwiftPM 실험적 지원향후 빌드 속도 개선을 위한 토대 마련

프론트엔드와 모바일 전반의 타입 아키텍처 정비 원칙은 TypeScript AI 코딩 품질 및 유지보수성 향상 기법과 AI 풀스택 엔지니어 로드맵에서도 동일하게 유효한 핵심 설계 기반입니다.

4단계 마이그레이션 실행 절차

기존 프로젝트를 0.87 환경으로 안정적으로 전환하기 위한 단계별 실행 흐름은 다음과 같습니다.

  1. 의존성 갱신 및 캐시 초기화: React Native 코어 패키지와 템플릿 설정을 갱신하고 Metro 캐시를 정리합니다.
  2. NativeEventEmitter 및 브릿지 타입 리팩토링: 제네릭 인터페이스 요구에 맞추어 이벤트 리스너 타입을 엄격하게 재선언합니다.
  3. Metro 설정 파일의 ESM/TypeScript 전환: 설정 파일을 metro.config.ts로 전환하여 번들링 옵션의 자동완성과 정적 검증을 활성화합니다.
  4. 전체 프로젝트 타입 검사 완주: tsc --noEmit 실행을 통해 서드파티 라이브러리 호환성 및 숨어있던 타입 에러를 일괄 해결합니다.

1단계: 패키지 갱신 및 Metro 캐시 초기화

새 버전을 설치하고 네이티브 의존성 캐시를 완전히 초기화합니다.

# 1. 코어 및 타입 의존성 갱신
npm install [email protected]
npm install -D @tsconfig/react-native@latest

# 2. Metro 및 Watchman 캐시 정리
watchman watch-del-all
npx react-native start --reset-cache

2단계: NativeEventEmitter 제네릭 타입 강화 대응

기존의 느슨했던 이벤트 에미터 코드는 0.87에서 컴파일 에러를 발생시킬 수 있습니다. 엄격한 이벤트 맵 타입을 정의해야 합니다.

// src/native/AudioPlayerModule.ts
import { NativeModules, NativeEventEmitter } from 'react-native';

// 1. 네이티브 이벤트 페이로드 인터페이스 명시적 선언
export interface AudioEventPayloads {
  onPlaybackStateChange: { state: 'playing' | 'paused' | 'stopped'; position: number };
  onPlaybackError: { errorCode: string; message: string };
}

const { AudioPlayerModule } = NativeModules;

// 2. Strict 제네릭을 적용한 EventEmitter 인스턴스 생성
export const audioEventEmitter = new NativeEventEmitter<AudioEventPayloads>(AudioPlayerModule);

// 3. 타입 안전한 이벤트 구독
export function subscribePlaybackState(callback: (event: AudioEventPayloads['onPlaybackStateChange']) => void) {
  return audioEventEmitter.addListener('onPlaybackStateChange', callback);
}

3단계: metro.config.ts 도입 및 설정 현대화

Metro 0.87은 TypeScript 설정 파일을 정식으로 지원하므로 번들러 옵션의 오탈자를 사전에 방지할 수 있습니다.

// metro.config.ts
import { getDefaultConfig, mergeConfig } from '@react-native/metro-config';
import type { MetroConfig } from 'metro-config';

const defaultConfig = getDefaultConfig(__dirname);

const customConfig: MetroConfig = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: true,
      },
    }),
  },
  resolver: {
    sourceExts: [...defaultConfig.resolver.sourceExts, 'mjs', 'cjs'],
  },
};

export default mergeConfig(defaultConfig, customConfig);

서드파티 라이브러리 타입 깨짐 대응 전략

구형 서드파티 라이브러리가 0.87의 엄격한 타입을 아직 지원하지 않는 경우 다음 2가지 전략으로 점진적 대응이 가능합니다.

  1. 타입 증강(Declaration Merging): src/types/overrides.d.ts 파일을 생성하여 문제가 되는 외부 모듈의 네임스페이스를 확장 선언합니다.
  2. skipLibCheck 활성화: 라이브러리 내부 .d.ts 파일의 타입 검사는 건너뛰고 프로젝트 소스 코드의 엄격성만 유지하도록 tsconfig.json을 구성합니다.

초보자가 자주 실수하는 포인트

  • 업그레이드 후 tsc 검사 없이 단순 앱 구동만 확인하고 배포를 진행하는 경우
  • 기존 커스텀 네이티브 브릿지 모듈의 시그니처를 Any 타입으로 우회해버리는 런타임 위험
  • Metro 번들러 캐시를 초기화하지 않아 예기치 못한 심볼 참조 오류를 겪는 경우

체크리스트

  • react-native 0.87 및 @tsconfig/react-native 최신 템플릿으로 갱신했는가
  • 커스텀 TurboModule 및 NativeEventEmitter의 제네릭 타입 정의를 정비했는가
  • metro.config.ts 또는 metro.config.js 설정 파일의 ESM 호환성을 검증했는가
  • CI 파이프라인에서 tsc --noEmit 명령어가 에러 없이 완주하는지 확인했는가

자주 묻는 질문

Strict TypeScript가 적용되면 기존 서드파티 라이브러리에서 타입 에러가 대량 발생하나요?

오래된 라이브러리의 경우 엄격한 제네릭 검사로 인해 타입 에러가 발생할 수 있습니다. 이 경우 skipLibCheck: true 옵션을 활성화하거나, 문제가 되는 라이브러리 타입만 declaration merging을 통해 보정하는 전략을 사용합니다.

SwiftPM으로 CocoaPods를 완전히 대체할 수 있나요?

React Native 0.87의 SwiftPM 지원은 아직 실험적(Experimental) 단계입니다. 대다수 커뮤니티 라이브러리가 여전히 Podspec을 기반으로 하므로 프로덕션 프로젝트에서는 CocoaPods 기반 파이프라인을 유지하는 것이 안전합니다.

참고 자료 · 검증 기준

위 자료와 내용을 대조한 날짜: . 도구·서비스 정책은 이후 바뀔 수 있으므로 적용 전 공식 문서를 다시 확인하세요.

이 글은 실제 실무 환경 테스트 및 검증된 기술 자료를 바탕으로 작성되었으며, 환경 변화에 따라 지속적으로 갱신됩니다.