モノリシックな大規模アプリを運用する技術-サービスを“分割しない”メリットをSansanの実例に学ぶ
モノリシックにアーキテクチャを構築するメリットとは?近年、マイクロサービスアーキテクチャが注目を集めていますが、Sansanは大規模なアプリケーションに成長したいまも、モノリシックな構造を維持しています。ドメインコンテキストの共有のしやすさ、チームビルドのしやすさなど、モノリシックな構造だからこそ得られるメリットを聞きました。
- モノリシックである利点 - ドメインコンテキストが共有しやすい
- Backlogを一本化し、モノリシックなシステムを運用しやすく
- 技術的負債の解消 ~事業フェーズに適した技術を選定する~
- 技術的負債の解消 ~リプレース可能な部分は積極的にエコシステムを活用~
- 技術的な改善をビジネスの改善に結びつける
近年、複数の小さなサービスをAPIによって連携させるマイクロサービスアーキテクチャが注目を集めています。分割されたシステムを各サービスチームが独立的に開発・デプロイできるこの手法は、組織のスケーラビリティーを高めてくれることに大きな特徴があります。
ですが、あらゆる課題を解決する銀の弾丸のようなアーキテクチャは存在しません。当然ながらマイクロサービスアーキテクチャにも向き・不向きはあり、対比的に語られることの多いモノリシックアーキテクチャは依然として有効な手法であり続けています。
モノリシックな体制の利点を生かして開発が続けられているのが、Sansan株式会社が提供する法人向けクラウド名刺管理サービス「Sansan」です。このアプリケーションはWebアプリケーションやバッチなどのプログラムが、ひとつのリポジトリで管理されています。また開発組織においても、各チーム同士が密に連携を取り合いながらプロジェクトを進行しているのです。
なぜ同社は、モノリシックな体制を貫き続けるのでしょうか。また、大規模な開発組織でプロジェクトを円滑に進めるための工夫とは。同社でアプリケーション基盤の改善に携わる加畑博也さんにお話を伺いました。
- 加畑博也さん(かばた・ひろや)
- Sansan株式会社 Sansan事業部 プロダクト開発部。大学院卒業後、大手電機メーカの研究所に新卒入社。電力の使用状況を用いたオフィスワーカの行動予測に関する研究開発に従事。2014年11月、Sansan株式会社に入社。以来、法人向けサービスSansanの開発を担当し、主にアプリケーション基盤の改善に携わる。
モノリシックである利点 - ドメインコンテキストが共有しやすい
──法人向けクラウド名刺管理サービス「Sansan」の開発組織についてご説明ください。
加畑 現在、「Sansan」は社員や業務委託の方々などを含めて130名ほどの組織で開発を進めています(取材を行った2020年6月時点)。開発組織は「Webアプリ」「スマホアプリ」「QA」といった役割ごとにグループが分かれており、各グループはさらに3~6名程度のチームに分割されています。
チームごとに得意とする領域や機能が異なるため、強みを考慮した形でプロジェクトの割り振りがされるケースが多いです。しかし、各チームの役割はガチガチに固定されているわけではなく、比較的フレキシブルな形でプロジェクトがアサインされています。また、後で詳しくお話しますが、各チームが担っている業務内容は開発組織のメンバー全員に共有されており、誰でも開発組織内で進行あるいは計画されているプロジェクトの状況を把握できる状態です。
──「Sansan」はバッチやWebアプリケーションが単一のリポジトリで管理されていると伺いました。組織が一定以上の規模になるとリポジトリ分割やそれに伴う組織体制の変更を行う企業も多いですが、現体制をとる利点とは何だと思われますか?
加畑 いくつかありますが、ひとつはドメインコンテキストに依存しないことです。例えば、マイクロサービスアーキテクチャのようにドメインや機能ごとにチーム・サービスが分割されている体制ですと、市場環境やビジネス要求の変化によって、タスクが特定のチームに集中する、特定のシステムの改修ばかりが多くなるといった事態が発生しえます。または、分割の仕方そのものを後で変えたくなるケースもあるかもしれません。
その場合、チームやシステムの体制変更にかかるコストが非常に大きくなるという欠点があります。つまりマイクロサービス的な体制をとると、特定ドメインのなかではリソースが最適化されるものの、ドメインを跨いだり変更するコストが非常に増大するという側面があります。「Sansan」のようにひとつのコードベースで開発を進めていくことで、開発リソースを企業全体として最適化しやすいという利点があるわけです。
加えて、中長期的かつ組織的にサービスをメンテナンスしやすいという利点もあります。「Sansan」はtoBのサービスであるという性質上、特定の機能がユーザー企業のビジネスフローに深く入り込んでいることが多い。そのため、toCのサービスと比べると一度リリースした機能を廃止する判断がしづらく、メンテナンス性に対する要求が相対的に高いです。
もしもドメイン単位でサービスが分割されていれば、チームごとに採用技術が異なるといったケースが発生しうるため、あるチームのメンバーが別のチームの機能をメンテナンスしづらくなってしまうはずです。単一のリポジトリにしておくと採用技術も基本的には統一化されるため、すべての機能をどのチームのメンバーもメンテナンスしやすくなります。
また、マイクロサービス化を推進すると複数サービス間をAPIで連携する形になるため、ネットワーク障害やトランザクション境界に起因するトラブルをどう解決するかを考慮しなければなりません。モノリシックなつくりにしておくと、そうした課題を考慮する必要がほぼなくなります。
──開発・運用上の利点が大きいのですね。
加畑 かつ、当社が扱っている名刺管理という概念そのものが、事業ドメインとして比較的新しい概念だから、という理由もあります。この領域はまだ明確な答えといえるビジネスモデルが存在しておらず、今後も当社の事業内容は変化し続けていくと思います。にも関わらず、ある段階でビジネスコンテキストを切ってサービスを分割してしまうと、コンテキスト自体の変化が起きた場合に、対応コストが非常に大きくなってしまうはずです。
──なるほど。ドメイン分割やそれに伴うマイクロサービス体制は、むしろ「Sansan」というサービスの進展性を阻害してしまうわけですね。
加畑 とはいえ、私たちはけして「モノリスであること」を強く志向しているわけではありません。アプリケーションとしてのデータモデル設計などをふまえて、適切なアーキテクチャを検討した結果、いまの形に落ち着いているというのが正しいです。
例えば、名刺のデータ化や名寄せのロジックはSansanのデータ統括部門(DSOC:Data Strategy & Operation Center)が開発しているのですが、その部門と「Sansan」の開発組織とでは、開発体制もコードベースも完全に別のものになっています。「モノリスかマイクロサービスか」という二者択一ではなく、その組織やアプリケーションにとって最適な設計を常に考えておく姿勢が大切だと思いますね。
──現在の開発体制の利点が生きた事例はありますか?
加畑 私たちは「オンライン名刺交換」機能の提供を2020年6月16日より開始したのですが、この機能開発がスピーディーに行えたのも、現体制だからこそだと考えています。
「オンライン名刺交換」のプロジェクトは新型コロナウイルスに起因する自粛要請の影響を受けて立ち上がったのですが、もともとは他のプロジェクトと同じような開発フローで進めていく想定でした。ですが、オンライン上で商談や会議を行うニーズが急激に高まったため、機能の優先度が非常に高くなったのです。
そこで、特例的なプロジェクトとして複数のチームからメンバーを招集し、「オンライン名刺交換」専門チームを立ち上げてプロジェクトを推進しました。ドメインコンテキストを横断するコストがないからこそ、この体制を実現できたと考えています。
結果的に、当初の予定よりも1か月ほど前倒しで機能をリリースできました。もし、マイクロサービス的な体制をとっていれば、メンバーのオンボーディングやドキュメントの解読といった作業に大きな学習コストがかかっていたはずです。そのコストがほぼ生じなかったため、スムーズに開発が進行しました。
Backlogを一本化し、モノリシックなシステムを運用しやすく
──各メンバーは、他のチームの開発の動きをどのように把握しているのでしょうか?
加畑 私たちは「Sansan」の開発組織全体で、一本化したBacklogを用いてプロジェクトを管理しています。もともと「Sansan」の開発組織では、チームごとにプロジェクトの優先順位を判断・管理する体制をとっていました。今よりも人数が少なかった時代にはその体制で問題がなかったのですが、人数が増えてくると徐々に課題が見えてきました。
例えば、各チームが別々のBacklogでプロジェクトを管理しているため、あるチームは優先度の高い業務ばかりをやっているのに別のチームは優先度の低い業務ばかりをやっている。つまり開発リソースを最適化できていない状況が生まれていました。また、別のチームが取り組んでいる改修の内容がわからないため、ソースコード修正やプロジェクトのコンフリクトが頻発していましたね。
──その状況を改善するために、Backlogの一本化が行われたわけですね。
加畑 もちろんBacklog運用のスイッチングコストは大きかったですが、取り組むだけの価値があったと思います。一元管理されているBacklogをベースに仕事が割り振られるため、全チームが優先度の高いプロジェクトから順に取り組めるようになりました。また、各チームが担うプロジェクトが可視化されるため、作業のコンフリクトが起きにくくなっています。
──チケットの起票からプロジェクトのアサインまで、どのような流れで行われるのでしょうか?
加畑 まず、ビジネス的な要求やチームメンバーの意見などから、機能の新規追加や変更のアイデアが生まれます。その内容をベースに、プロダクトマネージャーがBacklogへのチケット起票を行った後、複数のプロダクトマネージャーやステークホルダーとの会議を設けて優先順位づけを行います。
議論の結果によってはチケットがボツになるケースもありますが、それは残念なことではなくむしろ良いことです。取り組むべきではないプロジェクトが、適切にふるい落とされたということですから。優先順位がつけられた後、各プロダクトマネージャーは該当する機能の開発が得意なチームと相談し合って、プロジェクトを進めていきます。
──開発体制という意味ではGitのブランチ戦略も重要ですが、どのような形式をとられていますか?
加畑 masterブランチをベースに、チーム単位のdevelopブランチを切る運用をしています。各チームは各々のdevelopブランチからfeatureブランチを作成し、機能を開発してPull Requestを発行し、承認されたらチームのdevelopブランチにマージします。
リリースする際には、masterブランチから切り出したreleaseブランチに、チームdevelopブランチの資材をマージします。リリースが正常に終了すれば、releaseブランチの資材をmasterにマージした後、各チームが変更を取り込む流れになっています。
──いわば、チーム単位で「git-flow」のワークフローをとっているわけですね。それ以外にも、採用技術などで大規模開発における品質向上やメンテナンス性の向上に寄与しているものはあるでしょうか?
加畑 当社では歴史的経緯から「Sansan」のサーバーサイドの言語としてC#を採用しているのですが、その特徴が品質向上に寄与していると思います。静的型付けの言語ですからコンパイルの段階で記述の誤りを検出できますし、(C#がマイクロソフト開発の言語であるため)マイクロソフト製のIDEであるVisual Studioの恩恵を受けやすい。大規模開発において適切にプログラミング言語を選択することは、開発効率や品質を向上させるうえで重要だと感じます。
また、システムの改修をなるべく容易にするため、.NETのNuGetというパッケージマネージャを用いて社内でサーバーを構築し、セキュリティやメッセージングの基盤といった一部のコア機能をパッケージとして提供・利用しています。リポジトリは同一であるものの、設計上の依存関係は比較的疎な状態を保っています。少しずつ機能を切り出しながら、パッケージ化を進めている段階です。
技術的負債の解消 ~事業フェーズに適した技術を選定する~
──大規模なアプリケーションの開発・運用を続けていくうえでは、技術的負債を積極的に解消していくことも重要に思います。これまで、どのような施策に取り組まれてきましたか?
加畑 一例を挙げると、O/Rマッパーの技術的負債解消ですね。SansanではO/Rマッパーとして、2016年からEntity FrameworkとDapperを導入していました。
──両者はどのようなライブラリなのでしょうか?
加畑 Entity Frameworkは.NET標準のO/Rマッパーで、データを.NETオブジェクトとして扱います。発行されているクエリは抽象化されているため、開発者はデータベース層を意識しなくてよくなります。一方、Dapperはより軽量なO/Rマッパーで、SQLのクエリを開発者自身が記述する必要があります。2つのフレームワークを併用していたのですが、Entity Frameworkに関しては使い続けるうちに課題が生じてきました。
当社ではRDBMSにPostgreSQLを使っており、データプロバイダとしてNpgsqlを用いています。NpgsqlはEntity Frameworkに対するサポートとしてEntityFramework6.Npgsqlというライブラリを公開しているのですが、このライブラリはPostgreSQLの特殊な型をサポートしていません。そのため、当社ではEntityFramework6.Npgsqlを独自に拡張していたのですが、メンテナンスが非常に大変になってきました。
また、Entity Frameworkはクエリ単位でのチューニングや複数テーブルをJOINする場合、パフォーマンス最適化がしづらいという欠点があります。そこで、SansanではEntity Frameworkをカスタマイズして、ヒント句(pg_hint_plan)を差し込み可能にすることでパフォーマンスを向上させるという施策を行っていました。
これは、以前に当社の千田が「実録パフォーマンス改善 - 高速化のためアーキテクチャやアルゴリズム選択から見直すSansanの事例」という記事で語っていた内容です。ですが、独自カスタマイズのため問題が発生しやすく、ライブラリのメンテナンスコストも大きいという課題がありました。
これを解決するべく、Entity Frameworkで実装していた箇所を、全面的にDapperへ移行したのです。DapperはEntity Frameworkと比べるとクエリチュー二ングしやすいため、仮に複雑なクエリを発行した場合でもパフォーマンスを最適化できます。Entity Frameworkはサービス全体で利用されていたため、長期的なプロジェクトとして開発部全体のリソースを活用しながら、徐々に移行を進めていきました。
──その事例から何を学ばれましたか?
加畑 事業のフェーズに応じて、最適な技術は変化し続けるということですね。初期のフェーズにおいては、開発生産性を高めることを重視して技術選定が行われるケースが多いです。Entity Frameworkはそうしたケースの典型ですね。一方、事業が成長してアプリケーションのデータ量が増えてくると、よりスケールしやすい技術が選択されるようになります。
どちらの選択が良い、悪いというわけではありません。現在では負債になっている技術でも、採用された当時は必ずなんらかの意図があったはずです。私たちエンジニアは、なぜ過去にはその技術が選択されたのか、そして現在の事業内容をふまえてどのようにアーキテクチャを変えていくべきなのかを、常に考え続けることが重要なのだと思います。
技術的負債の解消 ~リプレース可能な部分は積極的にエコシステムを活用~
──加畑さんが取り組まれた負債解消施策には、他にどのようなものがあるのでしょうか?
加畑 あるAPIサーバーをAmazon EC2とApplication Load Balancerで構築していたのですが、Amazon API GatewayとAWS Lambdaを用いた構成へと刷新しました。
──どのような役割を担うAPIなのでしょうか?
加畑 2種類あります。ひとつは、Sansanのデータ統括部門側のシステムから呼ばれるAPI。もうひとつは、SendGridによるメール送信の結果を受け取るためのAPIです。どちらもロジックは非常にシンプルで、処理の結果をデータベースにINSERTするだけ。依存ライブラリも非常に少ないです。ただし、時期や時間帯によってリクエスト数の増減が激しいことや、全体としてリクエスト数の増加が顕著になっていることから、高いスケーラビリティーを確保しておくことが求められました。
これらのAPIを提供するためには、Amazon EC2をメンテナンスし続ける人的コストが必要でした。ですが、求められる要件から考えるとAmazon API GatewayとAWS Lambdaによる構成に変えることは容易です。かつ、AWS Lambdaはサーバーレスであるためサーバーのメンテナンスが不要になりますし、自動的にスケールするためリクエスト数が大量になっても問題ありません。
──ユースケースに非常にマッチしたアーキテクチャになっていますね。
加畑 各種クラウドプラットフォームでは、AWS Lambdaのように開発者にとって運用の負担が少なく、かつスケーラビリティの高い技術が登場し続けています。自社のユースケースに合っているかを検討したうえで、開発や運用の課題を解決できそうであれば、そうしたエコシステムに乗ることは非常に有益だと感じますね。
技術的な改善をビジネスの改善に結びつける
──どのような判断軸に沿って、負債を解消する・しないを判断すべきだと加畑さんは思われますか?
加畑 技術的な改善がビジネスの改善に結びつくかどうか、だと思います。例えば、特定の機能に技術的負債が生じて生産性が落ちており、ビジネス要求にうまく応えられていないのならば改善する意味合いは大きいです。一方で、なんとなく気持ち悪いから、自分の好みではないからという判断で行う改善は、意味のないものになってしまうと思います。
ただし、技術的負債に起因した機能改善の停滞を、ビジネスサイドに理解してもらうのはとても難しいことです。だからこそエンジニアは「なぜ、技術的負債がビジネスの成長を阻害しているのか」を、きちんと論理立てて説明できなければならないとも感じます。事業を成長させるために、どのような仕事をすべきなのかを自分なりに考えて行動するスタンスが重要だと思います。
──最後に、「Sansan」のように大規模なアプリケーションの開発に携わる意義について、加畑さんの意見をお聞かせください。
加畑 自分たちの仕事で、世の中に大きなインパクトを与えられることですね。ありがたいことに「Sansan」は多くの方々に利用していただいており、「名刺管理といえば『Sansan』」と世の中から認知していただけるようになりました。一方で、もし私たちが品質の悪いサービスを提供すれば、名刺管理の市場そのものを壊してしまうかもしれない。エンジニアとして、サービスの価値を高め続けていかなければならないという責任を感じます。
また前半でもお話したとおり、名刺管理というビジネス領域は体系化されたプラクティスがありません。わかりやすい正解がないので、自分たちなりにベストと思えるアーキテクチャや開発組織を生み出していく必要があります。エンジニアとして困難に直面することも多いのですが、だからこそ挑みがいがあるのだと私は思っています。
取材・執筆:中薗昴/写真:漆原未代