AWSでGraphQLサーバーをたてるときの選択肢を比較
AWSでGraphQLサーバーを用意する場合、AppSyncに目が行きがちですが、他にも選択肢があり場面によって使い分けても良さそうなのでそれぞれを比較、整理してみます。
前提条件
- フロントエンドもバックエンドもTypeScriptで開発したい
- できるだけサーバーレスでやりたい
- 開発速度を早めながらも、優れたDXで開発したい
比較する選択肢
- AppSync
- Hasura
- Apollo Server, Nest.jsなど最初から全てコードを書く方法
実行環境
何のサービスを使って動かすか。できるだけ手間が少なくて管理が用意だと嬉しい。
AppSync
AppSyncはマネージドなので、自分でホスティングする必要はない。ただ、Lambdaでリゾルバを書く場合は別途Lambdaのデプロイが必要な認識。
Hasura
Hasura Cloudを使う方法と、自前でコンテナをデプロイする方法がある。
Hasura Cloudはマネージド。自前でコンテナをデプロイする場合は、AWSなのでApp RunnerかECSかFargateあたりを使うことになりそう。サーバーレスでできると嬉しいという前提があるのでApp Runnerで動かせると嬉しい。
Apollo Server, Nest.jsなど
Node.jsが動く環境なら何を使ってもいいはず。
Subscriptionが使えるか
GraphQLのSubscriptionはサーバーで何か変更があったときにサーバーからクライアントに変更を通知できる仕組みです。
リアルタイム性が求められる機能を実装するときに使われることがあるのですが、実装が複雑な場合があったります。
AppSync
@aws_subscribeディレクティブを使えば実現可能なはず。
Hasura
Hasura Cloudを使う場合は特に制約なくSubscriptionが使える。
自前でコンテナをデプロイして使う場合は、実行環境でWebSocketが使えるかどうかに依存する。
App Runnerは2022/03/01現在WebSocketに対応していないので、Subscriptionは使えない。
FargateでSubscriptionが動くかどうかは未調査。
Apollo Server, Nest.jsなど
サーバーレスで動かす場合、Lambda、App Runner、Fargateのいずれかで動かすことになる。
Lambda、App RunnerはWebSocketに対応していないので厳しい。
FargateでSubscriptionが動くかどうかは未調査。
クライアントのデータフェッチ
AppSync
公式が推奨しているのはAmplifyが提供しているAPIを介してデータフェッチを行う方法。
あとインターフェースがReactに最適化されていない(data, isLoading, errorみたいな感じで返してくれるhookがほしい)のも難点。
ただ、Amplifyが提供しているAPIをガン無視して自分でデータフェッチの足回りを整える方法もあって、これをやれば前述のデメリットは解消できそう。
Hasura
クライアントは自由な方法でcodegen、データフェッチすることができる。
個人的にはHasura + urqlの体験は最高だと思っていて、データフェッチに関する責任をほぼ全て押し付けることができる。
Apollo Server, Nest.jsなど
Hasuraと同様に自由。
開発工数
開発にかかる時間。できるだけ早く開発が進むと嬉しい。
App Sync
VTLやLambdaを書く必要がある。
Hasura
単純なCRUDなら自動生成されたAPIを使うだけで済むのでかなりの工数削減が見込める。
現実的にはビジネスロジックを含んだMutationの多くはHasuraのAPIだけではまかなえないので、Remote SchemaやActionsを使ってコードを書くことになる。
それでもQueryのリゾルバのほとんどは実装せずに済むはずなのでとても魅力的。
Apollo Server, Nest.jsなど
基本的にすべて自分でコードを書く必要があるため工数はそれなりにかかる。けどコントロールはしやすそう。
結論
何よりも爆速である程度動くものを作りたい
→Hasuraが良さそう。App RunnerだとSubscriptionが使えないけど最悪クライアントでポーリングすれば実現自体はできる。
Subscriptionが必要になりそうということがある程度見えている
→App Syncが良さそう。
開発リソースに余裕があって長期的にコントローラブルな開発がしたい
→自分でコードを書く(Apollo Server, Nest.jsなど)のが良さそう。Lambdaでも頑張ればSubscription実現できるっぽい(?)
余談
はやくApp RunnerがWebSocketに対応してほしい。そしたら色々解決する。