バイセル Tech Blog

バイセル Tech Blogは株式会社BuySell Technologiesのエンジニア達が知見・発見を共有する技術ブログです。

バイセル Tech Blog

Cosmosプロジェクトを横断した技術設計やガイドラインの策定

はじめに

こんにちは。テクノロジー戦略本部 開発3部の今井です。

私は現在、顧客対応・SFA システム(以下、CRM)のバックエンド・インフラ領域の開発に携わりながら、Cosmos横断プロジェクトにも所属しています。
今回は、「バイセルリユースプラットフォーム Cosmos」(以下、Cosmos)の各プロジェクトを横断し、プラットフォーム全体の設計や方針の決定などを行う「Cosmos横断プロジェクト」の取り組みをご紹介します。

Cosmosの現状と課題

バイセルではDXの取り組みのひとつとして、さらに多様な買取・販売チャネルに対応し、買取から販売まで一気通貫してデータを管理・活用するCosmosの開発を進めています。

Cosmosは事業に必要な様々なアプリケーションを統合しており、顧客管理システム(CRM)、商品マスタ(Promas)、店舗買取システム(Store)など、約10種類のシステムで構成されています。
さらに、データ分析基盤である「Pocket」も内蔵し、各種データを有効に利活用できる環境を整備しています。

2024年12月期 決算説明資料

すでに買取申込や買取・査定などの領域にはCosmosを導入しており、我々CRMチームが相対するインサイドセールス部ではアポ獲得数の向上や教育コスト削減などといった、定性・定量の両面で成果が確認できています。

しかしながら、課題もあります。

Cosmosでは現在、顧客管理や訪問査定など異なるドメインを担当する複数のマイクロサービスが稼働しています。
それぞれ専任の開発チームが管理しているものの、マイクロサービスアーキテクチャに起因するいくつかの問題が見えてきました。

具体的には、チーム間のサイロ化と局所最適化による以下のような課題があります。

サービス間の通信方式について、REST/GraphQL/PubSubなどが混在しており標準化されていませんでした。
こうした状況が続くと、通信プロトコルやデータフォーマットがチームやサービスごとにバラバラになり、全体のアーキテクチャを俯瞰しにくくなるほか、チーム間の連携や運用が煩雑化するリスクがあります。
さらに、共通のガイドラインがないまま拡張や保守を続けると、システム全体の整合性を損ねる可能性もあります。

また、アーキテクチャや技術選定において、一貫性がないため車輪の再発明感がありました。

これらの根本にあるのは、「システム全体に影響を与える意思決定について、サービスを横断した視点で設計やレビューを行う場がほぼ存在しない」という点です。

そこで、横断的な視点で設計・レビューを行う仕組みを強化することで、こうした課題の多くは解決できるのではないか、という考えに至りました。
そのために立ち上がったのが、各チーム間の連携を深め、共通の方向性を見出すための「Cosmos横断プロジェクト」です。

Cosmos横断プロジェクトの開始

昨年10月に、Cosmosに関わるマネージャーやテックリードが集まり、Cosmos横断プロジェクトを立ち上げました。
これはチーム間の壁を越え、より一貫性のあるシステム開発を行うための取り組みです。

この横断的な取り組みは大きく分けて二つのプロジェクトから構成されます。

  • プロダクトデザインやマネジメントを設計・意思決定し、それを浸透させるプロジェクト
  • システムアーキテクチャのポリシーやルールを設計・意思決定し、それを浸透させるプロジェクト

本記事で取り上げる「Cosmos横断プロジェクト」は、私が所属している後者のプロジェクトを指しています。
前者のプロジェクトについては、ここでは扱いません。

Cosmos横断プロジェクトの目的とスコープ

このプロジェクトの主な目的は、Cosmosプラットフォーム全体を見渡して横断的な取り組みを推進することです。
すでに稼働しているシステムには配慮しつつ、新たに開発するコンポーネントやサービスでは、一貫性のあるアプローチを適用していくことを目指しています。

特に解決したい課題のひとつとして、各チームが独自の判断でアーキテクチャに関わる重要な決定を行っている状況があります。
短期的にはスピードを優先できる反面、長期的にはプラットフォーム全体の整合性や保守性に影響を及ぼす可能性があります。

そこで、プラットフォーム全体に大きな影響を与える設計や技術選択などの意思決定プロセスにおいて、Cosmos横断プロジェクトで検証や設計・レビューする仕組みをつくり、全体とチームの両視点をうまく調和させようとしています。

