React Native v0.71.0の影響でandroidビルドできなくなった件

# あらまし
* React Nativeのv0.71.0-rc0が2022/11/4に公開されたよ
* 上記リリースによって他のバージョンのReact Nativeで開発を行っていた場合に、androidのビルドエラーが発生するようになったよ
* React Native公式で事象と対処方法についてissueを記載してくれているので、この記事では関連知識とissueの解説をしていくよ
    * [公式のissue](https://github.com/facebook/react-native/issues/35210)

# 前提
## React Nativeとは
* [この記事](https://qiita.com/Iwark/items/7c27e919bb71f8b256f6)とか読んでもらうとわかりやすい。
* ざっくりいうとReactみたいな書き方でほぼほぼワンソースでandroidもiOSのアプリも作成できるすんばらしいフレームワーク。

## Node.js, npmとは
* Node.jsがなんたるかについては、[この記事](https://qiita.com/rpf-nob/items/6823fb8728754386ef30)がわかりやすく教えてくれる。（以下抜粋）
> JavaScriptをブラウザではなくPythonやRubyなどと同じようにターミナル上で動かすことができるようにするための実行環境のこと 

> Reactのような大規模なアプリケーションを開発するとなると、様々なパッケージが必要になり、そのパッケージたちが特定のバージョンで依存しあっています。Node.jsはそのパッケージのインストールと整合性の管理を解決するために必要であり、npm(Node Package Manager)がその解決を担っています。

* つまりこんな感じ
    * Node.js：JavaScriptの実行環境
    * npm：開発に必要なパッケージのバージョン管理

## Mavenセントラルレポジトリとは
* 正確な内容は、[このサイト](https://maven3.kengo-toda.jp/primer/maven-repository)を見てもらえればだが、ざっくりいうとJavaで利用できるOSSが置かれてる場所、そんなイメージで良いかと。

> JARなどの成果物やJavadocをライブラリを整理してまとめておく場所のことを、Mavenリポジトリと呼びます。 

> (セントラルリポジトリとは)Mavenがデフォルトで利用するリポジトリです。たくさんのライブラリが公開されています。

# 本題
## 事象
* v0.70以下のすべてのバージョンのReact Nativeを使用しているアプリでandroid用アプリのビルドを行う際に以下のようなメッセージが表示されるようになった。
```
Error: Command failed: gradlew.bat app:installDebug -PreactNativeDevServerPort=8081

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'My Project'.
Could not determine the dependencies of null.
Could not resolve all task dependencies for configuration ':classpath'.
    > Could not resolve com.facebook.react:react-native:+.
      Required by:
          project :
    > No matching variant of com.facebook.react:react-native:0.71.0-rc.0 was found. 
      The consumer was configured to find a runtime of a library compatible with Java 11, 
      packaged as a jar, and its dependencies declared externally, as well 
      as attribute 'org.gradle.plugin.api-version' with value '7.3.3' but:
```

## 対応方針
### v0.63以上
* 各バージョンに応じたhotfixがリリースされているので、react-nativeのバージョンをアップデート

### v0.63未満
* `android/buld.gradle`に以下を追記
```
def REACT_NATIVE_VERSION = new File(['node', '--print',"JSON.parse(require('fs').readFileSync(require.resolve('react-native/package.json'), 'utf-8')).version"].execute(null, rootDir).text.trim())

allprojects {
    configurations.all {
        resolutionStrategy {
            // Remove this override in 0.65+, as a proper fix is included in react-native itself.
            force "com.facebook.react:react-native:" + REACT_NATIVE_VERSION
        }
    }
```

## 原因
* 従来のReact Nativeテンプレートに含まれている`build.gradle`では、Androidアプリに関するライブラリに対する依存性として以下のような記載がある。（[参考:v0.70.5](https://github.com/facebook/react-native/blob/v0.70.5/template/android/app/build.gradle#L254-L255)）

```
    implementation "com.facebook.react:react-native:+"  // From node_modules
```


* この`+`を使った記法は`Gradle Dynamic versions`と呼ばれており、すべてのレポジトリの中から最新バージョンを取得するような動きとなる。
* v71.0がリリースされるまでは以下のような流れで正しいバージョンのReact Nativeが参照されていた。
    1. `npm install` の際に、`package.json`に記載されたバージョンのreact-nativeがダウンロードされ、`node_modules/react-native/android`に格納される
    1. androidアプリビルド時に上記の`node_modules/react-native/android`配下のReact Nativeを参照

* 一方で、v0.71からはリリース戦略が変更され、NPMパッケージではなく、Mavenセントラルにリリースされるようになった。
* 上記の２の段階で、`node_modules/react-native/android`には正しいバージョンのreact-nativeが格納されているにもかかわらず、より新しいバージョンのreact-nativeがMavenセントラルに存在するようになってしまったため、そちらが参照されてしまいビルドエラーになってしまった。

## 所感
* `Gradle Dynamic versions`でNPMの最新版のreact-nativeがダウンロードされなかったのはなぜだろう？ `npm install`を使わないとNPMからダウンロードできないのかな？とかモヤモヤは残っていますが、とりあえずこんなことが起きたんだなぁというのはなんとなく理解できました。
* ざっくり理解なので細かいところ間違っていたら優しく教えてください。。。