Open7

AWSでGraphQLサーバーをたてるときの選択肢を比較

Eringi_V3Eringi_V3

AWSでGraphQLサーバーを用意する場合、AppSyncに目が行きがちですが、他にも選択肢があり場面によって使い分けても良さそうなのでそれぞれを比較、整理してみます。

前提条件

  • フロントエンドもバックエンドもTypeScriptで開発したい
  • できるだけサーバーレスでやりたい
  • 開発速度を早めながらも、優れたDXで開発したい

比較する選択肢

  • AppSync
  • Hasura
  • Apollo Server, Nest.jsなど最初から全てコードを書く方法
Eringi_V3Eringi_V3

実行環境

何のサービスを使って動かすか。できるだけ手間が少なくて管理が用意だと嬉しい。

AppSync

AppSyncはマネージドなので、自分でホスティングする必要はない。ただ、Lambdaでリゾルバを書く場合は別途Lambdaのデプロイが必要な認識。

Hasura

Hasura Cloudを使う方法と、自前でコンテナをデプロイする方法がある。
Hasura Cloudはマネージド。自前でコンテナをデプロイする場合は、AWSなのでApp RunnerかECSかFargateあたりを使うことになりそう。サーバーレスでできると嬉しいという前提があるのでApp Runnerで動かせると嬉しい。

Apollo Server, Nest.jsなど

Node.jsが動く環境なら何を使ってもいいはず。

Eringi_V3Eringi_V3

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が動くかどうかは未調査。

Eringi_V3Eringi_V3

クライアントのデータフェッチ

AppSync

公式が推奨しているのはAmplifyが提供しているAPIを介してデータフェッチを行う方法。
https://docs.amplify.aws/lib/graphqlapi/getting-started/q/platform/js/
しかし、TypeScriptでこの方法を用いる場合、codegenで生成された型をasで型アサーションして使うことになるのでちょっと微妙。せめてGenericsで指定できてほしい。
あとインターフェースがReactに最適化されていない(data, isLoading, errorみたいな感じで返してくれるhookがほしい)のも難点。
ただ、Amplifyが提供しているAPIをガン無視して自分でデータフェッチの足回りを整える方法もあって、これをやれば前述のデメリットは解消できそう。
https://zenn.dev/hitochan777/articles/urql-amplify

Hasura

クライアントは自由な方法でcodegen、データフェッチすることができる。
個人的にはHasura + urqlの体験は最高だと思っていて、データフェッチに関する責任をほぼ全て押し付けることができる。

Apollo Server, Nest.jsなど

Hasuraと同様に自由。

Eringi_V3Eringi_V3

開発工数

開発にかかる時間。できるだけ早く開発が進むと嬉しい。

App Sync

VTLやLambdaを書く必要がある。

Hasura

単純なCRUDなら自動生成されたAPIを使うだけで済むのでかなりの工数削減が見込める。
現実的にはビジネスロジックを含んだMutationの多くはHasuraのAPIだけではまかなえないので、Remote SchemaやActionsを使ってコードを書くことになる。
それでもQueryのリゾルバのほとんどは実装せずに済むはずなのでとても魅力的。

Apollo Server, Nest.jsなど

基本的にすべて自分でコードを書く必要があるため工数はそれなりにかかる。けどコントロールはしやすそう。

Eringi_V3Eringi_V3

結論

何よりも爆速である程度動くものを作りたい

→Hasuraが良さそう。App RunnerだとSubscriptionが使えないけど最悪クライアントでポーリングすれば実現自体はできる。

Subscriptionが必要になりそうということがある程度見えている

→App Syncが良さそう。

開発リソースに余裕があって長期的にコントローラブルな開発がしたい

→自分でコードを書く(Apollo Server, Nest.jsなど)のが良さそう。Lambdaでも頑張ればSubscription実現できるっぽい(?)
https://www.apollographql.com/docs/apollo-server/data/subscriptions/#production-pubsub-libraries

Eringi_V3Eringi_V3

余談

はやくApp RunnerがWebSocketに対応してほしい。そしたら色々解決する。