Skip to main content

React Native 0.71-RC0 Android 장애 사후 분석

· 14 min read
Nicola Corti
Nicola Corti
Software Engineer at Meta
Lorenzo Sciandra
Lorenzo Sciandra
Senior Software Engineer at Microsoft

이제 0.71 버전이 공개되었으므로, 2022년 11월 4일 React Native와 Expo의 첫 0.71 릴리스 후보를 출시하면서 발생한 Android 빌드 문제에 대한 주요 정보를 공유하려 한다.

이 문제를 해결하는 데 기여한 개발자들은 최근 사후 분석 회의에 참여해 발생한 일, 이를 통해 배운 점, 그리고 앞으로 유사한 장애를 방지하기 위해 취할 조치에 대해 자세히 논의했다.

어떤 일이 있었나

2022년 11월 4일, 우리는 React Native의 0.71.0-rc0 버전을 여러 공개 저장소에 출시했다. 이 버전은 0.71의 첫 번째 릴리스 후보였다.

이 릴리스 후보에서 주요 변경 사항은 소스 코드에서 빌드하는 대신 Maven Central에 아티팩트를 게시해 빌드 시간을 개선한 것이다. 이 작업이 어떻게 진행되었는지에 대한 자세한 내용은 RFC#508관련 논의에서 확인할 수 있다.

하지만 새로운 프로젝트를 템플릿에서 스캐폴딩하는 방식 때문에, 이전 버전을 사용하는 모든 Android 사용자에게 빌드 실패가 발생했다. 그들은 프로젝트에서 사용 중인 버전(예: 0.68.0) 대신 0.71.0-rc0의 새로운 아티팩트를 다운로드하기 시작했기 때문이다.

왜 이런 일이 발생했는가

React Native 템플릿은 안드로이드 앱을 빌드하기 위해 build.gradle 파일을 제공한다. 이 파일은 React Native 안드로이드 라이브러리에 대한 의존성을 포함하고 있으며, 다음과 같이 표현된다: implementation("com.facebook.react:react-native:+").

여기서 중요한 점은 이 의존성의 + 부분(Gradle 동적 버전)이 Gradle에게 React Native의 최신 버전을 선택하도록 지시한다는 것이다. Gradle 동적 버전을 사용하는 것은 재현 가능성이 낮은 빌드를 초래할 수 있으므로 안티패턴으로 간주된다.

우리는 동적 버전이 야기할 수 있는 문제를 인지하고 있었기 때문에, 0.71 버전에서 새로운 앱 템플릿을 정리하고 모든 + 의존성을 제거했다. 그러나 이전 버전의 React Native를 사용하는 사용자들은 여전히 + 버전을 사용하고 있었다.

이로 인해 0.71.0-rc.0 이전 버전의 React Native를 사용하는 빌드가 모든 리포지토리를 쿼리하여 React Native의 최신 버전을 찾게 되었다. Maven Central에 새로 푸시된 0.71.0-rc.0이 사용 가능한 최신 버전이 되었기 때문에, 0.71.0-rc.0 이전 버전의 React Native를 사용하는 빌드들이 0.71.0-rc.0의 아티팩트를 사용하기 시작했다. 로컬 빌드(예: 0.68.0)와 Maven Central의 아티팩트(0.71.0-rc.0) 간의 React Native 버전 불일치로 인해 이러한 빌드들이 실패하게 되었다.

이 이벤트에 대한 추가 기술적 세부 사항은 이 GitHub 이슈에서도 확인할 수 있다.

문제 해결 과정

11월 4일 문제를 확인한 직후, 커뮤니티에서 수동으로 문제를 해결하는 방법을 찾아 공유했다. 이 방법은 React Native를 특정 버전으로 고정해 문제를 해결하는 방식이었다.

11월 5일과 6일 주말 동안, 릴리스 팀은 React Native 0.63 버전까지 모든 이전 버전에 대한 패치 릴리스를 배포했다. 이 패치가 자동으로 적용되어 사용자들이 수정된 React Native 버전으로 업데이트할 수 있게 했다.

동시에, Sonatype에 연락해 문제가 되는 아티팩트를 제거해 줄 것을 요청했다.

11월 8일, Maven Central에서 아티팩트가 완전히 제거되면서 이슈가 완전히 해결됐다.

주요 이벤트 타임라인

이 섹션에서는 주요 이벤트의 타임라인을 정리한다. 모든 시간은 GMT/UTC +0 기준이다.

교훈

이번 사건을 유발한 조건들은 React Native 0.12.0 버전부터 존재해 왔지만, 앞으로 React Native를 개발하고 출시하는 데 더 튼튼한 기반을 마련하고자 한다. 이번 경험을 통해 얻은 교훈과 앞으로 프로세스와 인프라를 어떻게 개선할지에 대한 실행 계획을 공유한다. 이를 통해 더 빠르고 강력하게 대응할 수 있도록 할 것이다.

