2024.12.24
ビジネスが急速に変化する現代は「OODAサイクル」と親和性が高い 流通卸売業界を取り巻く5つの課題と打開策
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へ移行するのは楽ではないですが、一つひとつの課題をクリアして着実に前へ進んでいます。
以上です。ご清聴ありがとうございました。
2025.01.16
社内プレゼンは時間のムダ パワポ資料のプロが重視する、「ペライチ資料」で意見を通すこと
2025.01.15
若手がごろごろ辞める会社で「給料を5万円アップ」するも効果なし… 従業員のモチベーションを上げるために必要なことは何か
2025.01.20
組織で評価されない「自分でやったほうが早い病」の人 マネジメント層に求められる「部下を動かす力」の鍛え方
2025.01.14
目標がなく悩む若手、育成を放棄する管理職… 社員をやる気にさせる「等級制度」を作るための第一歩
2025.01.09
マッキンゼーのマネージャーが「資料を作る前」に準備する すべてのアウトプットを支える論理的なフレームワーク
2025.01.14
コンサルが「理由は3つあります」と前置きする理由 マッキンゼー流、プレゼンの質を向上させる具体的Tips
2025.01.07
1月から始めたい「日記」を書く習慣 ビジネスパーソンにおすすめな3つの理由
2025.01.21
言われたことしかやらないタイプの6つの言動 やらされ感が強く他人任せなメンバーを見極めるチェックリスト
2017.03.05
地面からつららが伸びる? 氷がもたらす不思議な現象
2015.11.24
人は食事をしないとどうなるか 餓死に至る3つのステップ
特別対談「伝える×伝える」 ~1on1で伝えること、伝わること~
2024.12.16 - 2024.12.16
安野たかひろ氏・AIプロジェクト「デジタル民主主義2030」立ち上げ会見
2025.01.16 - 2025.01.16
国際コーチング連盟認定のプロフェッショナルコーチ”あべき光司”先生新刊『リーダーのためのコーチングがイチからわかる本』発売記念【オンラインイベント】
2024.12.09 - 2024.12.09
NEXT Innovation Summit 2024 in Autumn特別提供コンテンツ
2024.12.24 - 2024.12.24
プレゼンが上手くなる!5つのポイント|話し方のプロ・資料のプロが解説【カエカ 千葉様】
2024.08.31 - 2024.08.31