😈

ぼくのかんがえたさいきょうの個人開発あーきてくちゃ

2021/04/22に公開1

前置き

この記事で紹介するアーキテクチャはあくまで机上論であり、筆者が実際にこれらのアーキテクチャでサービスを運用したことがあるわけではありません。
そのため、考慮漏れ等あるかもしれません。その際はご指摘いただけますと幸いです。

モチベーション

  • 個人開発でアプリケーションを作って運用したい!
  • お金は極力かけたくない!
  • けどいい感じのツールを組み合わせてクールなアーキテクチャにしたい!

対象とするアプリケーションの概要

  • ブラウザで動くウェブアプリケーション
  • 認証機能を持つ
  • DBはNoSQLではなくRDB
  • アプリケーション本体とは別に管理画面アプリケーションが必要

以上を前提として考えました。

ぼくのかんがえたさいきょうあーきてくちゃ

こちらです。

コンポーネントごとに解説させてください。

フロントサーバー

Next.js on Vercelです。
こちらはもはや説明不要の王道構成かと思います。

管理画面

デプロイ先はAWS Amplify Console、アプリケーションはCreate React Appで作るReactのSPAです。
Amplify Consoleは、アプリケーションにAmplifyライブラリやAmplify CLIを使って構築していなくても、それ単体で使えるサービスです。
ビルド周りの面倒を見てくれたり、プルリクエスト単位でのプレビュー環境を用意してくれたりしてとても便利です。
また、数あるホスティング先の中から Amplify Consoleを選択した最大の理由は、無料で使用可能なBasic認証があるからです。
管理画面はBasic認証で守られてたほうがいいかな...?と思ったのでこの選択をしました(もちろんBasic認証とは別にアプリケーション内での認証も行います)。

IDaaS

Auth0を使用します。
が、正直ここは使い慣れているものを選択すれば良いと思っています。
AWS Cognito、Firebase Authentication等。
自分はCognitoとAuth0しか触ったことないですが、Auth0はホスティングされたログインページを日本語化できるのがいいなと感じました(CognitoのHosted UIは日本語化できないので)。

APIサーバー

ここがこのアーキテクチャ最大のキモです。
APIサーバーは、Hasura GraphQL Engineを使用して構築します。
https://hasura.io/

Hasuraをご存じない方に簡単に説明すると、

  • データベースに接続し、テーブルを作成するだけでCRUDのAPIが使用可能になるGraphQLサーバー
  • Auth0のようなIDaaSと連携して、データベースに対しての操作を権限で制御することができる

といった感じのサービスです。

個人開発ってやることが多くて大変ですよね。
フロントのUIを作るだけでも大変なのにバックエンドも0から構築するのは時間がかかる...。
そこで楽をするための選択肢として、Firebaseを使う、Amplifyを使うなどがあると思います。
しかしこれらのバックエンドは基本的にはFireStoreや DynamoDBといったNoSQLを使用するのが一般的であるというのが僕の認識です。
いつかFirebase、Amplifyから脱却したくなったときにNoSQL -> RDBに移行するのは大変そうなイメージがあります(NoSQL触ったことないのでそんなことなかったらご指摘ください)

HasuraはデータベースにRDBを使用します。
ので、最悪Hasuraをやめたくなったときも、データベースは既存のままでアプリケーション層だけ入れ替えれば済むのでまあなんとかなるんじゃないかな、、と考えています。

そして何より基本的なCRUD操作のAPIは自動生成できるのでバックエンドの開発工数は相当削減できそうです。
また、Hasuraの管理画面から、DBの操作に対してロールごとにルールを設定することが可能です。
例えば、フロントサーバーと管理画面でDBに対しての可能な操作を分けて制御したい場合は、フロントサーバーからリクエストするときにUserロール(自分のデータのみ操作可能)を割り当て、管理画面からリクエストするときにはAdminロール(すべてのユーザーのデータを操作可能)を割り当てるようにすれば済みます。
Hasuraは、リクエストヘッダx-hasura-admin-secretに正しい値がセットされているとAdmin権限として扱ってくれるので、管理画面からHasuraにリクエストする場合はこのヘッダを付けてAdmin権限で操作を行います。

