複雑で変化の激しい介護業界に立ち向かうアーキテクチャ選定とその背景

介護事業者向け経営支援サービス「カイポケ」のソフトウェア開発者の空中清高(@soranakk)です。 2021年12月に入社し、介護事業者向け経営支援サービス「カイポケ」のフルリニューアルプロジェクトに携わっています。 今回はフルリニューアルプロジェクトのアーキテクチャ選定や背景についてご紹介したいと思います。

フルリニューアルプロジェクトのアーキテクチャ

フルリニューアルプロジェクトのシステムはざっくりと解説すると、バックエンドにいくつかのサービスが並んでいて、フロントエンドとバックエンドの間にゲートウェイが立っているサービスベースアーキテクチャになっています。 それぞれのサービスはAWSに配置するようになっていて、この図のような構成になっています。

またフロントエンドとバックエンドはGraphQLを利用して連携している形になっていて、さらにバックエンド間通信においてもGraphQLを利用しています。 このようなアーキテクチャを採用したのは介護業界で適切なソフトウェアを開発するためです。 そこで、介護業界とはどんなものなのかを説明して、なぜこのようなアーキテクチャを採用したのかを深ぼっていきたいと思います。

複雑で変化の激しい介護業界

まず一口に介護業界と言っても、そこには多種な介護サービスがあり、また介護サービスには登場人物がたくさんいます。 介護サービスは通常のサービスと異なり、介護を受ける利用者が介護サービスを提供している事業者から介護サービスを受ける、というだけではありません。 その人にどんな介護サービスが必要で、どこの事業所ならその介護サービスが提供できて、一月分の予定(ケアプランと言います)はどうしたらいいか、ということを考えて利用者にケアプランを提供するケアマネジャーという方がいます。 介護が必要になった人はまず、このケアマネジャーからケアプランを受け取って、それを元に介護サービスを提供している事業所で介護サービスを受ける、という形になっています。 また、この時のお金の流れも普通の買い物などと異なり、介護保険というものが大きく関わってきます。 利用者は介護サービスを受けるときに全額負担ではなく、介護保険によって1~3割の負担を事業所に支払います。 介護サービスを提供した事業者は利用者から受け取らなかった保険分は1ヶ月分をまとめて次の月に国民健康保険団体連合会(通称:国保連)に請求して残りの金額を受け取る(介護保険請求)、という流れになっています。 また、そもそも利用者から直接報酬を受け取っていないケアマネジャーは次の月にまとめて国保連に請求することで報酬を受け取るようになっています。 このときケアマネジャーの提出するケアプランの内容と事業所の提出するサービスの提供実績に齟齬があると介護給付費が支払われないため、単に国保連に提出するだけではない複雑さがあります。

介護保険請求の流れ

さてここまでで、介護サービスを受ける人、ケアプランを決定するケアマネジャー、介護サービスを提供する事業所、介護給付費を支払う国保連、という登場人物が出てきました。

さらに介護サービスと言っても、そのサービスの種類はたくさんあります。 介護施設で受けるサービスの他に、例えば在宅で受けるサービスは内容によって数種類ありますし、他にも福祉用具の貸し出しサービスなど、本当にたくさんのサービス種類があります。 さらに数年毎に法改正が行われるため、たびたびルールに変更が加わったりサービス種類が増えたりと変化がとても激しいです。

サービスベースアーキテクチャ

カイポケのフルリニューアルプロジェクトでは、このように複雑で変化の激しい介護事業の環境に耐えながら継続して開発し続けられるシステムの形をドメイン駆動設計を通じて考えてきました。 その結果、「カイポケ」はいくつかの領域に分割できるだろうということがわかってきました。 大まかに言うと、ある介護サービス種類に特化した領域、介護保険との関連が強い介護報酬に関係する領域、カイポケをSaaSとして提供するための領域、などです。 そこでカイポケのフルリニューアルプロジェクトでは、確実に分解できそうな粒度の粗い領域毎のマイクロサービスにシステムを分割するサービスベースアーキテクチャを採用することにしました。 これまでモノリシックだった「カイポケ」をいくつかのサービスに分割して並行開発体制を取ることで、介護事業の複雑さや法改正による変化に対応しようとしています。

