- バックエンド / リーダー候補
- PdM
- Webエンジニア(シニア)
- 他18件の職種
- 開発
- ビジネス
こんにちは、ウォンテッドリーで iOS エンジニアをしている林です。
この記事は、Wantedly Advent Calendar 2024 の 15 日目の記事です。昨日は紀平さんによる「速さが鍵!グロースチームのプロダクトデザイナーのシゴト」という記事でした。
はじめに
この記事では 2024 年に行った内部改善の取り組みについて振り返りたいと思います。ウォンテッドリーのエンジニア組織では負債返済日という文化があり、月に一日使って負債の解消に取り組みます。
Mobile Chapter では Swift Package Manager (SwiftPM) への移行と Renovate 導入、また SKIE の導入などについて取り組みました。それぞれについて当時の課題とともにどのように進めたかを紹介します。
Swift Package Manager への移行
Wantedly Visit の iOS アプリではレイヤードアーキテクチャから Feature モジュールベースの構成に移行を進めている状態です。大まかには以下の図のようなモジュール構成です。外部ライブラリ(図中の 3rd-partry Libraries)は、必要とされるモジュールから依存されています。
なぜやったか
当時パッケージ管理システムに CocoaPods を用いていましたが、 今回以前の SwiftPM 検証の取り組みの結果として XcodeGen の project.yml 上でもパッケージ管理されるライブラリが混在していました。そのため Podfile と XcodeGen の project.yml それぞれでパッケージを管理する点、それぞれのパッケージ管理システム上で使用されるライブラリが重複しないように注意が必要な状況でした。
また、新規機能開発する際はソースコード以外に Info.plist やコンフィグファイルなどボイラープレートな構成を準備する必要があり、それだけで PR を分けて進めるなどの運用を行っていました。
これらは新規メンバーの参画の際に大きな認知負荷となっていたため、これらの課題の解消に向けて本格的に移行を進めることにしました。
どうやったか
移行はこのようなタイムラインで取り組みました。基本的には一つずつパッケージ定義を Podfile から project.yml へ移動を進めましたが、一部パッケージの移行の際に Xcode Previews が動作できなくなる問題に遭遇しました。別の検証によってマルチモジュールの各モジュールを SwiftPM の Target に当てはめた構成であれば、そういった問題は回避できそうなことが並行して把握できたため、2024 年 2 月のタイミングで Pacakge.swift を用いた方式に切り替えました。
従来の Xcode 上でのモジュール定義を SwiftPM の Target に移行するには、全てまとめて置き換える必要があり、その間他の開発が困難となってしまいます。そのためシンボリックリンクなどを活用して、現行のプロジェクト構成で引き続き開発が行える状態を維持しつつ、しばらく並行して Package.swift でのモジュール定義の準備を進めました。Package.swift 側の構成でビルドが成功することまで確認できたら、最後に一気にアプリケーション以外のモジュールを Package.swift のものに切り替えて移行が完了しました。
導入結果
結果として CocoaPods から SwiftPM でのパッケージ管理に一本化することができ、挙げていた課題を解消することができました。
副次的な効果として当時のアプリのダウンロードサイズを 30.1MB→26.9MB と 10% ほど削減することもできました。これはもともと全て動的フレームワーク形式で扱われていたモジュールが、 SwiftPM によるパッケージ管理によって適宜静的ライブラリで扱われることになり、未使用シンボルの削除などのリンク時の最適化が働いた結果だと考えられます。
移行については「 Mobile勉強会 Wantedly × チームラボ × Sansan 13」でも発表しましたのでそちらの資料もぜひご覧ください。
Renovate の導入
なぜやったか
SwiftPM への移行のモチベーションの一つとして Renovate の導入がありました。Renovate の導入以前はパッケージの更新をエンジニアが不定期に行っていました。そのため更新のあるパッケージの見逃しや、そもそも更新情報を能動的に見に行く必要があり、それによってより更新が不定期となる等の課題がありました。
わたしたちのプロジェクトでは以下の要因が複合的に絡んで Podfile の更新に難があったため、 Renovate の導入が見送られていました。
- Renovate の実行環境が macOS ではなく、かつ任意の処理を挟むなどの実現が困難だった
- Podfile を更新するために必要なプロジェクトファイルを XcodeGen によって生成していた
- KMP のリポジトリをプライベートな podspec として取り込んでいたため認証の問題があった
これらの点は、SwiftPM へ移行できれば解消できると仮説があったため、SwiftPM への移行によりRenovate の導入も可能になる算段がありました。
どうやったか
実際に導入を試みたところ、SwiftPM 移行以前は先に挙げた課題等があったため、中々進展がありませんでした。しかし、移行後は目立ったトラブルもなく導入が進みました。
一点 Renovate では Package.resolved の更新は現在サポートされていないため、わたしたちのワークフローでは Renovate が作成したブランチで Package.swift に差分があったら、 Package.resolved を更新してコミットを行うワークフローを取り入れています。
# Bitrise でのワークフロー例
trigger_map:
- changed_files: VisitPackage/Package.swift
push_branch: renovate/*
type: push
workflow: resolve_package
導入結果
それらによってパッケージの更新状況が可視化されるようになり、 Renovate による PR をストレスなくマージできる運用が実現できました。
SKIE の導入
2024 年後半には SKIE の導入も進めました。SKIE は KMP で定義された定義を、より Swift で扱いやすくするためのツールです。例えば Kotlin の sealed class が Swift でも網羅性チェックが行える enum の形式でエクスポートされるようになります。
なぜやったか
iOS エンジニアが KMP を扱う際の主な課題として、Kotlin で定義した型が Objective-C ベースで生成されるため、 Swift では扱いづらくなる点がチームメンバー内からも挙がっていました。そのため iOS 側のプロジェクトに取り込む際に Swift 側で型をラップするなど、ひと手間加えた運用などを行っていました。
具体例に関しては iOSDC Japan 2024 でのセッションでも紹介しています。
どうやったか
導入時の懸念として、今までの XCFramework をビルドするフェーズに加え、 SKIE による Swift インターフェース作成処理が行われるため、ビルド時間の増加などがありました。
この課題に対応するため、まず不要な定義が公開されないようにアクセス範囲の整理を行いました。Kotlin ではデフォルトの可視性が public であり、わたしたちの KMP ではデフォルトのままの箇所が多く必要以上に public 扱いになっていました。そのため Swift からも扱うユースケースに該当する定義は public とし、それに対する実装部などは internal であることを明示しました。
interface ApplyProjectUseCase {
suspend operator fun invoke(...)
}
internal class ApplyProjectUseCaseImpl(...) : ApplyProjectUseCase {
override suspend fun invoke(...) { ... }
}
導入結果
iOS 側のプロジェクトへの SKIEに対応した KMP の取り込み自体は、定義が class から enum へ変わることによる破壊的変更などはありましたが、大きな問題なく取り込むことができました。懸念されていた KMP のビルド時間についても、最近の SKIE を利用する限りでは特に目立った増加は見られませんでした。まだ導入直後ではありますが、まずは Swift 側でひと手間掛けてラップしていた対応から開放されました。
まとめ
これらの結果、新規機能開発において新しいモジュールを導入することが容易となり、ライブラリの更新も Renovate 導入以前よりエンジニアの負担なく活発に取り込めるようになりました。また SKIE については導入を始めた段階なので、これから検証を行いながら開発の質を向上させるために役立てていきたいと思います。
まとめとして負債返済日を活用しながら、こつこつカイゼンを進めていくことで最終的には開発を加速することができるようになりました。ただしマルチモジュール構成など今までの構成で移し終えただけなので、まだまだ次のカイゼンに向けて取り組める下地が整った段階です。
わたしたちは今後も様々な改善を行っていきます。そんな挑戦に一緒に取り組んでくれる仲間をお待ちしています。