kenju's blog

About Programming and Mathematics

My Understanding about GraphQL vs REST

Abstract

すごく雑にまとめると、以下のような感じ。

  • Client side の実装は圧倒的に楽になる
    • 複数 endpoints からリソースをとってきてまとめる処理が不要になる
    • Versionless で開発できる
  • Server side の労力は変わらない
    • REST 同様開発する必要がある
    • むしろ、REST での Best Practices や定石が効かない(N+1 や Batching 対応など)
  • Ecosystem や Best Practices は整ってきた印象
    • 海外でも国内でも採用事例を聞くようになってきた
    • Monitoring はまだまだ磨き込みの余地あり
      • 例えば、AWS AppSync の Managed Console では 2018 年 11 月初頭現在ほぼなにも監視項目がない(他の AWS Lambda / AWS DynamoDB と比べて貧弱)

REST

[Client] Fetch associated data with multiple HTTP requests

Client side では、欲しいデータが Nest されていたり関連があったりする場合でも、1 HTTP Request でリクエストすることができる。これによって、本来複数リクエストを必要としていたリソースの取得も、1 turn around で実現できる。

ただし、これは Client side から見た場合の話であって、Server side ではそれに対応した実装を行う必要がある。

[Client] Clients cannot tell which data to retrieve

よく言われるように、Client side で必要な attributes を指定できる。これによって、Client side が何を必要としているかが、宣言的に記述できる。

例えば、/repositories/ でレポジトリ情報を取得しようとする。

query { 
  repository(owner: "kenju", name: "2djs") {
    name
    primaryLanguage {
      name
    }
  }
}

GraphQL になる前の Facebook graph APIhttps://github.com/cookpad/garage では、Client side が返して field を Request 側で指定できるものの、殆どの場合はそうではない。

REST の場合、Repository.nameとRepository.primaryLanguage` だけが欲しい場合でも、往々にして不要な attributes も一緒に返ってきてしまう。ネットワーク帯域を無駄遣いしてしまっている。

GraphQL

[Client/Server] Everything is typed

GraphQL では、型宣言が必須である。

後述する通り、 REST でも型は定義できる。しかし、言語仕様自体に組み込まれているか否か、というのはかなり大きな差だと考える。

[Client/Server] Documentation is a first citizen

Schema があるということは、自動生成ドキュメントや mock server もつくりやすくなる。

とはいえ、REST でもこの手のツールはかなり開発されていて使いやすいツールも多いので、REST と比べて優れている、というわけではない。

[Server] Think in Graphs

https://graphql.org/learn/thinking-in-graphs/

Graphs are powerful tools for modeling many real-world phenomena because they resemble our natural mental models and verbal descriptions of the underlying process. With GraphQL, you model your business domain as a graph by defining a schema;

結局の所、Graph ベースで考えるのに向いた Application(e.g. SNS)にはビジネスロジックとデータの宣言が非常に seamless につながって考えられるようになる。Application によっては、REST を導入することによって Graph modeling を Client side で解体して CRUD base で考える、ということをしなくてよくなるので、開発者体験はかなりあがるはず。

また、Graph modeling が一見適していないような従来の管理アプリケーションや普通の CRUD Application でも、「Grpah で考えてみたらどうなるんだろう」という、ビジネスロジックを改めて見つめ直すきっかけをもたらしてくれる。

逆に言うと、Graph ベースで考える必要がある、ということ。例えば、Pagination について、Relay Cursor Connections Specification という仕様が公開されているけれど、offset/limit base で考える Pagination ではなく、cursor base (nodes/edges) で考える必要がある。これは、Feed や Timeline のような Application には向いているが、ページ数ベースで考える kaminari を使っているような Application には向いていない。

REST/GraphQL both does...

Can be typed

REST でも、JSON Schema を使えば型はつけられる。ポイントは、それが任意であり、API 開発者の判断に委ねられているということだ。

GraphQL では、型の宣言自体が仕様に組み込まれている。これによって、必ず型を宣言する必要が生まれてくることで、一定の制約が生まれる。

一般的には、複数クライアントの複数バージョンからリクエストされることを考えると、型という一定の制約があったほうが、Client side での Response Data のハンドリングは自明になる。逆に言うと、JSON Schema が無い field で文字列が返ってくるのか数値が返ってくるのかが自明的ではない場合、Client side で型判定したり Casting したりする必要が出てくる。