こんにちは。
最近、複数のWebアプリケーションで共通のユーザー情報を扱いたいという要件が出てきたので、どのように設計するべきか?ということを考えていました。
今回は、そのときに考えた3パターンのpros/consをまとめました。
要件
今回検討する前提となった要件は以下のとおりです。
-
複数のWebアプリケーションで共通のユーザー情報を扱う
例えば、楽天IDのような共通のID、パスワードでログインできるようにしたい -
その他の情報が各アプリケーションで存在する
全く同じアプリケーションを建てるという話ではなく、それぞれ別のアプリケーションである -
すでに一部のアプリケーションがモノリポで存在している
今回の要件を満たすために、モノリポをやめてマイクロサービスにするということもできるがもちろんコストがかかる
3パターンの設計
今回あり得るパターンとして、以下の3つを考えてみました。
分類するにあたり、適当に命名してみましたが特に有名な名前があるわけではないので、あくまで私が勝手に命名したものであることをご了承ください。
1. multi DB構成
早速結論になってしまうのですが、今回はこちらで設計することにしました。
詳細は図のとおりなのですが、
- 共通のユーザー情報を扱うDBを別途用意する
- そのDBには共通の情報(例えばユーザー情報)のみを格納する
- それ以外の情報を格納するDBは各アプリケーションごとに用意する
というイメージです。
今回はすでにあったアプリケーションはRailsで作成していたということもあり、multi DB対応はデフォルトの機能として存在しているため、比較的簡単に対応できそうだということも選択した理由の一つです。
この構成のメリットとしては、以下のようなものが挙げられると思います。
- それぞれのアプリで固有の情報についてはそれぞれのDBに格納できるため、アプリ設計としてはそれぞれがシンプルになりやすい
- それぞれのアプリが独立しているため、新規アプリの追加や削除がしやすく、片方のアプリに障害が発生しても他方のアプリは動作する
- デプロイもそれぞれのアプリごとに行えるため、デプロイのタイミングを合わせる必要がない
一方で、デメリットとしては以下のようなものが挙げられると思います。
- 共通の情報を扱うDBを別途用意する必要があるため、DB分のコストがかかる
- それぞれのアプリで共通の情報を扱うため、それぞれのアプリで共通の情報を扱うためのコードを書く必要がある
- 固有のDBに書いた情報が後から共通の情報になる可能性があるため、そのときの移行対応が大変になる可能性がある
- アプリのアクセスが増えると、共通の情報を扱うDBの負荷が増える可能性がある
- 共通の情報を扱うDBの障害によって、それぞれのアプリも動作しなくなる
- アクセスが増えると、共通DBに同時にリクエストが投げられた時の排他制御が必要になる可能性がある
2. メインアプリ構成
2つ目のパターンとして、メインアプリ構成というものを考えてみました。
こちらは、共通の情報を扱うDBを用意するのではなく、「メインアプリ」というものを用意して、そこで共通の情報を扱うというものです。
そのメインアプリから、それぞれのアプリに対してAPIを公開して、それぞれのアプリはそのAPIを使って共通の情報を扱うことができるのではないかと考えました。
メリットとしては、
- 共通DBを用意する必要がないため、その分のコストがかからない
- APIはメインアプリのみで公開するため、それぞれのアプリはメインアプリのAPIを使うだけでよい
- 共通の情報はあくまで一つのアプリで管理するため、移行対応がしやすく、また排他制御もしやすい
デメリットとしては、
- メインアプリが障害になると、それぞれのアプリも動作しなくなる
- APIを公開するためのコードと、それぞれのアプリでAPIを叩くためのコードを書く必要がある
- メインアプリのAPIの仕様変更によって、それぞれのアプリのコードも変更する必要がある
- 固有のDBに書いた情報が後から共通の情報になる可能性があるため、そのときの移行対応が大変になる可能性がある
- アクセスが増えると、メインアプリのAPIの負荷が増える可能性がある
- メインでないアプリのリクエストはメインアプリのAPIを経由するため、multi DB構成よりも遅くなる可能性がある
というものが挙げられると思います。
今回こちらを選択しなかった理由としては、開発コストが高くなりそうだということが挙げられます。
APIを公開するためのコードと、それぞれのアプリでAPIを叩くためのコードを書く必要があるため、それぞれに別のコードを書く必要があったところがネックでした。
3. API制御構成
3つ目のパターンとして、API制御構成というものを考えてみました。
こちらは、多少2と雰囲気が似ているのですが、メインアプリの代わりにAPIアプリというものを用意して、そこで全ての情報を扱うというものです。
メリットとしては、
- フロントエンドとバックエンドを完全に切り分けられるため、それぞれの責務が明確になる
- APIアプリのみで全ての情報を扱うため、移行対応がしやすく、また排他制御もしやすい
- DBは一つなので、固有だと思っていた情報が共通の情報になったとしてもデータの移行作業が発生しない
デメリットとしては、
- APIを公開するためのコードと、それぞれのアプリでAPIを叩くためのコードを書く必要がある
- APIアプリが障害になると、全てのアプリが動作しなくなる
- アクセスが増えると、APIアプリの負荷が増える可能性がある
- フロントエンドとバックエンドを完全に切り分けるため、初期の開発コストが高くなりそう
という感じでしょうか。
こちらも2と同様に、開発コストが高くなりそうだということが挙げられます。
しかし、2と違うのは、APIアプリのみで全ての情報を扱うため、移行対応がしやすく、また排他制御もしやすいという点です。
今回はすでに一つのモノリポのアプリが存在していたためこちらは採用しませんでしたが、綺麗な設計にはなるのでもし状況が違えば採用してもよかったかもしれません。
複雑になった場合もAPIアプリケーションを複数用意するなどがしやすいのも、大規模なシステムになってきたときには良さそうですよね。
まとめ
今回は、複数のWebアプリケーションで共通のユーザー情報を扱いたいときにどのように設計するべきか?ということを考えてみました。
結論としては、multi DB構成を採用することにしましたが、本当にそれぞれ良し悪しがあると思うので、状況に応じて適切なものを選択する必要が出てきそうですね。
簡単に以下にデメリットベースで表にまとめてみました。
メリットかと言われると微妙だけどデメリットだと言われるとそうだな、というものが多かったのでデメリットベースでまとめてみました。見づらくてすみません
multi DB構成 | メインアプリ構成 | API制御構成 | |
---|---|---|---|
共通DBを用意する必要がある | ○ | × | × |
他アプリの障害によって、他のアプリにも障害が発生するリスクがある | × | ○ | ○ |
それぞれのアプリ内に同じコードを書く必要がある | ○ | × | × |
固有のDBに書いた情報が後から共通の情報になった場合データ移行が必要になる | ○ | ○ | × |
アクセスが増えるとあるアプリの負荷が高まりやすい | × | ○ | ○ |
メインアプリのAPIの仕様変更によって、それぞれのアプリのコードも変更する必要がある | × | ○ | ○ |
フロントエンドとバックエンドを完全に切り分けられる | × | × | ○ |
初期の開発コストが高くなりそう | × | ○ | ○ |
デメリットとして書きましたが、例えばそれぞれのアプリ内に同じコードを書く必要がある
などはライブラリを作ったり、git submoduleを使ったりすることで解決できるかもしれません。
今回は時間が取りきれず、ライブラリの開発までには至りませんでしたが、もし時間があればライブラリを作ってmulti DB構成というのが一番良いのかもしれませんね。
モノリポかつmulti DBが標準で可能なRailsに慣れているエンジニア目線では、少なくともそのように感じました。
ぜひNode.jsでNext.jsとNestJSなどに慣れている方の目線なども聞いてみたいですね。
今回はこのあたりで。