인시던트 대응 전략

이번 사건은 React Native와 관련된 오픈소스 문제에 대한 우리의 인시던트 대응 전략의 허점을 드러냈다.

커뮤니티는 불과 2시간 만에 임시 해결책을 찾았다. 이 문제의 영향 범위에 대한 우리의 가시성 부족과 구버전에서의 수정이 복잡하다는 점 때문에, 우리는 GitHub 이슈에서 임시 해결책을 찾는 데 의존할 수밖에 없었다.

이 문제의 더 큰 범위를 인식하고 모든 사람이 GitHub 이슈를 찾을 수 있다고 기대할 수 없다는 사실을 깨닫는 데 48시간이 걸렸다. 우리는 사람들의 프로젝트를 자동으로 수정하기 위해 더 복잡한 적극적인 완화 조치를 우선적으로 적용해야 했다.

앞으로 개발자가 직접 적용하는 임시 해결책과 자동으로 배포할 수 있는 수정 사항 중 어떤 것을 선택할지에 대한 프로세스를 재검토할 예정이다. 또한 우리 생태계의 상태를 더 잘 파악할 수 있는 방법도 살펴볼 것이다.

릴리즈 지원 정책

rn-versions 도구에서 확인할 수 있듯이, 사건 당시 React Native 개발자 기반의 90% 이상을 커버하기 위해 버전 0.63까지 패치를 릴리즈해야 했다.

이 문제는 React Native 업그레이드 경험이 역사적으로 많은 마찰을 겪어왔기 때문에 발생한 것으로 보인다. 현재 생태계의 파편화를 완화하고 업그레이드 경험을 더 부드럽고 빠르게 개선할 방법을 모색 중이다.

새로운 버전의 React Native를 릴리즈하더라도 이전 버전을 사용 중인 사용자에게 영향을 미쳐서는 안 된다. 이번 사건으로 여러분의 업무 흐름에 방해가 된 점에 대해 사과의 말씀을 전한다.

동시에, 최신 버전의 의존성과 React Native를 사용하는 것의 중요성을 강조하고 싶다. 이를 통해 우리가 도입한 개선 사항과 안전 장치를 활용할 수 있다. 이 사건은 공식 릴리즈 지원 정책이 정의되고 있던 시점에 발생했으며, 아직 공개되거나 강제되지 않은 상태였다.

앞으로는 지원 정책을 커뮤니케이션 채널을 통해 명확히 전달할 예정이다. 또한 npm에서 이전 버전의 React Native를 더 이상 사용하지 않도록(deprecating) 하는 것도 고려 중이다.

타사 라이브러리 테스트 개선 및 모범 사례

이번 사건은 릴리스 테스트를 강화하고 타사 라이브러리에 대한 더 나은 가이드를 제공하는 것이 얼마나 중요한지 다시 한번 강조했다.

테스트 측면에서 0.63.x 버전까지의 릴리스는 현재 안정 버전에 적용된 자동화와 테스트가 부족해 어려움을 겪었다. 우리는 릴리스와 테스트 인프라의 중요성을 인지하고 있으며, 앞으로 이 부분에 더 많은 투자를 할 계획이다.

구체적으로, React Native 릴리스의 일환으로 타사 라이브러리 테스트를 적극 권장하고 지원하고 있다. 또한 Core Contributors Discord Server에 새로운 채널과 역할을 추가했다.

이와 함께, create-react-native-library의 메인테이너인 Callstack과의 협력을 강화해 라이브러리 템플릿을 개선하고 React Native 프로젝트와의 통합을 위한 모든 필수 모범 사례를 준수하도록 했다. 이제 create-react-native-library의 최신 버전은 0.71 프로젝트와 완벽히 호환되며, 이전 버전과의 호환성도 유지한다.

결론

전 세계 개발자의 업무 흐름에 방해가 된 점에 대해 진심으로 사과드린다. 앞서 언급했듯이, 우리는 이미 기반을 강화하기 위한 조치를 시작했으며, 더 많은 작업이 예정되어 있다.

이번 사건에 대한 통찰을 공유함으로써 여러분이 상황을 더 잘 이해하고, 우리의 경험을 활용해 각자의 도구와 프로젝트에 더 나은 방식을 적용할 수 있기를 바란다.

마지막으로, 아티팩트 제거를 도와준 Sonatype, 그리고 가능한 한 빨리 이 문제를 해결하기 위해 끊임없이 노력한 커뮤니티와 릴리스 팀에게 다시 한 번 감사의 말씀을 전한다.