サービス分割を行なったばかりの頃は、まだフロントエンドとバックエンドには分かれておらず、それぞれのサービス毎にカイポケを開発していく想定でした。 いわゆるマイクロフロントエンド構成です。 次はどのようにしてマイクロフロントエンド構成からフロントエンドとバックエンドが分かれたのかについて、ご紹介したいと思います。

フロントエンドとバックエンドの分割

初期のアーキテクチャでは分割したサービス毎にフロントエンドを開発するマイクロフロントエンドの構成を考えていました。 しかし更なるドメイン駆動設計やユーザーテストの結果からバックエンドの分け方とフロントエンドの分け方は異なることがわかってきました。 バックエンドは介護業界のサービス種類や介護保険などの法律上の制約で分けることができたのですが、フロントエンドも同じような分け方をすると使いづらいソフトウェアになってしまうことがわかりました。 また、フロントエンドはカイポケを利用する人、つまり介護業界に登場する人物毎に分けた方がUXがよさそうということがわかりました。 そのためフロントエンドはバックエンドのサービスとは分かれ、マイクロフロントエンドの構成をやめることになりました。

その経緯について、こちらの記事でも詳細に書かれていますので、ご紹介します。

tech.bm-sms.co.jp

ただし上の記事からのアップデートとして、一部の利用者に依らない共通のフロントエンドについてはバックエンドのサービスと合わせてマイクロフロントエンド構成で開発を進めているサービスもあります。

フロントエンド/バックエンド連携

フロントエンドとバックエンドは分かれましたが、フロントエンドからいくつもあるバックエンドを選んで通信を行うのは辛いだろうということからフロントエンドとバックエンドの間にAPIゲートウェイを置いています。 当初から認証の観点でゲートウェイを置くことになっていましたが、さらにAPIを束ねる機能も担うことになりました。 また、フロントエンド/バックエンド間通信のプロトコルはクライアント側から柔軟にデータの取得方法を選択できるGraphQLを採用しています。 このAPIゲートウェイの置き方を少し工夫しているのでご紹介します。

APIゲートウェイでバックエンドのGraphQLを束ねる

フロントエンドからはゲートウェイだけが見える状態になっていて、ゲートウェイへGraphQLリクエストがやってきます。 その後のゲートウェイから適切なバックエンドへ流す処理を実現するため Apollo Federation を採用しています。 Apollo Federationは複数あるGraphQLサーバーを一つにまとめることができる技術です。 Apollo Federationを用いることでゲートウェイにやってきたGraphQLリクエストを適切なバックエンドのGraphQLサーバーに流すことができ、適切なレスポンスをフロントエンドに返すことが可能になります。 Apollo Federation を使わないで複数のGraphQLを束ねようとすると、ゲートウェイにやってきたGraphQLリクエストから適切なサーバーを選んでルーティングする処理を実装しなければならず、実装コストの増加や管理が煩雑になる懸念があります。 ただし、Apollo Federation を使う場合にも注意しなければならないことがあります。 バックエンドのGraphQLサーバーはそれぞれ独立しているのですが、最終的にゲートウェイで一つに束ねられることになります。 そのためバックエンドのGraphQLのスキーマ同士で、それぞれ名前等が衝突しないように作っておく必要があります。 また命名規則も統一しておかないと、あるバックエンドのGraphQLスキーマでは複数形は s を付けるようになっているけど、別のバックエンドでは List と付けるようになっていて〜、といった混乱が起こってしまいます。 なのでスキーマの命名規則などはバックエンドのチーム間で話し合って統一するようにしています。