とはいえ、現時点では既存の基幹システム(以下、GYRO)のリプレイスが組織全体での最優先事項となっています。
そのため、大掛かりな再設計や開発を即座に進めるのは難しいのが実情です。

そこで当面のスコープとしては、GYROからCosmosへのリプレイスを通じてトライアルを行うことで、今回のアプローチが有効かどうかを検証していくことにしました。

これらの取り組みを通して得られた知見をベースに、最終的にはCosmosのサービス群全体に同様のアプローチを広げていく考えです。

策定したポリシーやルール

Cosmosにおけるサービス構成やアーキテクチャの設計方針

Cosmosでは、マイクロサービスの数に比例してチーム数または兼任数が増え、Cosmos全体を見据えた意思決定が困難になり、局所最適に陥ってしまう状況が見受けられました。
サービス数が過剰に増えることで、組織の開発リソースとのバランスを崩しやすくなるほか、一部のサービスでは担当者が曖昧で保守・運用の責任範囲が不明確なサービスもありました。

結果として、サービスごとの品質管理や意思決定が分散し、Cosmosとして達成すべきゴールに集中しづらくなるリスクが懸念されていました。

加えて、各チームが自分たちのサービスを設計・開発する際、他のチームの状況まで十分に把握しきれず、局所最適のまま進んでしまうケースも散見されました。
さらに、サービス間の通信方式としてREST・GraphQL・Pub/Subメッセージングなど、多様なアプローチが混在している点も課題として挙げられました。
自由度の高さはメリットとなる一方、標準化やガイドラインの整備が追いつかないと、プラットフォーム全体の連携や把握が難しくなる要因になります。

ネットワーク制御ルールにも似たような問題が生じており、チーム間で十分に共有されていないため、サービス間の通信境界やセキュリティポリシーの認識にズレが生じるケースもありました。

他にも複数のサービスが存在しますが、便宜上CRMとStoreのみ記載しています。

こうした課題を踏まえ、よほど特別な要件がない限り、既存のサービスやアーキテクチャへ組み込むことを基本とし、サービス数を抑える方針にしました
これにより、組織全体での合意形成や方針策定を円滑に進め、Cosmosとして本来注力すべき領域にリソースを集中させようと考えています。

ドメインの再整理

まずはCosmos全体のドメインを再整理し、大きく「問い合わせ領域(広義のCRM)」と「買取査定領域(広義のDeal)」に分割することとしました。

それぞれが担う業務範囲を明確にし、チームの担当範囲を明確化することで、複数に分散していたドメイン知識を整理する狙いがあります。
在庫管理などの領域もありますが、全体を一度に推し進めようとした場合、コミュニケーションコストの増大や手戻りによる無駄が発生する懸念があります。
そのため、細かくフィードバックを得ながら調整できるよう、まずはこの二つの領域に注力する方針にしました。

他にも複数のドメインや機能が存在しますが、便宜上CRMとDealのみ記載しています。

モジュラモノリスの採用

続いて、当面のアーキテクチャとして「モジュラモノリス」を採用することに決定しました。

具体的には、問い合わせ領域(広義のCRM)に関わる機能はCRMサービスに集約し、買取査定領域(広義のDeal)に関わる機能はDealサービスに集約する方針です。
いずれのサービスでも、ドメインごとにモジュールを分割して境界を明確にしています。

フロントエンドの設計

画面は基本的に機能単位で提供し、それぞれのモジュール(たとえばCRM内のReservationなど)ごとに画面やメニュー構成を意識しています。
モジュール単位で厳密に画面を分割するのではなく、あくまでドメインごとに必要なビューやメニューを切り替える形を想定しています。

CRMでのメニュー構成の例としては、以下のようになっています。

  • コミュニケーション管理: /communication/search
  • アポイントメント管理: /appointment/search

いずれも src/pages/ 配下でそれぞれの機能を切り出し、モジュールの境界をわかりやすく保つように設計しています。

一方でPC・スマホなどの画面要件が全く異なる場合、分割する方針でも問題ないとしています。

バックエンドの設計

モジュラモノリスの設計については、以下のような点を押さえています。

1つのサービス(たとえばCRM)の中に複数のモジュールを設け、ディレクトリ構成でドメイン境界を示します。
一方で重要なポイントとしては、過度に作り込むことを非推奨とし、工数をかけすぎない程度に設計する方針にしました。

