はじめに
技術評論社様より発刊されているSoftware Designの2024年5月号より「レガシーシステム攻略のプロセス」と題した全8回の連載が始まりました。
本連載では、ZOZOTOWNリプレイスプロジェクトについて紹介します。2017年に始まったリプレイスプロジェクトにおいて、ZOZO がどのような意図で、どのように取り組んできたのか、読者のみなさんに有益な情報をお伝えしていければと思いますので、ご期待ください。第1回目のテーマは、「ZOZOTOWNリプレイスプロジェクトの全体アーキテクチャと組織設計」です。
目次
ZOZOTOWNリプレイスの背景、目的
背景
ZOZOTOWNは、2004年12月にサービスを開始して以降、基本的なアーキテクチャは変えずに成長してきました。数年に一度のペースでサイトリニューアルも行ってきましたが、UI/UXを中心としたリニューアルでした。
右肩上がりの成長を続けていたものの、2017年当時、中長期目標として設定していた商品取扱高5,000億円にシステム全体が耐えられないことが予見され、リプレイスプロジェクトの検討が始まりました。
目的
リプレイスプロジェクトは、「ZOZOTOWNを使っていただいているお客様にいつでも快適に買い物をしていただけるサービスを提供するため」、そして、「ZOZOTOWNの成長のため」に行います。この目的を達成するために、リプレイスを通して、改善していきたいことを整理していき、目的を達成するためのポイントを大きく4つ定義しました。
柔軟なシステム
リプレイス以前、オンプレミスのみで稼働していたZOZOTOWNは、新春セールなどの高負荷イベント時におけるサーバ増強には苦労してきました。イベントに合わせて事前にサーバの必要台数を見積もり、購入し、セットアップする必要がありました。また、処理コストが重いコンテンツをカットするなど、インフラだけではなくアプリケーションとしても作業が発生していました。
そこで、インフラ基盤をオンプレミスからクラウドへ移行することで、必要なときに柔軟に増強できるシステムにしたいと考えました。
開発生産性
事業展開における機能開発に加え、開発者視点でのUI/UX改善や、ソースコードのリファクタリングなどやりたいことがたくさんあります。しかし、モノリスアーキテクチャで開発されてきたZOZOTOWNでは、開発者数が増加するにつれてデプロイ作業が衝突して順番待ちが発生するなど、開発生産性に悪影響が発生し始めていました。
そこで、マイクロサービス化することで開発に関わるチームが並行で開発できるようにし、開発生産性を高めたいと考えました。併せて、IaC(Infrastructure as Code)や CI/CD(Continuous Integration / Continuous Delivery)を導入することで、デプロイ自動化による開発生産性の向上もねらいました。
技術のモダン化
ZOZOTOWNはVBScriptで動いています。開発元であるMicrosoft社もVBScriptの積極的な機能開発は現在行っておらず、このままでは稼働させる環境もなくなり、事業が停止するリスクがあります。経営リスクを回避するためにも、技術のモダン化は必須で、リプレイスプロジェクトは避けられないと考えました。
また、レガシー言語であるがゆえに、AWS、Google Cloud、DatadogといったクラウドベンダーがSDKを提供しておらず、利用を諦めるか、ライブラリを独自実装しなければならない状況でした。さらに、VBScript向けに協力会社内製のWebフレームワークを使用していて、そのフレームワークの動きを新メンバーは理解しなければならない状況でした。JavaやGo言語のようなクラウドベンダーが標準的にサポートしているプログラミング言語や、現代的なフレームワークに置き換えていくことで、そのような部分の実装コスト、学習コストを減らしたいと考えました。
採用強化
リプレイスプロジェクト、ひいては事業開発を加速するために採用強化が必要でした。リプレイスプロジェクトは、エンジニアとしての成長につながる経験ができるものだと思っています。知見をテックブログやイベント登壇で社外に向けて発信することにより、ZOZOに興味を持っていただき、採用を強化したいと考えました。
ZOZOTOWNリプレイスの歴史とアーキテクチャの変遷
アーキテクチャの変遷
2004年〜2017年:オンプレミス(リプレイス前)
Webサーバ、DBサーバなどはすべてオンプレミスで運用していました。基本的な技術スタックはWindowsのIIS(Internet InformationServices)で、Classic ASP(VBScript)を動かしていました。データベースにはSQL Serverを利用していました。主なビジネスロジックはSQL Serverのストアドプロシージャで記述しており、WebサーバはHTML/JSONを生成するビューレイヤーとして利用していました。
このアーキテクチャは2004年当時、Microsoft製品でシステムを構築する際のベストプラクティスとされていたものでした。ネットワークの細い当時はデータの近くで処理するストアドプロシージャのほうが高速で、ロジックを DB サーバに寄せることで DRY(Don't Repeat Yourself)に書ける利点がありました。このアーキテクチャでZOZOTOWNは売り上げを伸ばしてきたことからも、当時の技術選定として成功したと言えるでしょう。
一方で、さまざまな困りごとも出てきていました。主なビジネスロジックはストアドプロシージャとしてDBサーバで実行されるため、DBのCPUを消費してしまいます。CPUを増やすにはDBを増やす必要があり、負荷分散させづらい状況にありました。DBサーバのスケールアップでは限界が見え、DBを垂直分割し対処してきましたが、それでも限界が見えてきました。また、ストアドプロシージャのユニットテストフレームワークが なく、TDD(Test Driven Development)など昨今では当たり前とされている開発プラクティスを導入できないことも困りごとでした。
2017年〜2020年:モノリスリプレイス
そこでストアドプロシージャからの脱却を目標の中心に据えて、モノリスtoモノリスアーキテクチャでのリプレイスプロジェクトが始動しました。フェーズを「参照系(商品、検索)」「準更新系(お気に入りログなど)」「更新系(カート、注文、会員)」の3つに分解し、フェーズ1として参照系機能のリプレイスプロジェクトが進行しました。1
ビジネスロジックを処理するのに、DBサーバのCPUではなくWebサーバのCPUを使うアーキテクチャに変更できれば、Webサーバの台数を増やすことで負荷に対処できます。そこでSQL Serverの参照系ストアドを Java API化することにとにかく注力し、DBサーバの負荷を下げることが目標とされました。商品データは、オンプレSQL Serverからレプリケーションを貼って、クラウドSQL Serverに持ってきました。
この参照系リプレイスプロジェクトによって、ECサイトでトラフィックの大多数を占める参照系ワークロードのスケーラビリティを手に入れることができました。一方で、次のような課題も見えてきました。
- モノリスアーキテクチャであることで生まれるデプロイの順番待ちが開発生産性に支障を与えていること
- クラウドSQL Serverのコスト(とくにライセンス費用)が高いこと
- 更新系ワークロードリプレイスの目処が立っていないこと
- ユーザートラフィックの入り口がオンプレIISのままであり、VBScript脱却の目処が立っていないこと
2020年〜:マイクロサービス化
これを受けて新たなリーダーのもと、ZOZOTOWNリプレイスプロジェクトは再始動しました。マイクロサービス化しながらリプレイスプロジェクトを行う方針に大きく変更となり、メインで利用するDBもMySQLとするなど、技術スタックに関する変更も行われました。リプレイス後のアーキテクチャイメージと切り替え方法も示され、VBScriptからの脱却と、更新系ワークロードのリプレイス計画も立てられました。
技術スタックの選定
リプレイスプロジェクト再始動のタイミングで、技術スタックについてもあらためて選定し直しました。選定のポイントとしては「大規模開発に向いている」「人材を採用しやすい」「社内ノウハウがある」「廃れるリスクが少ない」技術を選定しました。とくに、最後の点については、リプレイスプロジェクトが長く続く可能性を考慮し、リプレイスのリプレイスが走ることを避けるために最重視したポイントでした。技術者個人としては新しいものを使いたくなりますが、邪念を排除し、組織にとって最も良い選択を行うことが肝要だと考えています。結果として、次のような技術選定になりました。
- フロントエンド:JavaScript / TypeScript
- バックエンド:Java、Go、Python(ML向け)
- インフラ基盤:AWS、Google Cloud(ML向け)、Kubernetes
- RDBMS:MySQL(RDBMSが不得意な分野は別途検討、DynamoDB、Elasticsearchなど)
バックエンドのプログラミング言語は、Javaをメインで利用しています。すでにJavaでリプレイスプロジェクトが始まっていたというのもありますが、大規模開発に向いていること、業務委託も含め人材を採用しやすいことを評価しました。Javaは一時期、機能開発が停滞していた印象を持っている方もいると思いますが、当時すでに機能開発も活発化しており、モダンな機能も取り込まれていることから、廃れるリスクも少ないと評価できたのが幸いでした。Go言語も使って良いと定めており、高速に動作し、アプリケーションの立ち上がりが早いことから、とくにトラフィック量の多いアプリケーションや、AWS Lambdaのようなサーバーレス環境で利用すると恩恵があります。機械学習の文脈では、ディープラーニングフレームワークなどライブラリの都合でPythonでAPIサーバを構築することもあります。
クラウドサービスは、AWSをメインで利用しています。人材採用しやすく、廃れるリスクが小さいのもそうですが、高いサービス品質を持ち、主要クラウドサービスの中で「最も痒かゆいところに手が届く」クラウドサービスであると評価しています。機械学習の文脈では、Google Cloudを使っても良いと定めています。データウェアハウス製品であるBigQueryや、Google独自の機械学習ワークロード向け集積回路TPU(Tensor Processing Unit)の提供を始めとして、データおよび機械学習の文脈で独自の強みを持つクラウドサービスであると評価しています。
コンテナ基盤は、Kubernetesを利用しています。2020年当時、Kubernetes以外にも活躍しているコンテナ基盤はありました。しかし、Google CloudやAzure、AWSがKubernetesのマネージドサービスを提供するようになり、Kubernetesが廃れるリスクはかなり小さいと判断できた時期でした。AWS EKS(Elastic Kubernetes Service)の提供は2018年であるため、2017年に技術選定をしていたら、違った判断になったかもしれません。
組織設計
プロジェクトチームの構成と変遷
2017年開始当初のリプレイスプロジェクトでは、フロントエンド/バックエンドはそれぞれでカートや商品詳細、検索などといった各機能を担当しやすいような複数チームで構成され、SREはすべてのインフラを管理する1つのチームで構成されていました。そして、各チームが事業案件(ZOZOTOWNの新機能追加や機能改修など)を担当しながら、リプレイスも進めるという二足のわらじ体制をとっていました。
ZOZOにはファッションやZOZOTOWNが好きなスタッフが多く、さまざまな部署からZOZOTOWNをさらに良くするためのアイデアが次々と寄せられます。それらに応えるため、どうしてもリプレイスの優先度を落とさざるを得ず、開発リソースの確保といった部分で、うまくリプレイスプロジェクトが進行していきませんでした。そこでバックエンドエンジニアの数名でリプレイス専属のチームを作り、リプレイスを進めていきました。
まずは、その専属チームが1つのリプレイス事例を作りました。その後、マイクロサービス化を拡大していく過程で、ID基盤や会員基盤・検索基盤・カート決済基盤など各マイクロサービスのチームを、構築するタイミングで作っていきました。そして、各マイクロサービスを担当するチームと、SREチームから構成される技術開発本部(現:技術本部)が設立されました。
リプレイスを行う初期段階では、事業開発を行ってきたチームが自分たちでリプレイスをやりたい、と思うのは当然だと思います。筆者たちも何度かトライしましたが、そのやり方でうまくいったことはありませんでした。リプレイス専属チームを作り、事例を作り、徐々に既存チームも巻き込み、最終的に融合するか、既存チームにシステムを移管する、という流れを取るのが有効です。
マイクロサービス分割と組織
マイクロサービスは組織論でもあります。マイクロサービス分割に関しては、ZOZOTOWNが持つ機能を大別し、それぞれの機能(マイクロサービス)を担当する専属のチームを作る想定で次のように分割設計を行いました。
- 認証・会員
- 商品(ブランド、ショップ)・お気に入り
- 検索
- 推薦
- カート・決済
むやみやたらにマイクロサービスの数は増やさず、基本的には1チーム1マイクロサービスを担当するくらいが大まかな方針です。逆に言うと、マイクロサービスの規模感は1チームが専属で必要な作業量を見込めるくらいとなるように分割設計しました。将来的に1チームの担当サービスが増えて2、3個になってしまうことは想定していますが、1チームが数十個マイクロサービスを担当するような設計は避けています。
このようなマイクロサービスの分割設計は、「開発」「運用」「組織」の側面から検討を進めました。
「開発」の側面
開発の側面からは、各サービスに自律性を持たせ、開発生産性を高められる設計を意識しました。
まずは、ZOZOTOWNにおける機能とデータ、データとデータの関連性を把握することから始めました。これらの関連性を把握することで、たとえば、AとBの似たような機能をサービス分割するか一緒にするか、の意思決定がしやすくなります。ポイントとして、データの更新時に、複数のマイクロサービス間で分散トランザクションが必要にならないような境界線を見つけ、サービス分割を行うことを意識しました。うまくサービス分割できると、データに何かしらの仕様変更が入った場合でもサービス間の調整が不要になり、効率的な開発フローを回すことにつながります。マイクロサービスのメリットの1つである自律性を高めることにつながります。
「運用」の側面
システム運用の側面からは、リソース増強が必要な機能をきちんと把握し、効果的に実施できるようにする設計を意識しました。
モノリスの場合、特定のサブ機能のみをスケールさせたくても、モノリスサーバ全体をスケールさせなければなりません。マイクロサービスの場合、特定のサブ機能(≒マイクロサービス)のみをスケールさせることが可能なので、費用対効果を高めることができます。そのために、事業特性や過去実施イベント、障害記録を分析し、高負荷になる機能を整理しました。
ZOZOTOWNの場合、セールやZOZOWEEK、福袋といったイベント実施のタイミングで、とくにカート投入、購入、認証、商品検索などの機能が高負荷になる傾向があります。しかし、そういったイベント時でもそれほど負荷がかからないような機能もあります。そのような傾向を整理し、どういったマイクロサービス分割が、リソース増強などの運用全般で効率が良いかを考慮しました。
「組織」の側面
組織の側面からは、業務の専門性と、現在の開発体制からマイクロサービス化後の開発体制とのギャップを意識しました。
ZOZOTOWN の場合、カート投入・購入、商品検索、推薦といった機能が業務の専門性が高い機能に該当しますが、それらのチームで利用する技術スタック・業務知識は、ほかのチームに比べて特殊です。そのようなことを考慮し、組織分割の検討材料として取り入れました。
また、事業展開における業務量の把握も行いました。JIRAやGitHub、今後どんな開発案件があるかを示した開発ロードマップなどから、過去、現在、未来の開発案件がどのような機能の改修を必要とするものなのか、その傾向を分析しました。リプレイスが終わった後は事業開発をしていくことになります。各チームの業務量のバランスが良くなるように、ドメイン知識の関連性も意識したうえで担当マイクロサービスをアサインし、人員計画を考えました。
急にマイクロサービスと同数のチームを作るような大幅な組織変更をしてしまうと、新任リーダーの教育やチームビルディング、チーム間の連携に齟齬が生まれるなど、多くの懸念がありました。技術スタック・業務知識のキャッチアップにも時間がかかります。理想的なマイクロサービスの形、それに合わせた開発体制を目指して、技術的な練度を高めながら、現実的な組織変更を少しずつ重ねることで、組織づくりをしていきました。
コミュニケーションと意思決定
理解を得る
リプレイスプロジェクトを進めるうえで、ビジネス部門、エンジニア部門(対社内/対社外)、経営層に対して、リプレイスの重要性を理解してもらうことは重要だと考えています。
ビジネス部門に対しては、社内向けの成果発表会などで、リプレイスによる事業効果(システム障害の減少、高速化、コスト削減など)を伝えることで、協力を得られやすい関係性を構築することを意識しました。
エンジニア部門に対しては、同じく社内向けの成果発表会・テックブログ・登壇での発信や、開発体験の向上、アラート件数の減少、などの成功体験を実際に感じてもらうことによって、リプレイスプロジェクトへの協力を得られやすくなりました。社外に対しては、テックブログや登壇を通じてZOZOの抱える課題や技術力を発信することで、採用強化につなげていきました。
そして経営層に対しては、リプレイスの目的、かかる費用、計画、考えられるリスクを整理して説明し、プロジェクトの承認を得ました。定期的なプロジェクト進捗報告を実施し、計画に変更があれば再度承認を得ながら進めています。進捗報告では、得られた事業効果も伝えることで、プロジェクトの優先度低下や廃止といった事態を避けることを意識していました。
リプレイスプロジェクトを計画どおり進めることは大事ですが、あくまでも事業が成功しているうえで成り立っているプロジェクトだと考えています。開発者としては、機能開発をフリーズして、リプレイスに専念するのが最もやりやすいでしょう。しかし、その間に競合他社に置いていかれ、リプレイスを実施するプロダクトとしての価値そのものを失ってしまっては元も子もありません。そのリスクを避けるために「事業を止めない」をリプレイスプロジェクトのポリシーとしました。サイト無停止でユーザーに気づかれないようにリプレイスしたり、リリース前に負荷試験を実施しボトルネックを事前に潰しておいたりと、事業に悪影響を出さないことを大前提として、技術的難易度が高くても工夫して成し遂げるように進めています。
リリースフロー
ZOZOでは社内標準のリリースフローを定義しています。ZOZOにおけるリリースフローとは、案件の進捗工程(企画・設計・開発・テスト・リリース)ごとに必要な確認事項を定めたものです。リリースフローに従う必要があるかどうかはアーキテクチャの重要な変更、重要な情報の取り扱いなどの一定の条件が存在しますが、ZOZOTOWNリプレイスプロジェクトの各プロジェクトは必ずリリースフローに従うルールとしています。
リリースフローは、CTO、CISO部やテックリードを含めて企画、設計、テストの3段階でレビューMTGを行い、技術的、セキュリティ的に問題がないかを確認します。レビューMTG以外にも、全社で定められている開発ガイドラインに準拠しているかのチェックリスト確認もリリースフローには含まれています。
ADR(Architecture Decision Record)
リプレイスプロジェクトでは、アーキテクチャや設計において、さまざまな意思決定が生まれます。それぞれがどのような検証、理由により方針を決定したのかADRとしてまとめています。ADRは、次の内容で記述しています。
- タイトル(Title)
- コンテキスト(Context)
- 決定(Decision)
- ステータス(Status)
- 結果(Consequences)
最終的なアーキテクチャがまとめられているドキュメントはあるものの、その技術選定の理由や設計意図については残されていない、または議事録やコメントの一部として埋もれてしまっていることがよくあると思います。プロジェクトの初期から参画しているメンバーのみが理解している状態では、途中から参画するメンバーは新たな変更などの意思決定において、判断が難しくなってしまいます。また、時間経過とともに記憶もあいまいになり、初期から参画しているメンバーですらその意図を忘れてしまうこともあるでしょう。このようなことが積み重なってくると、変更に対して多くの時間がかかり、開発生産性の低下を招く可能性もあります。そのような状態を避けるためにADRを残すようにしています。
ロードマップ
リプレイスプロジェクトにはいくつものサブプロジェクトがあり、各サブプロジェクトをまとめたロードマップを定義しています。しかし、当初からロードマップを定義できていたわけではありません。クラウドやマイクロサービスに対してノウハウや経験がない状態からの挑戦でしたので、まずは取りかかりやすい部分を対象にリプレイスしてみることにしました。しかし、障害を発生させてしまうなど、うまくいかないことも数多くありました。ですがそこで多くのことを学び、それらの経験をもとに次のように年度ごとにテーマを設け、少しずつ範囲を広げるようにロードマップを作成していきました。
- 2020年度:マイクロサービスプラットフォームの土台を作り、マイクロサービス化の事例を1、2個出していく(達成)
- 2021年度:さらにマイクロサービス化し、体制も強化し並列度を上げていく。うまくいくことを実証する(達成)
- 2022年度:終わりまでの全体設計・ロードマップをあらためて引き、さらに並列度を上げていく
ロードマップを作成する際には、技術的な基盤を先に作りつつ、リプレイスの効果が大きいものを優先的に着手することを意識しました。また、事業効果(システム障害の減少、高速化、コスト削減など)も得られるように、サブプロジェクトのスコープを調整し、着実に事業成果を報告できる計画にしました。リプレイスプロジェクトは、過去に一度会社としての優先順位が下がったことがあります。それを避けるために、経営層にリプレイスプロジェクトの価値を定期的に理解してもらえるような計画を意識しました。
リプレイスロードマップは、進捗や状況次第で、四半期に一度のペースで適宜見直し、取り組んでいます。
おわりに
今回は、ZOZOTOWNリプレイスの全体感について、プロジェクト推進において意識していることやうまくいったこと、うまくいかずに軌道修正したことを盛り込んで紹介しました。今後、大規模システムのリプレイスプロジェクトに関わる方々の参考になれば幸いです。
第2回以降は、ZOZOTOWNリプレイスプロジェクトがこれまで取り組んできたサブプロジェクトを具体的にいくつかピックアップして、より詳細に紹介していく予定になっていますので、ご期待いただければと思います。
本記事は、技術本部 ECプラットフォーム部 ディレクターの高橋 智也と執行役員 兼 CTOの瀬尾 直利によって執筆されました。
本記事の初出は、Software Design 2024年5月号 連載「レガシーシステム攻略のプロセス」の第1回「ZOZOTOWNリプレイスプロジェクトの全体アーキテクチャと組織設計」です。
ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。
- フェーズ1は2017年度中に終わらせるのが当初の目標でしたが、会社としての優先順位が下がるなどもあり、結果として3年ほど続くこととなってしまいました。↩