はじめに
こんにちは、ZOZOTOWN開発本部でZOZOTOWN iOSの開発を担当している小松です。私たちは、チームがより効率的かつスケールしやすい開発環境を構築するために、Swift Package Manager(以下SPM)への移行をはじめとして様々な取り組みを行いました。本記事では、その過程で得られた知見と実践した内容についてご紹介します。
背景と動機
ZOZOTOWN iOSは日々進化しています。加えて開発に携わる人が増えたことで、コンフリクトの増加やメンテナンスコストの増加などの課題が増え、開発基盤の改善が急務となりました。将来的なメンテナンスコストの削減と開発効率の向上を目指し、以下の動機に基づき改善活動を開始しました。
- スケールしやすい基盤作り
- アプリの成長に合わせた柔軟な開発環境の構築
- チームにとって開発しやすい体制
- 開発者のストレスを軽減し、生産性を向上させる環境整備
- 長期的なメンテナンスのしやすさ
- 将来的なトラブルを未然に防ぎ、長期的な安定稼働を実現
課題
ZOZOTOWN iOSは、その規模と複雑さから、いくつかの重要な課題に直面していました。
- ビルド権限の複雑さ
- ビルド権限の付与がチーム内で完結せず、ビルド可能状態に持っていくまで時間がかかる
- コンフリクトの多発
- チームの人数や並行プロジェクト数が増えていくにつれてpbxprojファイルのコンフリクトが多発していた
- メインのライブラリ管理がCocoaPodsだった
- CocoaPodsのメンテナンスモードが発表され1、近いうちに脱却の必要があった
- pbxprojによるパッケージ管理では、ライブラリ間の依存関係が明確に把握しにくい
- 現在使用しているライブラリとその依存関係などが把握しづらかった
- ライブラリが古いバージョンのまま放置されている
- 手作業でのバージョンアップには、時間と手間がかかる
解決策とアプローチ
これらの課題を解決するために、私たちは以下のアプローチを取りました。
1. 権限管理の改善
ビルド権限が複雑になってしまっているため、シンプルな構成になるように改善しました。
ZOZOTOWNにはZOZOMAT/ZOZOGLASSといった計測機能が含まれています。これらはニュージーランドにある子会社のZOZO NEW ZEALAND LIMITED(以下ZOZO NZ)が開発したSDK(C++)を、社内の別チームがSwiftでラップしたものを使用しています。SDKのPackage.swiftはZOZO NZのリポジトリで管理していました。本体のXCFrameworkはJFrog2のストレージサービスで管理されていました。
つまりZOZOTOWNをビルドする際には、株式会社ZOZOのOrganizationへのアクセスだけではなく、ZOZO NZのOrganizationとJFrogへのアクセスが必要でした。特に、JFrogの権限付与はJFrogの仕様やZOZO NZとの時差により、スムーズに進めることが難しい状況でした。また、英語でやりとりできるメンバーが限られていたためコミュニケーションが属人化していました。こうした背景があり、ZOZOTOWN iOSをビルド可能な状況にするまでに時間がかかってしまっていました。
そこで計測ライブラリのRepositoryを自社Organization内にmirrorとして作成し、XCFrameworkをRelease Assetに配置しました。結果としてJFrogへの依存を解消し、権限付与をチーム内で完結、ビルドを簡略化することに成功しました。
2. Package.swiftによるライブラリの依存管理の導入
ライブラリが長い期間更新されておらず依存関係が把握しづらい問題についての解決策としてPackage.swiftを導入しました。導入にあたってはiOS界隈でよく見られる一般的なマルチモジュール構成ではなく、ライブラリの依存のみを管理するPackageを作成しました。こちらは下記を参考にしました。
これにより、依存関係の可視化と管理が容易になりました。
Package.swiftがあれば、下記コマンドで依存関係をグラフにできます。
swift package show-dependencies --format dot | dot -Tpng -o graph.png
こちらが実際に出力された依存関係の図です。一部社内ライブラリを黒塗りにしています。
詳しい解説はこちらにまとめているので、気になる方は参考にしてみてください。
また、Package.swiftがあることによって自動でライブラリの更新のPRを作成しやすくなりそうです。まだ、ZOZOTOWNにはその仕組みはありませんが今後対応していこうと思います。
3. Group参照からフォルダ参照への変更
ZOZOTOWNがXcode 16に対応したタイミングで、pbxprojのコンフリクト問題を解消するために、Group参照からフォルダ参照へ変更しました。3これにより、プロジェクトファイルの競合が大幅に減少し、開発効率が向上しました。この変更によってかなり開発は楽になりましたが、参照の仕組みそのものが変わるため影響も大きいです。仮にGroup対応したPRをリバートしようものなら大変になることが想定されるので、タイミングをよく見ながらやったほうがいいなと感じました。
4. SPM移行とTool系ライブラリの改善
ZOZOTOWN iOSでは以前から一部ライブラリの管理にSPMを使用しており、導入したタイミングから完全移行を検討していました。しかし、Xcode 15系でSPMを利用するとブランチの切り替えでpbxprojファイルが変更し、SPMキャッシュが揮発しました。そのため、キャッシュが効かず再度ライブラリをダウンロードする必要になるため移行を躊躇していました。この問題がXcode 16で解消されたこと、CocoaPodsがメンテナンスモードに入ったことを機に、SPMへの完全移行を進めました。
完全移行するにあたっては、下記の順番で進めていきました。
- 使用しているライブラリがSPMに対応しているかを確認する
- SPM対応のバージョンへのアップデートがあるライブラリのアップデート
- 複雑そうなTool系のライブラリをアップデート
- その他のライブラリをアップデート
Tool系のライブラリの移行
上記項目の中でもTool系のライブラリのアップデートが一番苦戦しました。ZOZOTOWNで使用しているTool系ライブラリはSwiftGenとLicensePlistの2つです。どちらもBuildToolPluginには対応していましたが、ZOZOTOWNで使用していたユースケースとは微妙に合わずすんなり移行とは行きませんでした。SwiftGenについては、Xcode 16のAsset Symbols生成機能4を利用することで、ツール自体を廃止し、より効率的なリソース管理を実現しました。LicensePlistについては、SPM経由での導入を避け、Homebrew経由でインストールして使用するようにしました。GitHub Actionsを組み合わせることで、プロジェクトからの切り離しとライセンス情報の自動更新を可能にしました。
複雑な依存関係におけるリンカのエラー
ここも大きく詰まったポイントでした。ZOZOTOWN iOSはネットワークモジュールをAPIClientとして別Targetに切り出しており、その依存の関係は下記のようになっていました。A、BというライブラリはCocoaPodsで管理されており、特にBはZOZOTOWNとAPIClientの両方で使用されています。
それをそのままSPMへと移行したところ、以前からSPMで管理されていたライブラリ(図中のC)でリンク時にエラーが出るようになりました。
こちらも苦戦しましたが、直接的にリンカの問題を解決するのではなく、構成管理そのものを見直しました。最終的な結果としては、APIClientのターゲットごとSPMで管理するようにすることで問題を解消し、よりシンプルな構成にできました。
これらの問題はありましたが、無事ZOZOTOWN iOSはCocoaPodsから完全に脱却し、晴れてライブラリ管理を全てSPMへと移行できました。
得られた効果
これらの取り組みをやったことで様々な効果を得ることができました。
そのうちの1つとして、ジョインからビルドできるようになるまでの時間の高速化に成功しました。今までは新しいメンバーが参画した際にZOZOTOWN iOSをビルドしてタスクに取り掛かれるまでによくて半日、悪くて数日かかってしまうこともありました。ビルド構成をシンプルにしていくにつれ、業務参加から30分程度でビルドまで持っていくことができるようになり、業務開始時におけるボトルネックの解消に成功しました。
また、誰でもビルドできるようにしたことで他チームのメンバーがZOZOTOWN iOSをビルドするというケースが増えました。ZOZOTOWNはZOZOの中でも事業の柱であるため、ネイティブだけではなくWebView側でも日々新しい機能が追加されています。今までは、Web側のチームメンバーが動作確認をしたい場合ネイティブチームへと連絡し、調査してもらう必要がありました。双方で割り込みや待ち時間が発生していましたが、Webチームが簡単にビルドできる状態になり、不具合調査や修正依頼がスムーズになり、互いにメリットが増えました。
まとめ
本記事では、ZOZOTOWN iOSチームが行ったスケールしやすい開発基盤作りの取り組みについて紹介しました。私たちの経験が、他の開発チームの参考になれば幸いです。私たちは、今後も継続的な改善活動を通じて、より堅牢な開発基盤を構築していきます。
最後に
ZOZOでは、一緒に大規模なサービス作りをしてくれる方を募集しています。ご興味のある方は、以下のリンクからぜひご応募ください!
- https://blog.cocoapods.org/CocoaPods-Support-Plans/↩
- https://jfrog.com/↩
- https://developer.apple.com/documentation/xcode-release-notes/xcode-16-release-notes#Project-Management↩
- https://developer.apple.com/documentation/xcode-release-notes/xcode-16-release-notes#Asset-Catalogs↩