19
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GraphQL でフロントに優しい API を作ろう

Last updated at Posted at 2018-12-21

これはRetty Inc. AdventCalendar2018 21日目の記事です。
昨日は @takumi-suzuki さんの リモート環境をFire HDに切り替えてみた でした。
FireHD が悲しい結末を迎えてしまいましたね。:cry:


はじめまして。Retty Web チームでインターンをしている宇野です。
インターンでは主に、オウンドメディアのRettyグルメニュース(以下、グルメニュース)の開発をしています。今回の記事では、グルメニュースに GraphQL を導入することにしたので、実際に触ってみたいと思います。

はじめに

最初に、GraphQL 導入の経緯を説明します。
グルメニュースには現在、記事を配信する側と入稿する側のサービスが別々に存在します。2つのサービスがあることにより、メンテナンスコストが倍になってしまい手間です。 :worried:
そこで、API を作り一つのサービスにして、サーバーとフロントを分離しようとしています。この API 部分に GraphQL を利用します。

GraphQL とは?

Facebook が開発した、API のためのクエリ言語です。クライアントとサーバーのやりとりを簡単にするために使用されます。
例えば、User 情報を取得する場合 GraphQL では次のように書きます。

type User {
  id: ID
  name: String
}

type Query {
  user: User
}

GraphQL はクエリ言語なので特定の DB やストレージに結びついておらず、RDB だけではなく localStorage や REST API に対しても 使うことができます。

RESTful API との違いは?

RESTful API との違いを次の図で説明していきます。

f3670b34-1b4b-9942-0fa6-409c4118cf0e.png

https://fullstackmark.com/post/17/building-a-graphql-api-with-aspnet-core-2-and-entity-framework-core

RESTful は、ルーティングやスキーマの定義が自由なため、フロント側と並行して開発するのが難しいです。しかし、GraphQL だとエンドポイントは一つで、スキーマの定義もモデルの設計をしていれば問題なくできます。他にも、次のような pros/cons があります。

pros

  • API 通信が1回で済む
    • リソース毎に API と通信しない
  • リソースの差分だけを指定して取得できる
    • 既にページで持ってる情報を改めて取得しなくて良い
  • JSONに似た構文で書きやすい

cons

  • キャッシュが URL ベースでできない
  • モニタリングが難しい
    • エンドポイント毎の監視できない

GraphQL の導入

それでは、 GraphQL を使ってみましょう。グルメニュースは、PHP フレームワークの Laravel を使っています。
GraphQL のフレームワークにはlaravel のパッケージである Lighthouse を使用します。Lighthouse はディレクティブ(@)を使って、モデルのリレーションやバリデーションを定義できます

Lighthouse のインストール


$ composer require nuwave/lighthouse

config ファイルの配置

php artisan vendor:publish --provider="Nuwave\Lighthouse\Providers\LighthouseServiceProvider" --tag=config

これで GraphQL を使い始めることはできますが、開発に便利なパッケージ laravel-graphql-playground も一緒に入れましょう(以下、playground)。playground は、 ブラウザ で GraphQL のサーバにクエリを投げて結果を確認できるパッケージです。また、右側にあるタブ DOCSSCHEMA で Lighthouse が生成したスキーマファイルを見ることができます。

composer require mll-lab/laravel-graphql-playground
c531070a-a770-2b77-9cac-c976a2b31b89.png

Lighthouse ファイルの作成

ファイルは routes/graphql 以下に配置します。次の2つモデルを作成して、 playground でデータを取得してみます。

  • shops テーブル
カラム名
id int
name string
address string
  • items テーブル
カラム名
id int
name string
genre string

表を元にスキーマはこのようにしました。

schema.graphql
type Shop {
  id: ID!
  name: String
  address: String
  items: Item @hasMany
}

type Item {
  id: ID!
  name: String
  genre: Int
  shop: Shop @belongsTo
}

type Query {
  shops(
    id: ID @eq
    name: String @where(operator: "like")
    address: String @where(operator: "like")
  ): [Shop] @paginate(model: "Shop")

  items(id: ID @eq
    name: String @where(operator: "like")
    genre: Int @eq
  ): [Item] @paginate(model: "Item")
}

DOCSSCHEMA タブの内容は次のようになります。(一部分のみ)

DOCS

4857071f-2d61-4dbf-4223-3889b54b0a50.png

SCHEMA

3d0ec0a7-48cb-f283-b9a0-69f033f2c1b4.png

フロント側では、既にどちらも idname は持っており、 addressgenre が欲しいとします。

クエリ
query {
  shops(id: 2, count: 3, page: 1) {
     data {
      address
    }
  }
  items(genre: 1, count: 3, page: 1) {
    data {
      id,
      genre
    }
  }
}
実行結果
{
  "data": {
    "shops": {
      "data": [
        {
          "address": "92394 Armando Shores Suite 623\nDeckowshire, NV 22748"
        }
      ]
    },
    "items": {
      "data": [
        {
          "id": "4",
          "genre": 1
        },
        {
          "id": "6",
          "genre": 1
        }
      ]
    }
  }
}

shopitem の異なるリソースを一回の通信で取ってくることができ、 address, genre だけを取得することができました。 :smile:

まとめ

GraphQL 導入の説明と Lighthouse を使って GraphQL に触ってみました。キャッシュやモニタリングなど難しい部分もあり、技術的に枯れていないので学習コストは高いかもですが、銀の弾丸はないんです。

まだまだ導入事例は少ない GraphQL ですが、とても便利なのでぜひ使ってみてください。

明日は @yongyu-li さんです。

19
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?