CRMの例を挙げると、開発当初よりDDD+オニオンアーキテクチャを採用していましたので、それぞれのモジュール(=ディレクトリ)を作成し、その配下に既存のレイヤー構成を維持するようにしています。

  • Before
/
├── handler/
├── usecase/
├── domain/
└── repository/
  • After
/
├── crm/
│   ├── handler/
│   ├── usecase/
│   ├── domain/
│   ├── repository/
│   └── public/
├── reservation/
│   ├── handler/
│   ├── usecase/
│   ├── domain/
│   ├── repository/
│   └── public/
└── shared/

サービス内に複数モジュールが存在するため、モジュール同士が密結合にならないように以下のルールを設定しています。

  1. モジュール同士の連携は、公開インターフェース(public)を介して行うこと
  2. 他のモジュールのDBに直接依存しないこと

ここでいう「公開インターフェース」とは、モジュラモノリスにおいて、各モジュールが外部に公開するよう定義されたAPI(実態はメソッド)を指します。
モジュール内部の実装詳細は隠蔽され、他のモジュールからはこの公開インターフェースを通じてのみアクセス可能となるように設計しています。
こうすることで、将来的な分割を容易にする仕組みを整えています。

サービス間連携

Cosmosにおけるサービス間連携については、最終的な意思決定を各チームに移譲するという基本方針をとりながら、以下のような緩やかな制約を設けています。

フロントエンドからドメインを跨いだ呼び出しを許容

API Gatewayを経由し、別ドメイン(サービス)のAPIをフロントエンドから直接呼び出すことを許容します。
これは、別ドメインを単に代理するためのAPIや、過度にBFFへビジネスロジックを寄せることを避け、マイクロサービス本来のAPI連携を活かすことで開発速度を向上する狙いがあります。

設計時の留意点

フロントエンドが直接複数のバックエンドを呼び出す際、トランザクション管理が複雑にならないかを事前に確認します。
データ整合性のレベルや、バックエンド間の依存関係を考慮し、場合によってはフロントエンドから直接呼び出さず、同一ドメイン内で処理をラップすることも検討します。

基本的にはRESTを採用する

現在はGYROへのリプレイスを優先する都合上、REST APIによる通信を基本としています。
今後、運用を進めていく中で要件が拡張した場合は、gRPCやPub/Subメッセージなど他の通信方式も検討する予定です。

Cosmosにおける外部連携の設計やポリシー

CRMでは、GYROにある顧客管理・予約管理サービスのリプレイス先として稼働する都合上、LP(Web問い合わせ)やChatPlus(チャットボット)など複数の外部サービスと連携する必要があります。
そこでCosmos内を調査したところ、すでに販売管理サービス(以下、EXS)が外部からのアクセス経路を設けていることがわかりました。

確認したところ、Cosmos全体として外部連携に関する方針やポリシーが無かったため、セキュリティリスクや運用上の混乱を招かないためにも、Cosmos全体として標準的な認証認可の仕組みやアクセス制御のポリシーを整理するべきだと考えました。

現在、以下のようにサービスと外部連携が行われており、サービスごとに通信方法や認証方式が異なる状態です。

サービス (to) 連携が必要な外部サービス (from)
CRM 外部チャットサービス
EXS 外部ECサイト

ポイントを整理すると、以下のようになります。

  1. 認証認可
    • CosmosではAuth0でアクセストークン(JWT)を発行し、API Gatewayで認証を行った上で、マイクロサービスがJWT内のロールに基づき認可する構成。
  2. マイクロサービスの配置・アクセス制御
    • 各サービスは異なるGoogle Cloudプロジェクトに存在し、すべてのマイクロサービスをCloud Run上に配置。
    • API Gateway → マイクロサービス間はインターネット経由。
    • マイクロサービスはIAMによるサービス間認証またはIP制限(Cloud Load Balancing + Cloud Armor)でアクセスを制御。
  3. 外部サービスの制約
    • ChatPlusやIVRのように認証方法の自由度が低いサービスと、Web予約サービスのように当社管理で認証方法の自由度が高いものが混在。
    • どのパターンでも、通信のどこかでJWTが必要であり、さらにIAM認証またはIP制限を突破する仕組みが必要。

CRMとEXSのアーキテクチャですが、便宜上一部のみを記載しています。