また名前の衝突など、バックエンドのGraphQLスキーマを束ねた結果に不整合が発生していないことをチェックするため、GraphQLのスキーマ管理サーバーとしてApollo Studioを利用しています。 それぞれのバックエンドサーバーはApollo StudioにGraphQLスキーマを登録する形になっていて、ゲートウェイからはApollo Studioを参照して合成GraphQLスキーマを取得するようにしています。 またバックエンドのチームはCIで合成したGraphQLスキーマが壊れてしまわないこともチェックするようにして、不意に壊れてしまってフロントエンドからアクセスできなくなることを防いでいます。 フロントエンド・バックエンド間の通信だけでなく、サービス間連携においてもGraphQLを採用しています。次に、そのことについてご紹介します。

サービス間連携におけるGraphQLの採用

リニューアルプロジェクトではバックエンド間のサービス間通信プロトコルでもGraphQLを採用しています。 バックエンド間通信だけを考えるとGraphQLは適切なのだろうか?といった疑問もありました。 しかしそれぞれのバックエンドはフロントエンド用にGraphQLプロトコルを提供することが決定していたため、サービス間通信用に新しいプロトコルに対応すると、フロントエンド用とサービス間通信用で二つのプロトコルを管理することになります。 また二種類のスキーマを管理するのは煩雑になるだろうというもありました。 そこで、スキーマ管理とプロトコルスタックを少なくしてシンプルにしたいという理由からバックエンド間通信でもGraphQLを利用することに決定しました。

フロントエンド用とバックエンドのサービス間通信用のGraphQLスキーマを統一的に管理するために少し工夫しています。 完全に二つのスキーマファイルを分けて管理する方法も検討したのですが、queryやmutationは違うだろうけど、type等は同じものを使いたい場面がありそうで、その場合にそれらを共有する方法をどうしたらいいのかが課題になりました。 そこでGraphQLのDirectiveとApollo Studioの機能を使って、一つのスキーマファイルで両方を管理できるようにしています。 Directiveには可視性を制御できるものがあり、バックエンドのサービス間通信用のスキーマは不可視の状態でApollo Studioに登録することで、ゲートウェイからApollo Studioを参照したときは存在しないように見せることができます。 一方、サービス間通信の場合のスキーマはバックエンドの統一スキーマではなく、通信したいバックエンド単体のスキーマで良いので、直接そのスキーマを見るようにして参照します。

最適なシステムの形を目指して

今回紹介した構成で実際に並行開発体制を維持しながら法改正に対応できるかどうかは、これから確認していくことになります。 その結果からまたドメイン駆動設計を行うというサイクルを通じて、私たちはより良い「カイポケ」を作り上げていこうとしています。 昨今のソフトウェアは開発してリリースしたら終わりという訳ではなく、継続して改善し続けていくことが基本となっています。 私たち「カイポケ」のフルリニューアルプロジェクトチームでも次の法改正を視野に入れながら、変化していく介護業界で継続して改善し続けられるシステムアーキテクチャを目指して開発を続けています。 実際、今回紹介したアーキテクチャではフロントエンドとバックエンドは完全に分かれているのですが、さらなる検討の結果から、一部の利用者に依らない共通のフロントエンドについてはマイクロフロントエンドのようにバックエンドもフロントエンドも開発している状況だったりします。 こういったエス・エム・エスでのアーキテクトの仕事の仕方についてはこちらの記事で詳細に書かれていますのでご紹介します。

tech.bm-sms.co.jp

最後になりますが、フルリニューアルプロジェクトではエンジニアだけでなくプロダクトマネージャー・UI/UXデザイナーなど、複雑で変化の激しい介護業界での最適なシステムの形を目指して一緒に開発をしてくれるメンバーを募集中です! プロジェクト専用サイト内に募集中のポジションを記載していますので、興味のある方はぜひご覧ください!

またカジュアル面談もやっておりますので「選考に進む気持ちはまだないけどもっと突っ込んだ話を聞きたい」とか「ここはどうなってるの?」みたいな感じで軽く話してみるだけでも結構ですので、興味があれば是非お気軽にお声がけください!