何をしたのか
はじめまして、VPoTの稲田です。
20年ほどJavaで開発を続けてきたAIMSTARというプロダクトを、1年ほどでVue3, Goによってフルリニューアルました。
AIMSTARは、開発初期はオンプレ環境などでパッケージ版として提供しており、数年前にクラウド版に移行したいわゆるエンタープライズ向けのSaaSです。
また、このリニューアルプロジェクトは単に使用言語を変えるだけではなく、「UIUXの全面的刷新」および「マイクロサービス化・マルチテナント化」を同時に達成し、プロダクトとして大きく躍進するための野心的なプロジェクトでした。
レガシーシステムをリプレイスする予定の方々にとって、少しでも参考になる記事になればと思います。
前提:プロダクトと組織体制について
リニューアルそのものについて書く前に、このプロジェクトの前提を簡単に説明しておきます。
エンタープライズSaaS AIMSTAR
本記事で取り上げているAIMSTARというプロダクトは、「お客様のデータを取り込み、事業成長を促進する分析・施策実行を支援する」、主にエンタープライズ向けのSaaSになります。
いわゆるCDP(Customer Data Platform)とMA(Marketing Automation)を組み合わせたようなSaaSで、全体で1日あたり数億レコードのデータを取り込み、数千万件から数億件の配信(Eメールやアプリプッシュなど)を行う、技術的難易度が比較的高いものになります。
オンプレとクラウドが入り混じる提供環境
長年提供し続けてきたプロダクトなので、提供環境も様々です。
クラウドで提供しているお客様もいますが、オンプレで提供してるお客様もいらっしゃいますし、さらに機能に個別のカスタマイズを入れて提供している環境もあります。そのため、そもそも既存機能がどういったものなのか・どう使われているのかをまとめるのが比較的難しい環境でした。
プロダクト開発チーム・サイクルの不在
上述のようにカスタマイズを入れられるパッケージ販売をしていたため、いわゆるSaaS開発的なプロダクトサイクルが存在していないような状況でした。また明確にQAやSREチームなども存在しておらず、開発者当人やCSチームなどが中心になってQAや監視周りを担当していました。
そのため、そのようなチームやサイクルを同時に構築していく必要がありました。
QAチーム・SREチームの組成については別の記事で詳細に扱おうと思います。
どのようにリニューアルしたか
上記のような障壁がある中で、どのようにリニューアルしたかについて説明していきます。
自分がシステムのフルリニューアルをするときに知れると嬉しかった情報を現場感に即して具体的にお伝えできたらと思います。
リニューアルのスケジュールとROIについて
既存システムをリニューアルするということは、新規開発の多くをストップする判断になることと思います。 そうなると、事業を運営する上では「どのタイミングから新規開発を再開できるようになるのか」つまりリニューアルはいつ終わるのかというのを事前に確定させていく必要が出てきます。
結論で言うと、事前に工数/スケジュールを予測・計画することはしませんでした。 もし全ての機能をそのままのデザイン・仕様にしてプログラミング言語を切り替えるだけであればスケジュール予測はある程度成立すると思いますが、ほぼ全ての機能の仕様見直し・機能の統廃合を行うプロジェクトだったため、無意味な見積もりになると思い、特に厳密な工数計算をすることはありませんでした。
代わりにやったこととしては
- 決め打ちで1年とスケジュールを置く。 そこに間に合うような形で、リニューアル内容のスコープをプロジェクトを進めながら調整していく。
- 全ての機能のリリースが間に合わなかったとしても、一部の機能群だけを先にリニューアルしてリリースできるような技術的仕組みを整えておく。
です 「会社全体で意思疎通をはかるためスケジュール自体は一旦決めるが、スケジュール通りにならなくてもダメージを出来るだけ小さくする」ようなスタンスで取り込んでいました。
リニューアルする上でのスケジュールを決める必要もあったのですが、「そもそもリニューアルをすべきなのか」の判断が同時にありました。そこで求められるのがリニューアルの投資対効果なのですが、こちらについてはスケジュールと同様、事前に計算が出来なかった部分が多かったです。
- 最終的なインフラコストの算定
- 最終的なチーム構成と、開発生産性の向上率
- リニューアル開発に投資しなければいけない人員
あたりが事前に計算できればもちろんリニューアルの可否判断はしやすいのですが、今改めて考えてみてもこれらの値を事前に計算して出していくのは困難だったと思います。
とはいえ、幅を持たせた計算を行い、それを定期的に修正して、完了に向けて精度を高めていくようなことをしていました。
例えばインフラコストであれば「爆発的に負荷が高くなってしまった場合のインフラコスト、逆に非常に軽かった場合のインフラコスト」で計算し、機能群が完成するたびにそのマイクロサービスに対する負荷試験を行い、最終的なインフラコストを徐々に幅を狭めていくようなイメージで実施していました。
全体のアーキテクチャをどのように構想したか
最終的に4つのサービスから構成されるマイクロサービス構成に落ち着きました。詳しいサービス構成については別途記事を書く予定ですが、概ね以下のような点に気を付けて全体設計を進めていきました。
1. コンピューティングリソースをうまく使い分けて、インフラコストを最適化すること
例えば、配信をする基盤と顧客データを分析するための基盤はユーザーによる使われ方も、コンピューティングリソースの使われ方も大きく異なります。前者はプロセス内部で多くのスレッドを並列に動かしCPUを大量に使うような処理な一方で、後者は大量にレコードが入ったDB側のリソースを多く消費します。
これらそれぞれに適材適所なインフラを用意し、コストやパフォーマンスを最適化していました。
具体的には、例えばDBであれば分析基盤にはSnowflake・配信基盤にはPostgreSQLを使用していますし、プロセスの構成であれば分析基盤は単純な1プロセスですが、配信基盤はProducer-Consumerのモデルを採用しています。
2. 開発チームをうまく分割して、全体の認知負荷を下げること
CDP+MAのような複数領域にまたがっている、かつエンタープライズ向けの幅広い機能を提供するSaaSなので、全体の認知負荷がかなり高いと考えていました。
リニューアル前の構成では多くの機能を知らないとなかなかいじりづらい箇所も多かったのですが、リニューアル後の構成では、例えば配信基盤からすると「顧客を抽出するための条件を投げると、どういうロジックかはよく知らないが最適な顧客が抽出される」ような分析基盤が実現できています。
このように、チームを分割してそのチームのドメイン知識をより深めていけるような体制を敷けるようなアーキテクチャ構成にしました。
3. 機能群の段階的なリリースを可能にすること
スケジュールの不確実性があったため、リニューアル後の機能を小出しにできるような安全策を敷きながらアーキテクチャを構成していました。
フロントエンド側からすると、新しいバックエンドを叩いているように見えるが、そのバックエンドは裏側でリニューアル前のバックエンドを叩くような構成を維持していました。
4. マイクロサービスが無駄に増えすぎないようにすること
「サービス間の通信が失敗しうること・複数DBにまたがるトランザクションを気にする必要が出てくること」が厄介だと思っていたため、マイクロサービス分割に対しては原則保守的なスタンスで臨んでいました。そのため、まずは同一マイクロサービス内にモジュラーモノリスのように実装していって、開発を進めていく過程で「開発チームが分割できそうなこと」「複数DB内のテーブルを跨ぐ必要がなさそうなこと」が実際に確認出来てきたタイミングでサービスを分割していました。
リリースの方法について
当初はストラングラーパターンに従うことを想定していました。まずはFE/BE間にAPI Gatewayを挟み込むようにして、特定のエンドポイントを少しずつリプレイス後のBEにリクエスト先を移行していくような形です。
ストラングラー フィグ パターン - Azure Architecture Center
しかし、
- AWSのAPI Gateway上で同一エンドポイントのリクエスト先サーバーを複数設定していくのが簡単そうではない点
- UIUXを見直すことで、同一エンドポイントのレスポンスが全く異なるものになってしまう点
という理由から、API Gatewayでリニューアル前後の差異を吸収するのではなく、「フロントエンド側でページごと分けてしまい、表示ページを制御するAPIによって差異を吸収する」方策を最終的に採用しました。
こちらの図のような接続構造になっており、どのメニューを出すかをユーザーIDによってスイッチングできるような仕組みを用意してあります。
結果的には、この方策を採用したことでスピード感のある開発を維持出来ていた考えています。もし、裏側の言語やロジックだけを変えたいリニューアルであればストラングラーパターンのようなやり方の方が安全性を保てるのではないかと思います。
リニューアルと並行する既存顧客向けの開発はどのようにしていたか
基本的にはリニューアルにリソースを割くようにはしていましたが、既存のお客様からの要望もあるのでそちらの対応も並行して進めていました。こちらは、別チームを切り出すのではなくリニューアルチーム全体工数の3割程度と決めて全員で対応にあたるような形で進めました。(といいつつ、時には5割以上割いていたりもしたので内情はてんやわんやでした)
一般的には、恐らく別チームを完全に切り出して「既存顧客対応」と「リニューアル対応」を別で進めるのが効率が良かったのではないかと思っています。
しかし弊社内にはもともとプロダクトの創成期からコードを書いていたエンジニアが在籍しており、彼らが全機能に対するドメイン知識を持っていました。このリニューアルにおいて適切にサービスをドメイン分割していくにあたって彼らがリニューアルの実作業に深く関わることが必要不可欠だったためにこのようなチーム体制に落ち着きました。
既存環境の移行はどのように行ったか
オンプレやカスタマイズが入ったバージョンが多いプロダクトなので環境移行はかなりの困難を伴います。こちらについては別途記事を切り出して書こうと考えています。
おわりに
長年価値を提供しつづけてきたプロダクトをリニューアルするのは非常にタフである一方で、成功すれば大きな価値を生みます。
この記事ではリニューアルの全体像を紹介しましたが、ここから弊社のテックブログ内記事でリニューアル内部の詳細な話をしていけたらと考えています。
採用情報
弊社ではプロダクトのフルリニューアルを迎え、さらなるデータ活用・AIへの取り組みを強化していくべく仲間を募集しています!