안녕하세요, 이번에는 react-native-video 오픈소스 프로젝트에서 Fabric (new architecture)을 적용하며 겪었던 일들을 한번 써보려고 합니다.

우선 Fabric은 RN에서 새롭게 선보인 New Architecture에서 View (UI) 관련한 네이티브 모듈을 뜻합니다.

Fabric에 대한 공식문서는 다음과 같습니다.

https://reactnative.dev/architecture/fabric-renderer

1. New Architecture

우선 제가 알기로 New Architecture는 기존 RN에서 네이티브 모듈을 엮을때에 항상 브릿지를 이용해서 JS 레이어와 native 레이어 사이의 통신을 주고받던 방식에서 C++ 언어를 사용하여 브릿지 사용을 없애 성능 향상을 시킨 네이티브 모듈의 새로운 아키텍쳐 라고 알고 있습니다.

자세한 공식문서는 다음과 같습니다.

https://reactnative.dev/docs/the-new-architecture/landing-page

2. react-native-video

react-native-video는 꽤나 유명한 오픈소스 RN 비디오 관련 라이브러리 입니다.

아무래도 RN에서 각 도메인에 맞는 피쳐마다 메인 오픈소스 라이브러리가 존재하는데, 비디오 관련해서 유명한 네이티브 라이브러리라고 보시면 될 것 같습니다.

오픈소스의 깃헙 레포 url은 다음과 같습니다.

https://github.com/react-native-video/react-native-video

사실 꽤나 방대한 라이브러리 라서 여러가지 기능들을 쓸 수 있게 제공을 합니다만, 비디오의 특성상 필요한 기능들을 모두 집약한 느낌이라 관리가 힘든 것은 사실입니다.

관련해서 제가 진행한 작업은 미리 마련된 오픈소스 라이브러리에서 New Architecture를 적용한 작업입니다.

회사에서 회사 동료와 함께 작업을 해서 PR을 올렸는데 아직 머지가 되진 않았습니다.

https://github.com/react-native-video/react-native-video/pull/3122

https://github.com/react-native-video/react-native-video/pull/3204

아무래도 코드 베이스가 바뀌고 방대한 PR이다 보니, 쪼개려 한다고 쪼갰는데도 부담이 가는 PR이 만들어지더군요.

따라서 최종적으로는 codegen 부터 지원하는 PR을 만들었습니다.

https://github.com/react-native-video/react-native-video/pull/3487

3. 트러블 슈팅

사실 꽤나 후발 주자로써 new architecture 도입을 시작 했기 때문에, 관련해서 찾아볼 수 있는 다른 RN 오픈소스 라이브러리의 레퍼런스가 많았습니다.

제가 참고했던 좋은 라이브러리들의 링크 몇 개를 올려놓겠습니다.

https://github.com/th3rdwave/react-native-safe-area-context

https://github.com/lottie-react-native/lottie-react-native

https://github.com/react-navigation/react-navigation

등등 꽤나 메이저한 라이브러리들은 이미 저희가 시작하기 전에 new architecture 지원들을 하고 있더군요.

따라서 이러한 라이브러리들은 어떻게 Fabric을 적용했나 참고했는데, 많은 도움이 되었습니다.

일단 iOS 의 경우 podspec에서 나누는 것 부터 시작합니다.

https://github.com/lottie-react-native/lottie-react-native/blob/master/packages/core/lottie-react-native.podspec에서 보이는 것 처럼 podspec에서 new architecture가 적용 되어있는지 여부를 확인 후에 필요한 pod 모듈들을 따로 인스톨 합니다.

안드로이드의 경우 build.gradle에서 나뉩니다.

https://github.com/lottie-react-native/lottie-react-native/blob/master/packages/core/android/build.gradle#L96 에서 볼 수 있듯이, fabric 여부에 따라 빌드할 파일을 분리합니다.

첫번째로 어려웠던 부분이 codegen 과 typescript를 엮는 부분이었는데요, 관련해서 0.73.0 이전 버전에서는 이벤트 콜백 파라미터에 array (readonly array) 타입이 지원이 되지 않아서, 애를 먹었던 것이 생각나네요.

하지만 0.73.0 을 포함 한 이후 버전 부터는 지원이 되니 참고하세요!

https://github.com/facebook/react-native/blob/81e368e1d33bbbebe3c46df045536bbd7d1454bc/CHANGELOG.md?plain=1#L62C45-L62C133

일단 가장 큰 차이점은 C++의 namespace 로 코드젠이 이루어지기 때문에, 다른 타입에서 같은 변수 이름을 쓸 수 없습니다. 따라서

type SomeType {
  name: string
}

type AnotherType {
  name: string
}

과 같이 썼던 부분들이

type SomeType {
  someTypeName: string
}

type AnotherType {
  anotherTypeName: string
}

과 같이 바뀌어야 했습니다.

iOS같은 경우는 c++ 을 직접적으로 다루어서 .mm 확장자를 가진 파일을 다루어야 했는데요, 이 또한 꽤나 처음엔 적응하기 어려운 작업이었습니다. 관련해서 동료분이 iOS는 주로 작성을 해주셨는데, 스택오버플로를 참고하여 JS 단에서 내려온 프롭들을 파싱하는 유틸함수를 가져왔던 기억이 있네요.

안드로이드는 생각보다 간단합니다만, 각각의 event들에 대한 파일들을 새로 생성해서 관리해야 했기 때문에 힘든 경험이 좀 있었습니다.

결론적으로 마이그레이션 작업을 끝냈고 프로덕션단에 적용을 목적으로 순항하고 있었으나, react native new architecture가 아직은 UI가 깨지는 등 불안정 했기 때문에 다시 old architecture로 회귀 후 배포를 했네요.

결론적으로 트러블 슈팅 과정은

  • 다른 오픈소스 라이브러리들을 레퍼런스로 참고
  • C++의 경우 잘 모른다면 스택오버플로를 참고
  • RN에서 꾸준히 업데이트 해주는 Changelog를 참고

하여 꽤나 어려운 작업이었지만 해결했네요.

이런 방대한 오픈소스 프로젝트 작업을 기여한 것은 또 처음이라 관련해서 아직 머지가 되고 있지는 않습니다만, 이럴 때에는 최대한 피쳐들을 쪼개어 작은 PR로 만들어 주면 메인테이너분들이 관리하기가 훨씬 쉽다는 점도 깨달은 점입니다.

← Go home