認証の仕組みを集約するためには、大きく以下3つの案のどれかを選択する必要があります。

  1. 既存のAPI Gatewayに外部連携できる仕組みを用意する
  2. 外部連携専用のAPI Gatewayを新たに設け、各マイクロサービスへ通信を流す
  3. 外部連携専用のAPI Gatewayを新たに設け、既存のAPI Gatewayへ通信を流す

既存のAPI Gatewayは、複数のマイクロサービスに渡って行う処理を統一的にコントロールし、各サービスが自分たちのビジネスロジックのみに集中できるよう設計しています。
そのため、以下のような機能があります。

  • JWTによる認証、利用停止(Revoke)
  • ルーティング

など。

そのため、既存のAPI Gatewayに外部連携できる仕組みを用意すると、責務が汚染されるリスクがあると考えました。
ここまでの理由から、2または3の「外部連携専用のAPI Gatewayを用意する」案が望ましいと判断しました。

では、2または3のどちらかですが、2の「外部連携専用のAPI Gatewayを新たに設け、各マイクロサービスへ通信を流す」案は以下の理由から見送りました。

  • 外部連携専用のAPI Gatewayから各マイクロサービスへ通信を流すと、既存のAPI Gatewayへ通信を流すよりも、トレーサビリティが低くなる。
  • 各マイクロサービスでは、外部連携専用のAPI Gatewayからのアクセスも許可する必要があり、認証認可ポリシーの分散を招く。

こういった理由から、最終的には3の「外部連携専用のAPI Gatewayを新たに設け、既存のAPI Gatewayへ通信を流す」案を選択しました。

全体的な方針は定まりましたが、外部連携専用のAPI Gatewayを新たに設けることは、開発・運用コストともに決して低くありません。
現状、GYROのリプレイスを優先している背景を踏まえると、すぐにその体制を整えるのは難しい場面もあるでしょう。

また、買取申込みを担うCRMと販売を担うEXSはドメイン上、外部連携が発生します。
しかし、その他のサービスでは外部連携を必要とする可能性が低いので、他のサービスでは認証認可の仕組みを整える必要がありません。

こうした理由から、中長期的にはCosmos全体で認証認可を一元管理するというゴールは定めつつ、短期的にはCRMとEXSのみで個別に外部連携の認証を整える形で落としどころを探っています。
先に申し上げた通りデメリットはあるものの、足元で進めている開発などを踏まえればやむを得ない面もあるのが実状です。

どのように浸透させるか

それぞれのCosmosプロジェクトに説明する場を設けています。

特に私はGYROからCosmosへのリプレイスをリードしている立場上、他チームとのコミュニケーションが多いです。
そのため、自分が軸になりコミュニケーションを取ることで、ドメイン的に近いチームから浸透させることを目指しています。

私は、こういったルールやポリシーの適用には、しっかりと背景・目的を説明することが唯一の有効な手段だと考えています。
表面的な「こうしましょう」という指示だけでは、Cosmos標準の意図や各チームが自分たちの課題解決にどう役立つのか理解できず、浸透させることは難しいです。

内容によってハレーションはあると想像していますが、ここは根気よく伝えていくしかないと考えています。

さいごに

私自身、このプロジェクトでは優先度を見誤らないように気を配りつつ、常に現場感を持って取り組むことを大事にしています。

Cosmos横断プロジェクトは、技術書や生成AIが提示するベストプラクティスなどをそのまま適用するための場ではありません。
理想論に偏りすぎると、現場とのギャップが生まれてしまいます。

リスクやトレードオフが伴うケースもありますし、短期的には戦略的に技術的負債を借り入れることを選択する場合もあります。
しかし、組織としての優先度や各プロジェクトの事情を考慮しつつ、中長期的な視点で意思決定していきたいと考えています。

今後のスケジュールとしては、以下を予定しています。

  • FY25下期までに「Stock」を導入し、買取申込みから在庫管理までの基幹システムをローンチ
  • FY26上期からはレクストHD(福ちゃん)へのシステム導入を開始し、グループ全体への展開を予定

グループ会社へCosmosを展開することが控えているため、今後さらに多くの課題が見えてくるかと思います。
そうした局面でも我々が率先してオーナーシップを発揮し、最適な意思決定を積み重ねていきたいと考えています。

バイセルではエンジニアを随時募集しております。興味のある方はぜひ以下の採用サイトをご覧ください。

herp.careers