メルカリCSツールにおけるDBの疎結合化への取り組み

この記事は「連載:技術基盤強化プロジェクト「RFS」の現在と未来」として書かれたものです。


メルカリCS Tool チームでTech Leadをしている @hukurou です。前回はトランザクションチームの取り組みを紹介しました。今回はCS Toolチームが取り組んでいる、メルカリのカスタマーサービスツール(以下、CSツール)のDBへの依存の削減や、その依存箇所を検出するための静的解析ツールの開発について紹介します。他の取り組みについても、この連載内で他のメンバーが紹介する予定です。

「RFS」におけるCSツールの目標

RFSとは「Robust Foundation for Speed」の略で、メルカリが将来に渡って力強く、素早く成長し続けるために、今あるビジネス共通基盤の複雑な技術的問題を解決していく取り組みです。以下の記事では、より詳細にプロジェクトの目的や取り組みについて説明しています。

関連記事:メルカリが今、ビジネス基盤強化に投資する理由とは?プロジェクト「Robust Foundation for Speed」の全貌

CS Tool チームではこのRFSというプロジェクトで、CSツールプラットフォーム化を目指しています。プラットフォーム化というのは、CSツールを開発するために共通で必要な機能やシステムを提供する共有基盤を構築し、その上に各ビジネスに対応したCSツールを作っていくというイメージです。

現在のメルカリには、コアとなる大きなCSツールの他に、各ビジネスやサービスのための複数のCSツールが存在します。これはメルカリのビジネスが拡張するにしたがって、それぞれに特化した独自のCSツールを作り、新しいビジネスに対応させるというケースが多かったためです。ですが、メルカリのサービスが大きくなってきたことでそういったCSツールの数も増え、共有できる機能が再利用できない、それぞれのツールを一定のセキュリティ水準に向上させるまでコストがかかるといった問題が見えてきました。

そこで、コアとなるCSツールを管理するCS Toolチームで、各CSツールが共通で利用できる基盤を提供しようと考えています。

しかし、そもそものコアとなるCSツール自体が様々なサービス、ドメインと密結合になっており再利用性が高くないという課題がありました。そこで、現在はプラットフォーム化の前段階として、コアとなるCSツールの他のサービスへの依存の疎結合化、特にメルカリ本体のサービスが持つDBへの依存の削減(以下、DB decoupling)に取り組んでいます。この部分については次の章でもう少し詳しく説明していきます。

「RFS」におけるCSツールへの取り組み

CS Tool チームの管理するCSツールはメルカリの創業当初から開発・運用されてきたモノリシックなアプリケーションで、BackendはPHP、Frontendは主にJavaScriptで構築されています。メルカリのカスタマーサービスを支える中心的なサービスで、他の様々なサービスと連携してCS業務に必要な機能を提供しています。これまでにCSツールのいくつかの機能のマイクロサービス化し、CSツールから切り離してきましたが、まだまだ多くの機能がCSツールに残されています。

このCSツールは、ここ数年でできたドメインや機能は密結合を可能な限り避けるようにデザインされていますが、それ以前に実装された商品や取引などのドメインでは、前述の通り他チームの管理するDBに直接依存するケースが多く存在します。この状態では、例えば先の記事で取り組みを紹介したトランザクションチームがDBに手を入れる際に、トランザクションチームは他チームのサービスであるCSツールのユースケースも常に考慮する必要があり、コストが高くなってしまいます。また、CSツールのプラットフォーム化を進めていくためにも他サービスとの結合を疎にし、さまざまなデータをCSツールの複数のドメインで再利用できる状態を目指していく必要があります。

関連記事:Understanding and Modernizing a Legacy Codebase
関連記事:メルカリの取引ドメインにおけるモジュラーモノリス化の取り組み

そのため、以下の図のようにCSツールがサービス側のDBを直接参照している部分をAPI経由に変更し、依存を各チームのAPI側に委譲していくという取り組みを進めています。


図. CS ToolのDB依存のAPIへの委譲

GraphQLサービスを利用したdecoupling

CSツールのDBへの依存をAPIに移行していく一番シンプルな方法は、CSツールのBackendから直接APIにリクエストする方法です。しかし、それでは現行のCSツールの依存が解決されるだけで、CSツールをプラットフォーム化する、新しいCSツールを作るといった場合に既存の資産を再利用しづらいと考えました。

そこで、今回のdecouplingの作業では、CS Toolチームで開発してきたGraphQLサービスを利用することにしました。GraphQLサービスについては、CSツールの商品通報対応をマイクロサービス化した際のこちらの記事でも紹介しています。このGraphQLサービスは、主にマイクロサービスから取得したデータを結合してFrontendに提供するBFF(Backends For Frontends)としての役割を持っています。現在は、商品通報対応以外にも、CSツールからマイクロサービス化された複数のツールがこのGraphQLサービスを利用しています。実際のdecouplingは以下の図のようなイメージです。