DB

HerokuのPostgresを使用します。
AWSやGCPにもフルマネージドなRDBのサービスはありますが、個人開発で使うにはちょっとお高いです。
Herokuは10000レコードまでは無料で使用可能で、無料枠を超えたとしても$9/月で10000000レコードまで使用可能枠を増やせます。
自分が調べた中では、お金を払わずにRDBを使用する前提だとHerokuのPostgres以外に現実的な選択肢がなさそうでした。

FaaS

図ではLambdaを選択していますが、Lambdaでなくても問題ありません。
これは、Hasuraでは対応できないビジネスロジックを処理するために使用します。
HasuraにはActionsという機能があり、HasuraがやってくれるCRUD処理では対応できないようなビジネスロジックを適用したい場合、処理をFaaSに委譲してGraphQLのレスポンスにマージすることができます。
つまり、フロントエンドは常にHasuraのエンドポイントだけ見ていればよく、Hasuraより後ろになにがあるかを意識する必要はないのです。

感想

コンポーネントについての紹介は以上です。
とにかくHasuraがすごいので、Hasuraにベッタリな実装を行うことで開発の速度は高まると思います。
これは個人の考えですが、Hasuraを使う以上剥がしやすい設計とかはあまり考えなくていいのかなとも思います。HasuraはコードをかかずにGraphQLサーバーを用意するという目的に特化しているので、将来RESTにしたくなったらどうしよう...とか考えるより、GraphQLを使い倒す!に倒したほうが恩恵を享受できそうです。
もし、どうしても将来が心配で早い段階でRESTに移行する可能性を捨てきれない、といった場合は、自分ならHasuraを選択せず、 Prismaとかを使って自分でコードを書いてAPIサーバーを構築するかなと思います。

筆者は、マジでこのアーキテクチャが最強だと信じて個人開発を進めようと思っています。
ただ、このアーキテクチャも3回くらいこれが最強だ!と他のアーキテクチャを思いついて、また考え直してというのを繰り返して生まれたので、開発中に他のアーキテクチャに浮気するかもしれません。
真に最強のアーキテクチャなんて幻想ですね。
自分だけの最強アーキテクチャを探し続けようと思います。

ボツ案

以下は、ボツ案というか筆者が作りたいアプリケーションにマッチしなかったアーキテクチャ案です。
せっかく考えたので載せます。

Prisma使ってAPIサーバー自分で用意するパターン


APIサーバーを構築する時間がかかりますが、これもなかなかいいかなと思っています。
ただ、実装の手間を考えたとき、フロントだけで大変だし、サービス本体と管理画面それぞれ別のAuth0に対してJWT検証したりするの面倒くさいなーと思ってしまいました。
とにかく楽をしたかったので自分の場合はHasuraがマッチしました。
ただ、サービスが成長したときにバックエンドをスケールさせやすいのはこちらのアーキテクチャな気がします。
自分でコード書いてるのでかゆいところにまで手が届くでしょうし、Heroku -> 他のクラウド への移行例はググればいっぱい出てくると思うのであとの苦労は少なくて済みそうです。
偉そうにこんなこというと燃えそうで怖いのですが、「EasyのHasura、SimpleのPrisma」かなと感じました。

管理画面が不要なアプリケーションのパターン

Next.jsのgetServersidePropsやapi roureからPrismaでDBにアクセスするパターンです。
APIの数が少なくて、管理画面が不要な小さなアプリケーションならこれを選択すると思います。
Vercelの無料プランではサーバーレス関数の使用可能数が12個までなので、割と簡単に超えてしまいそうなのが不安な点です。

関連

Hasuraはチュートリアルがすごく丁寧だったのでぜひ触ってみてほしいです。
(30分で終わると書いてありますが自分は3時間位かかりました)
テーブルの定義、Auth0との連携、ロールによるアクセス制御、Actionsを使ったビジネルロジックの実装といった、APIサーバーを作るのに必要そうな機能が一通り学べます。
https://hasura.io/learn/graphql/hasura/introduction/

Discussion

______

AWS,GCPなどで組もうとなると、かなりお高くなっちゃうので
安く仕上げる構成を探していました。

参考になりました!ありがとうございます!