こんにちは。ビズリーチの新卒事業部でフロントエンドエンジニアをやっている円谷(@___35d)です。以前ビズリーチのデザイナーブログにも登場して、通勤風景の写真でチーム内で相当いじられました。興味ある方はぜひそちらも読んでみてください。今日はエンジニアブログの方を書いていきたいと思います。
さっそく本題ですが、2018年11月に ビズリーチ・キャンパスfor OB/OG がフルリニューアルされました。いままでWebViewベースで構築されていたアプリをリデザインし、React Nativeでフルネイティブ化しました。この記事ではReact Nativeを採用するまでに至った背景と、導入してどうだったのかについてお話できればと思います。この記事が、これからReact Nativeを使ったアプリ開発を検討している方の参考になれば幸いです。
目次
- はじめに
- 社内事情と技術選定について
- React Nativeで良かったところ
- 学習コストが少なくて済み、アプリのメンテナが増えた
- Hot Reloadによってスタイル修正がすばやくできた
- React Native Debuggerによってスムーズなデバッグが可能になった
- React Nativeだとツラかったところ
- Reduxの初期学習コストが高くてツラい
- アニメーションの実装の煩雑さ / パフォーマンスチューニングがツライ
- バージョンアップについていくのがツライ
- 結論:導入してよかった
- ほかの開発者から一言
社内事情と技術選定について
React Native は、Facebookが開発したクロスプラットフォームアプリ開発用フレームワークです。React Nativeでアプリを作ることで、クロスプラットフォーム( iOS / Androidどちらでも動く)アプリを作ることができます。 Facebook社製なのでFacebookはもちろんですが、Instagram / Facebook Messenger / Discord / Skypeなど、さまざまな大規模アプリで採用実績があり、世界的に注目を浴びつつあります。React Nativeという名前の通り、 React (JavaScript) が書ければ、アプリ開発をすることができることも特徴の一つです。
以上の特徴を踏まえて、私たちはReact Nativeを導入することを決めました。その理由の1つとして、ビズリーチはWebに精通したエンジニアが多い一方、アプリエンジニアが少ないという状況が続いていることが挙げられます。私の所属する新卒事業部で見ても、Webエンジニアは10名程度在籍している一方で、アプリエンジニアは @kouchi67 の1人しかおらず、アプリのメンテナンスは彼にお任せといった状況でした。
私たちの事業部では、Webに精通しているエンジニアなら比較的学習コスト少なくコードが書けるであろうReact Nativeをアプリの開発言語として採用し、アプリ開発に携われる人数を増やそうとしました。ビズリーチ・キャンパスfor OB/OGは、アプリエンジニア1名と、私を含む他3名のWebエンジニアで開発を行いました。
React Nativeを採用して良かったこと
😀学習コストが少なくて済み、アプリのメンテナが増えた
一番の良かったことはこれだと思います。上記のような課題を抱えていた私たちの組織にReact Nativeにはぴったりフィットしていました。一人に依存していたアプリのメンテナンス作業も、開発人員が増えたおかげで複数人で行うことができるようになりました。React Nativeを採用することで、組織の課題を解決することができました。また、スタイルの記述はCSSとほぼ同じなので、デザイナーでも微妙なスタイルの調整を行うことができたことも良かったことの一つでした。
せっかくのTech Blogなので、技術の観点からも良かったことを何点か列挙したいと思います。React Nativeのさまざまな機能を駆使することで、生産性とコード品質を向上させることができました。
😀 Hot Reloadによってスタイル修正がすばやくできた
私たちは、デザイナーがSketchでデザインカンプを作成、エンジニアが実装、その後、デザイナーに実機で見た目を確認してもらう(デザイナーレビュー)、というフローで開発を行っていますが、デザイナーレビュー時の細かいマージンの調整などはHot Reload (エディタ上で修正したものが即時に反映される) 機能を使うことでスピーディに行うことができました。デザインカンプとの微妙なズレは、デザイナーに実機で確認してもらいながらエンジニアがコードを修正する、という進め方でスタイルを調整することができ、スピーディな開発を実現することができました。
😀 React Native Debuggerによってスムーズなデバッグが可能になった
複雑なアプリになればなるほどアプリの状態管理は複雑になります。Reactで状態管理をするには定番のReduxを私たちのチームでも採用しました。Reduxを導入することで、Storeと呼ばれる格納領域に、状態管理を一任することができます。
さらに、React Native Debugger を導入することで、このStoreの状態を常に確認しながら開発を進めることができました。Actionが発生するたびにログが流れ、Storeにどのような変更が発生したのかをGUIで確認することができました。さようならconsole.log(); ちなみにこのReact Native Debuggerは、Chromeなどのブラウザと同じく、アプリ内のDOMの構造やサイズ、スタイルなども見ることもできます。原因不明のスタイル崩れなどもこれを使うことで素早く原因箇所を特定することができます。とても便利なツールでした。
React Nativeを採用してツラかったこと
ここまで良かったことをつらつらと書いてきましたが、つらみを感じた部分もたくさんありました。社内の他のエンジニアからもつらみの声がたくさん上がりました。その声の中から3つピックアップして紹介したいと思います。
🤮 Reduxの初期学習コストが高くてツラい
当初はReduxに熟練していないメンバーが多かったので、チーム皆で理解と共通認識を深めながらコードを書いていました。また、どのプロジェクトでもそうだと思いますが、業務ロジックへの理解も浅い状態からのスタートでした。
プロジェクトが進みReduxの習熟度と業務ロジックへの理解も深まるにつれて、書いている時点では最適と思ったコードが技術的負債になっていたことに気づくことが多々ありました。それに伴いStoreも再設計していく必要がありましたが、Redux自体の記述量が多く、修正→確認のイテレーションを回すのに時間がかかってしまうことが多々ありました。また、再設計の過程で新しいバグを生み出してしまう場合もあり、ここにつらみを感じることがありました。
最初から完全に理解した状態で作り上げることは不可能なので、技術的負債と常に向き合い続け再設計し続けるプロセスを踏む必要があります。これは私の主観ですがReduxは初期学習コストが決して低いものではないので、私たちのようなチーム体制の組織に導入する上では、上記のようなことに直面することへの覚悟がある程度必要だと思っています。
🤮アニメーションの実装の煩雑さ / パフォーマンスチューニングがツライ
今回の開発では、アニメーションにも力を入れましたが、実装はなかなかのつらみを感じました。上記のReduxと同じですが、アニメーションに精通したメンバーがいたわけではなかったので、試行錯誤を繰り返しつつ実装を進めていきました。その過程で、コードの煩雑さとパフォーマンスチューニングで特につらみを感じました。
煩雑なアニメーションコードと戦い続ける
こちらの例は、学生からOBに話を聞きたいリクエストが飛んだときに表示されるカードですが、このカードをタップすると以下のようなアニメーションが同時に発生します。
- カード自体が伸縮
- 画像が拡大
- 閉じるボタンがフェードイン
- 上からシャドー
- 下からボタンが登場
- 下からプロフィールが登場
同時に多くの要素がアニメーションすることで、実装がどんどん煩雑になっていき、render() が肥大化、アニメーションのデバッグはますます困難になっていきました。そこで以下のように、アニメーションさせる処理を分割しなるべく見通しのよい状態を維持し続けるように試みました。
|
|
|
|
アニメーションのパフォーマンス問題と戦い続ける
アニメーションが煩雑になると、どうしてもパフォーマンスが低下してしまうことがありました。 shouldComponentUpdateで余分なrender() が走らないように細かに制御しました。初期描画時はアニメーションをしない、などアニメーションを実行するかどうかをstateにフラグとして持たせていますが、 stateが更新されるたびにrender() が実行されるとパフォーマンスがどんどん落ちていきます。shouldComponentUpdateを適切に使用することで、render() の実行を必要最小限に抑えることができます。
|
|
また、以下の例はローディングのアニメーションの実装コードですが、useNativeDriverを使用しないと、アニメーションの動作がカクカクになってしまい、ユーザー体験を損ねてしまいます。useNativeDriverを適切に使用し、軽快に動作するよう、細かい調整がアニメーションの実装には必要になってきます。
|
|
つらみがたまってネガティブなことをたくさん書いてしまいましたが、一方で、シンプルなアニメーション(要素が移動するだけ等)はLayoutAnimationを使用することによって簡潔に記述することができるので、少しリッチにしたい、という場合には簡単な実装で実現することができます。
🤮バージョンアップについていくのがツライ
React Nativeは 3ヶ月に1度大きなバージョンアップがあります。まだメジャーバージョンが出ていない(執筆時点で最新バージョンがv0.57.7 )ということもあり、今後破壊的なアップデートが出てくる可能性も多いにあります。
メンテナンスしやすいアプリケーションを維持するためには、バージョンアップ作業は必要不可欠だと私たちは考えています。バージョンアップの詳しいやり方については他の記事に譲ることにしますが、完全に自動化はできない作業なため(手作業でコンフリクトを解消したりする必要がある)、少なからず作業工数がかかります。バージョンアップ作業そのもの以外にも、バージョンアップに伴うライブラリの動作確認、アプリ全体の動作確認などにも工数がかかります。
React Native導入を検討している場合、この頻繁なバージョンアップを受け入れることができるかも事前に考慮しておくべきだと思います。
結論:導入してよかった
ここまで良かったこととつらかったことを書いてきました。開発途中で、AirbnbがReact Nativeから撤退 というショッキングなニュースがあったりして社内がざわついたりしましたが(笑)、React Native導入によってアプリのメンテナが少ないという課題を解決することができたのが私たちにとってはとにかく大きく、結論、React Nativeを導入して良かったなと考えています。
開発中私たちが感じたつらみも、私たちの技術力不足が原因だったことがほとんどで、レベルを上げて物理で殴れば解決することばかりだったかなと今では思っています。いま0から書き直したらもっと良い設計にできるはず。
テストが完全に導入できていなかったり、クロスプラットフォームといいつつAndroidアプリはまだリリースできていないなど、まだまだやりきれてないところもありますが、今後もReact Nativeと仲良くしていければ良いなと思っています。少なくとも僕は今回のプロジェクトを通してReact Nativeのことがだいぶ好きになりました(笑) この記事がこれからReact Nativeを導入しようと迷っている方々の判断材料の一つになればと思います。ここまで読んでいただきありがとうございました!
ほかの開発者からひとこと
若様
冒頭に登場しました @kouchi67 です。僕を救ってくれたReact Nativeですが、Swiftにはないメリット・デメリットがあり、とても勉強になりました。辛い部分もありますが、チーム構成や目的によっては選択肢になりうるのがReact Nativeだと思いますし、少なくとも私達にはFitしてるかなと思いました。このブログを読んで興味を持った方がいたら是非チャレンジしてみてください!
ボギーさん
自分はモバイルアプリエンジニアではなかったのですが、React Nativeを採用することでスムーズに開発に入ることができたと思います。レイアウト周りでWebの知識を活かすことができたことと、Hot Reloadingによる変更の即時反映機能は、React Nativeで得られた大きなメリットでした。もちろん使っていくうちにつらみを感じることもありましたが、手軽にモバイルアプリ開発に手を出せるのは面白いと思います。
おのじゅん
Objective-C、Swiftの遺産やツラミを差し置いても採用する魅力がReact Nativeにはあると思います。React Nativeを通してモバイルアプリを作る楽しさが広がり、面白いアプリが増えたら素敵ですね。
ビズリーチやReact Nativeに興味がある方はこちら👇まで