図. GraphQLサービスを利用したdecoupling

decouplingのためのデータ取得をGraphQLサービスに集約するメリットは大きく分けて2つあります。1つ目は先程述べたように、GraphQLサービスに集約することで再利用性を高められる点です。decouplingするテーブルのデータ取得をGraphQLサービスに集め、GraphQLのスキーマを充実させることで、他のCSツールのマイクロサービスでも利用できるようになります。2つ目は、これまでのマイクロサービス化で実装してきた既存のGraphQLスキーマを利用できる点です。既存のスキーマを再利用できれば実装を減らせる可能性があります。

また、現在のCSツールは、社内のほとんどのマイクロサービスで利用されているgRPCを用いた通信ができないため、もしAPIがマイクロサービス化されると追加の修正が必要になるというのも理由の1つにあります。

一般的にGraphQLはFrontendからリクエストされることが多いと思いますが、現在はCSツールのBackendから、このGraphQLサービスにリクエストしています。FrontendではなくBackendからリクエストしている理由は、テーブル単位でdecouplingを進める際にBackendが複数のテーブルに依存していると、過渡期において、GraphQLから取れるデータとBackendから取れるデータが分かれてしまい、Frontendに追加の実装が必要になってしまうためです。また、既存のBackendが複雑なロジックを持つ場合、それらを全てFrontendに実装し直す必要があり時間がかかってしまうということもあげられます。

最終的にはFrontendから直接リクエストが送られるべきですので、CSツールのBackendで依存を徐々にGraphQLに移し、各エンドポイントで依存が全て解消されたところについては、そのGraphQLのクエリをFrontendから送るように移していく予定です。

依存箇所の特定

これまで、どうdecouplingを進めているかについて紹介してきましたが、プロジェクトの開始したときには、具体的にどのくらい解決すべき依存箇所があるのかを把握できていませんでした。かなりの量になることは何となく想像できていましたが、decouplingを進めるためにはCSツールのどこでどのDBにアクセスしているのかを知る必要があります。これは、マイルストーンの設定や進捗管理のためにも必要になってきます。そこで、まずはCSツールでのDBへのアクセスを検出、集計する静的解析ツールを作成しました。

まずはCSツールでDBを利用する際に使われるいくつかの典型的なコードを検出できるようにしました。簡略化していますが、以下のようなコードを検知し、その引数などから接続先のDBやクエリ先のテーブルを検出し依存箇所を洗い出します。

$sql = “select * from users;”
$db_service->get_connection()->query($sql)

また、自動検出が難しい部分にはPHPDocのタグのようなコメントを1つ1つ付与し、そのコメントもツールで検出するようにしました。

/**
 * @db-hint db_name table_name
 */

これにより、DBへの依存箇所の特定が容易になり、decouplingの計画やAPI設計をスムーズに進めることができるようになりました。外部チームがCSツールのdecouplingをする場合にすぐに情報を提供できたり、古いDBをクローズすることになった時も簡単に調査ができたりといった副次的な効果もありました。

また、進捗状況を追うためにツールの解析結果をスプレッドシートでグラフ化しています。実は最初のマイルストーンとして進めているのは緑色のdomain Dですが、グラフを見ると他のドメインについてもdecouplingが進んでいることがわかります。これは、対象のテーブルをdecouplingする際に、別のテーブルがjoinされており、かつそのテーブルの必要な情報が既存のGraphQLスキーマを利用して取得可能な場合、一緒にdecouplingするようにしているためです。つまり他のドメインの依存が減少しているということは、それだけ既存のスキーマを再利用できていると言えます。

こうして全体の進捗で見ると、最初のマイルストーンに対してはまだ半分ほど、全体で見るとまだまだたくさんの依存が存在していますが、既存のGraphQLスキーマも利用しながら進められていることがわかります。

まとめ

この記事では、CS Toolチームが取り組んでいるCSツールのDB decouplingや、依存箇所を検出するための静的解析ツールの開発について紹介しました。

現在は、ドメイン単位でマイルストーンをおいてdecouplingを進めています。しかしDB decouplingはCSツールのDBへの依存を減らしながら再利用しやすい形でデータを集約していくだけで、それ自体がCSツールのゴールではありません。CS Tool チームはより良いカスタマーサービスを提供するためにCSツールの改善に取り組んでいきます。

この記事で紹介した取り組みは、「RFS」というメルカリのビジネス共通基盤の技術的な課題を解決していく全社横断的なプロジェクトにおける、CS Tool チームの取り組みです。そしてメルカリではこのRFSという大きなプロジェクトに一緒に立ち向かっていく仲間を募集しています!ご興味が湧いた方は、以下のリンクをご覧ください。
Software Engineer, Backend Foundation (PHP/MySQL) – Mercari

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加