この記事は CyberAgent Developers Advent Calendar 2024 20日目の記事です。
こんにちは。WINTICKET の Web 版(以降 WINTICKET Web)のリードを担当している @dora1998 です。
WINTICKETはサービス開始から5年半が経過し、技術選定の見直しを時に大胆に進めてきました。そこで、今回はここ2年ほどのリアーキテクチャを振り返り、それぞれどのような課題を解決してきたのかをまとめていきます。
2年での開発生産性の変化
WINTICKET Webでは、ネイティブアプリに比べてリリースが容易に行えるWebのプラットフォーム特性を踏まえ、中長期で目指したい理想像を「事業価値を最速で届けられるチーム」と定義しました。
開発生産性の参考となる実際の指標は、ここ2年で以下のように変化しています。
年間リリース数 | 81回 (2022年) → 123回 (2024年) |
---|---|
月間PRマージ数 | 83 (2022年) → 166 (2024年) |
変更障害率 | 8% (2024年) ※リリースの成功・失敗以外でも起こるため、障害対応回数/リリース回数で計算 |
PRマージ数は2倍、リリース頻度は1.5倍になっており、生産性が向上にしている中でも変更障害率は低い状態にできています。PRやリリースの数がそのまま事業価値の多さにつながるわけではありませんが、より変更を素早くユーザーに届けられる状態になっていると言えるでしょう。
主なリアーキテクチャ
ここからは、リアーキテクチャの一部をピックアップして紹介していきます。
実行基盤の GKE → Cloud Run 移行
当時、WINTICKET WebのSSRなどを行うサーバーはGKE上で実行していましたが、安定したリリースができていない課題がありました。
具体的には、段階的なリリースができていないこと、リリース前に確認するステージング環境ではデータが本番と比べて足りないことがあり、リリースすることへの心理的ハードルが高い状態でした。
そのため、以下の要件を満たすようにリアーキテクチャを行いました。
- Dark Canary 環境の新設
- メトリクス監視も備えた段階的リリース
※Dark Canary環境とは、特定のHTTPヘッダやCookieを持つユーザーのみに提供する検証環境です。通常の環境と同じURLでアクセスできるため、コールバックURLが固定されている機能についても動作確認できることが特徴です。
加えて、Webフロントエンド中心のスキルセットを持つチームでGKEを運用していく負荷の高さもあったため、このタイミングでCloud Runへ移行しました。移行の詳細は以下の記事で紹介しています。
- WINTICKET Web の GKE 脱却と Cloud Run の採用
- WINTICKET Web をゼロダウンタイムで Cloud Run へ移行する際に行った工夫
- WINTICKET Web の Canary / Dark Canary リリースを支える Release Manager の紹介
これによって、
- リリース前に本番に近い状態で動作確認が行える
- Cloud Runのシンプルな構成で、Webチームがオーナーシップを持って改善できるようになる
といった恩恵が得られました。
ReduxからTanStack Queryへの移行
WINTICKET Webでは、API取得を含めた全ての状態をReduxで行っていました。フォルダ構成やテンプレートが整備され、統一されたコードベースではありましたが、以下のような課題が見えてきました。
- API取得の状態を各所で定義する煩雑さ
- リクエスト中・エラー発生のフラグ
- リクエストを一意なキーに変換して、取得結果をリクエストごとに分離
- Entityごとに正規化することによる依存関係の複雑さ
- 別々のAPIに同じEntityが含まれていた場合、Entityごとにstateの同じ場所に正規化して格納していたので予期せぬ壊れ方をすることがあった
この時点でRedux周辺の記述は8万行ほどの規模になっていましたが、機能開発と並行しながら約半年で全体を移行完了することができました。移行の詳細は以下のスライドにて紹介しています。
API操作を全てTanStack Queryへ移行することによって、
- 状態管理のコード量が35%減
- データフローがシンプルになる
といった成果を得ることができました。
PR Dark Canaryの導入
前述のTanStack Queryへの移行はデータ取得層の大きな改修を伴ったため、トランクベース開発ではなく、トピックブランチで開発を進め、QCでデグレがないことを確認してからリリースする手順を踏んでいました。
しかし、認証やチャージといった外部システムと連携する箇所については、開発環境でもコールバックURL等が固定されているものが多く、Pull Requestごとに作成されるプレビュー環境ではQCができない状態となっていました。
そのため、QCのためにDev環境へ反映するべく、一度PRをマージするといった運用がなされ、QC中に別の機能を本番環境へリリースする際は一旦QC中の差分をmainブランチからRevertする運用が行われていました。
ここで、「同一URLで異なる環境に接続できる」というDark Canary環境の特徴が実装段階やQCでも大きな効果を発揮することがわかったため、Dark Canary環境を拡張し、同一URLでPRごとの環境に接続できるようにする改修を行いました。これを私たちは「PR Dark Canary環境」と呼んでいます。
PR Dark Canary環境は、Cloud Runのサイドカーを活用して実現しており、詳細は以下の記事で解説しています。
PR Dark Canary環境によって、動作確認を経ていない変更がmainブランチへ一旦マージされる状況をなくすことができ、本番リリース時の作業が大幅に短縮されました。
管理画面のリアーキテクチャ
Webチームでは、サービス本体の開発に加えて、社内で日々の運用を行うための管理画面の開発も担当しています。管理画面はサービス本体と比較して実装工数が確保しづらく、その状況でも少しでも快適に開発しようと複数のアーキテクチャが混在するキメラ状態になっていました。
管理画面はWebpackを使ったシンプルなReactのSPAですが、
- 状態管理層(ほぼAPIキャッシュ)にunstated, Recoilが共存している
- 徐々にRecoilに移行していく予定だったが、無限スクロールや取得結果の更新など一部仕様を実装する上で煩雑になる課題があった
- メンテナンス状況的にもRecoilの実装箇所を今後さらに増やすのは好ましくない
- File-based Routingではなく、パスに対応するページが探しづらい
- 規約も不十分だったため、配置が実装者によって若干ばらつきがあった
という課題が存在しました。
事業が拡大する中で、社内で運用上の要望も多く寄せられるようになり、以下の改修を行う意思決定をしました。
- サービス本体で採用実績があるTanStack Queryを導入
- unstated, Recoilのうち、特に古いunstatedを使った実装をTanStack Queryへ完全移行
- WebpackからViteへ移行
移行を進める中で、Viteへ移行したことでFile-based Routingに対応するTanStack Routerも採用できる状態になったため、React Routerからの載せ替えも行いました。
ルーターの載せ替えにあたっては、ASTベースの移行ツールを開発することで個別のページごとの手作業をほぼゼロにすることができました。詳細は以下のスライドをご覧ください。
管理画面のリアーキテクチャにより、複数世代のアーキテクチャが混在していた複雑さが減り、TanStack RouterやViteの採用で開発体験も大きく向上しました。
現在は、管理画面へのコミッターをWebフロントエンドチーム以外にも広げ、ネイティブアプリやバックエンドを開発するメンバーにもコミットしてもらうことで、より多くのエンジニアで運用上の課題が解決できる状態作りを進めています。
意識していたこと
課題ファーストのリアーキテクチャ
特にWeb周辺は新たなライブラリ・ツールチェインが日々登場し、技術トレンドを大きく塗り替えていくこともあれば、そうでないこともあります。
当たり前の話ではありますが、なんとなく古いから、ではなく、新しいライブラリ・ツールチェインを導入することで何が解決できるのかを意識して優先順位を定めることを改めて大切にしています。
モブプロの活用
私たちのチームでは週2回モブプログラミング(以下モブプロ)を行っています。題材は日によって様々ですが、新しい技術の検証や運用上の課題を解決するスクリプトの作成などに取り組むことが多く、チームの技術的好奇心を満たす場として機能しています。
また、TanStack Query移行のような全員が関連するアーキテクチャの変更も、最初はモブプロで行うことで理解度を揃えた状態で移行を進めることができました。
おわりに
ここまで、直近2年の技術的に大きく変化したWINTICKET Webを振り返ってきました。それぞれの詳細はすでに出ている記事を参照する形にはなりましたが、WINTICKET Webが最速で事業価値を作り出せるチームを目指して、どのように開発上の課題に日々向き合ってきたか、一連の流れを少しでも感じていただければ幸いです。
もちろん解決したい課題は今なお多くあり、直近では、
- デザインシステムの設計・実装
- スキーマ定義をもとにしたAPIクライアントの自動生成
などに取り組んでいます。また新たな取り組みができた際には紹介できればと思いますので、ぜひ今後の活躍にもご注目ください!