はじめに
gRPCとGraphQLをどう使い分けるかがわからず混乱していたので、軽く整理した。
どう違うか
GraphQLはAPI用のクエリ言語で必要なデータを指定することで無駄な通信をしないようにすることができる。
一方でgRPCはProtocol bufferを用いてRPC(サーバー上のメソッドをあたかもクライアント側で呼んでいるかのように見せるもの)を実現している。
どちらも、サーバーに対してリクエストを出しレスポンスを受け取るという目的は一緒。
ただ、gRPCはGraphqlのように柔軟なクエリ(関数呼び出し)はない。
サービスという形でRPCの関数を呼び出し結果を得るが、その結果の形は固定。
また、Mediumの記事でも述べられている通り、gRPCは低レベル向き、GraphQLは高レベル向き。
なので、ウェブアプリを作るときには、フロント側がアクセスするAPIはGraphQLで、そのAPIが通信する別のAPIはgRPCで実装するみたいなことをすればいいっぽい。
ちなみに、web-grpcなるものがあってフロント側でもgRPCを使えるようにはできる。ベストプラクティスはなんだろう。
補足
gRPCとは
gRPCはGoogleが開発したRPC(Remote Procedure Control)のライブラリで、
Protocol Bufferとよばれるシリアライゼーションを用いてRPCを処理する。
Protocol BufferもGoogle生まれ。
RPCはサーバー上のコードをあたかもクライアント側にあるかのように、クライアントから呼び出せる仕組みである。
GraphQL
APIのためのクエリ言語である。次の3つを特徴としている。
- 必要なものを必要な分だけ
例えばJSONを返すようなRESTだと、返ってくるデータにはクライアント側では不要なものも含まれており、
無駄な通信帯域を消費していた。GraphQLでは、クエリを用いて必要なデータのみを取ってくることができる。
例えば以下のように特定の人の情報を返すようなREST APIがあったとする。
もし仮にクライアント側ではid
,firstname
,lastname
しか必要ないとしても、
APIがそういう仕様なので受け取って必要ないものは捨てる。
あるいは、REST APIの仕様を変えて特定の条件下ではid
,firstname
,lastname
しか返さないようにする。
要はREST APIは柔軟性にかける。
{
"person": {
"id": 2,
"age": 25,
"firstname": "dora",
"lastname": "emon"
"phonenumber": [
"080-xxx-yyyy",
"090-zzz-xxxx"
]
}
}
GraphQLでは以下のようにクエリで必要なデータを簡単に指定できる。
{
person {
id
firstname
lastname
}
}
-
できるだけ多くのリソースを一回のリクエストで取得
n + 1問題などのようにリクエスト回数をできるだけ減らすことができる。 例えば/users/${id}
がユーザーIDが${id}のユーザー情報を返すとする。また、そのデータにははユーザーのフォロワーのID一覧がリストで含まれている。もしフォロワーの名前も取得するとなると、フォロワーの数(n)だけ/users/${id}
にアクセスしないといけなくなり、通信のオーバーヘッドが大きくなってしまう。もちろん/users/${id}
で返されるデータにフォロワーの詳細情報も含めることができる。クライアントが必要としない(しなくなるかもしれない)無駄な情報とともに。 -
1つのエンドポイントでAPIを提供
参考サイト
- gRPC公式サイト
- GraphQL公式サイト
- GraphQL & gRPC (Part 1): Mediumの記事