2024.10.01
自社の社内情報を未来の“ゴミ”にしないための備え 「情報量が多すぎる」時代がもたらす課題とは?
ReactNativeのアプリをモダンSwiftに置き換えてます(全1記事)
リンクをコピー
記事をブックマーク
大門弘明氏:それでは「React Nativeで書かれたアプリをSwiftで書き直しています」の発表を始めます。
まずは自己紹介をします。名前は大門と申します。2014年に新卒で合同会社DMM.comに入社して、iOSエンジニアとしてオンラインサロン事業部でお仕事をしています。
本日お話しすることですが、つらい気持ちの話と、アプリ設計の紹介を少ししようと思っています。僕にとってReact Nativeはつらい。
そもそも何を作っているのかというと、オンラインサロン専用コミュニティを会員が利用するためのiOSアプリを作っています。主な機能として、投稿や返信などのタイムラインを確認できたり、ライブ配信の視聴、あとはオーナーの投稿などのプッシュ通知が受け取れたりするアプリです。
まずこのアプリが抱えている課題のお話をします。1つ目、プロジェクトのアップデートがとてもしんどいです。iOSプロジェクトは、毎年のアップデートなど、Appleの方針に従って変更を続けていかなければなりません。これはどのプロジェクトでも同じです。
それに加えて、React Nativeのアップデートはかなりしんどいものでした。React Native自体が公式のものではないので、常に最新のXcodeに対応しているわけでもなく、一筋縄ではいきません。
そもそも僕はこのプロジェクトで初めてReact Nativeに触れたので、React Nativeがわからなくて、見慣れない構文だらけのJavaScriptを使うのがかなりつらかったです。
2つ目ですが、アップデートのしんどさも相まってReact Nativeが負債化していました。イケてるアプリを作るためにはiOS、Swift、JavaScript、React Nativeあたりのすべての深い理解が必要です。
当アプリは当初フロントエンドエンジニアが開発していたという背景があり、ほぼすべてがReact Nativeで作られています。iOSの知見が足らず、開発する際の足枷になるなどの課題はあったかと思うんですが、iOSエンジニアがいなかった当時としては最適な選択だったかなと思います。
しかし時は流れて、品質や開発スピードの改善のためにアプリへ投資して、iOSエンジニアにきちんと作ってもらうという事業判断になりました。今は僕も含めてiOSエンジニアが3名いるのですが、今度はJavaScriptやReact Nativeの知見不足が足かせになり、あまり得意分野を活かせず、開発のスピードが出ないということになってしまいました。
また、React Nativeで書かれてはいるものの、現在対応プラットフォームはiOSのみで、あまりReact Nativeのメリットを活かせていません。React Nativeをこのまま使い続けていくとデメリットの部分に苦しめられ続けることになりそうです。
ここまでの話から、開発の足枷になってしまったReact Nativeを脱却して、Swift化しようという話になりました。次はそのお話しをします。
React NativeからSwiftの移行はつらいが無理ではない。ということで、我々がReact NativeのアプリをSwift化した流れを簡単に紹介します。
その1、XcodeとReact Nativeを最新の状態にアップデートします。最新のXcode、React Nativeでビルドできるように、まずはひたすらエラーや問題を取り除いていきます。
その中で、一部のライブラリがアップデートできない場合があります。具体的には仕様が変わっていて、アップデートすると動作が保証できないものや、そもそも最新のXcodeやReact Nativeに対応していないもの、対応中のプルリク状態でマージされていないものなどです。
こうしたライブラリはpatch-packageを利用して修正しました。patch-packageはnpmでインストールしたライブラリにパッチを当ててくれるツールです。JSファイルだけではなく、ネイティブの.mファイルや、podspecファイルなどもこれで修正できます。
例えばXcode12に対応するためには、React Native用ライブラリのネイティブ部分がその依存関係を書き換えなければいけないんですね。その対応が行われているライブラリと行われていないライブラリがありました。
行われていないライブラリや、あえて古いバージョンを利用したいライブラリなどは手動でパッチを当てて対応をしています。地道な作業を繰り返して、まずはXcodeとReact Nativeのバージョンを最新のものに追いつかせます。
次はいよいよSwift化の基盤を作っていきます。今日はそのおおまかな設計の話をします。DMMには事業部などの縦割りの組織のほかに、横串のエンジニア支援の部署があって、社内推奨のアーキテクチャがあります。
iOSの場合はVIPERライクの設計になっているので、こちらをベースにして社内での技術の流動化を図ろうと思いました。また、いずれ消えゆくReact Nativeの部分は1つのモジュールとして、そのほかの機能もモジュールで分割するマルチモジュールな設計にしました。
スライドには出ていませんが、リアクティブプログラミングのフレームワークはRxSwiftではなく、純正のCombineを採用しています。
この図は、とある画面の構成を簡単に表したものです。一番上のViewControllerはUIの更新とPresenterへのイベントの通知のみを担当します。イベント通知はスライド上ではディスパッチとなっている部分です。
Presenterは、受け取ったイベントをもとにInteracterにビジネスロジックを依頼して、結果に応じてViewControllerのあるべき状態を通知、もしくはルーターに画面遷移を依頼します。画面の構成は以上です。VIPERライクな画面の作り方になっています。
次にマルチモジュールの全体像です。Featureと呼ばれる部分が、画面や機能のまとまりごとにモジュールとして分割されます。React Nativeの部分も1つのFeatureとしてモジュール化しています。メインターゲットはいわゆるInfrastructure層の実装や、DI、各種Featureの呼び出しなどを行います。
先ほどの図では依存関係がちょっとわからないので、依存関係を簡単に表した図も用意しました。このCoreとCommonって何ぞや? と思った方がいるんじゃないかと思うので説明します。
Commonは、Swift本体の拡張などほかのプロジェクトにソースコードをそのままコピー&ペーストしても動くコードを置いています。例えば、文字列をスネークケースに変換するとか、Stringクラスの拡張とかですね。Coreは、アプリケーション固有のグローバルオブジェクトや、VIPER関連の基底クラスなどを置いています。
次に、React NativeとSwift間のやりとりをどのようにして行っているかを紹介します。これはReact Nativeを利用したアプリのユニークな部分だと思います。
アプリでは、1個1個の処理に対してネイティブ側にインターフェイスを持たせるのではなく、Swift側から見たときにイベントを受信するためのSubjectと、送信するためのメソッドのみを用意して、enumで定義したイベントオブジェクトが流れるPub/Subのような仕組みを作りました。
図にするとこんな感じです。真ん中のBridgeModuleはイベントの送受信以外の振る舞いを持たず、ハブのような役割に徹します。React Nativeからイベントを受信したい場合は、Swift側からBridgeModuleが提供しているSubjectを購読して、流れてきたイベントに応じて処理を実行します。
React Native側にメソッドを公開できるRCT_EXTERN_METHODというマクロを利用して、BridgeModuleのreceiveFromRNというメソッドをReact Native側から呼び出します。React Nativeにイベントを送信する場合はこれを呼び出すだけです。
React Native側は、初期化時にNativeEventEmitterというところにaddListenerしてイベントが流れてくるのを待つだけです。
このNativeEventEmitterは、React Nativeで標準で搭載されているネイティブとの連携の仕組みです。Swift側はnotifyToRNというメソッドにイベントを載せて呼び出して、React Nativeはそのイベントを受け取ります。
簡単にですがコードも載せてみました。Swift側はreceivedEventというSubjectとnotifyToRNメソッドだけを意識すれば、React Native側とやりとりが行えます。
Swiftファイルとは別にObjective-Cのファイルがあるのは、SwiftではRCT_EXTERN_METHODやRCT_EXTERN_MOJULEなどのマクロを利用できないからです。この部分だけObjective-Cで書いています。
推奨アーキテクチャと、マルチモジュールの設計と、Pub/Sub上でReact NativeとSwiftがメッセージをやりとりする仕組みが整ったら、あとは段階的にSwift化していきます。
具体的には影響範囲の少ない末端の画面からSwift化していきます。なぜならSwift化の途中で新規機能の開発などが入る可能性があるからです。そのためSwift化が完全に終わらなくてもアプリをリリースできる状態にしておく必要があります。
また、末端の画面以外からSwift化をしてしまうと、SwiftからReact Nativeに遷移して、またそこからSwiftの画面に遷移して、さらにそこからReact Nativeの画面に遷移するという状況が生まれてしまいます。その場合、単純にコントロールが難しくなり、依存関係も複雑になってしまいます。このような理由から末端の画面から順番に移行していきます。
末端の画面からSwift化しているイメージを説明します。この矢印は単に画面遷移のおおまかな順番を表しています。我々はこの青い部分を通称で第1弾と呼んでいます。先ほど紹介したSwift化の基盤部分と、どうしても先にSwift化しておかないとスムーズに移行が進められないと判断した画面などのことです。
これらを先にSwift化して、この時点でいったんリリースが可能な状態になります。そのあとに各末端画面や、中間の画面を順番にSwift化していくフェーズを第2弾、第3弾と呼んでいます。
ここまで、我々がどのような流れでReact NativeのアプリをSwift化しているのかを紹介しました。現状はまだリリースされていないですが、第1弾まで作業が完了しています。これから多くの課題が出てくるんじゃないかと思ってはいるので、機会があればそういったことも紹介したいと思います。
今日のまとめです。僕にとってReact Nativeはつらいという気持ちの表明と、Swift化の流れと設計を紹介しました。React NativeからSwiftへ移行するのは楽ではないですが、一つひとつの課題をクリアして着実に前へ進んでいます。
以上です。ご清聴ありがとうございました。
2024.10.29
5〜10万円の低単価案件の受注をやめたら労働生産性が劇的に向上 相見積もり案件には提案書を出さないことで見えた“意外な効果”
2024.10.24
パワポ資料の「手戻り」が多すぎる問題の解消法 資料作成のプロが語る、修正の無限ループから抜け出す4つのコツ
2024.10.28
スキル重視の採用を続けた結果、早期離職が増え社員が1人に… 下半期の退職者ゼロを達成した「関係の質」向上の取り組み
2024.10.22
気づかぬうちに評価を下げる「ダメな口癖」3選 デキる人はやっている、上司の指摘に対する上手な返し方
2024.10.24
リスクを取らない人が多い日本は、むしろ稼ぐチャンス? 日本のGDP4位転落の今、個人に必要なマインドとは
2024.10.23
「初任給40万円時代」が、比較的早いうちにやってくる? これから淘汰される会社・生き残る会社の分かれ目
2024.10.23
「どうしてもあなたから買いたい」と言われる営業になるには 『無敗営業』著者が教える、納得感を高める商談の進め方
2024.10.28
“力を抜くこと”がリーダーにとって重要な理由 「人間の達人」タモリさんから学んだ自然体の大切さ
2024.10.29
「テスラの何がすごいのか」がわからない学生たち 起業率2年連続日本一の大学で「Appleのフレームワーク」を教えるわけ
2024.10.30
職場にいる「困った部下」への対処法 上司・部下間で生まれる“常識のズレ”を解消するには