<CodeLearn/>
GraphQL レッスン1

GraphQLの基本

RESTとの違い、メリットとデメリットを理解しよう

GraphQLとは?

GraphQLは、APIのためのクエリ言語であり、 サーバーサイドのランタイムです。2012年にFacebookが社内で開発を始め、 2015年にオープンソースとして公開されました。

従来のREST APIでは、サーバーがレスポンスの構造を決めていましたが、 GraphQLではクライアントが必要なデータの形を指定します。 これにより、過不足のない効率的なデータ取得が可能になります。

# GraphQLの基本的なクエリ
query {
  user(id: "1") {
    name
    email
  }
}

# レスポンス
{
  "data": {
    "user": {
      "name": "田中太郎",
      "email": "taro@example.com"
    }
  }
}

クエリの形がそのままレスポンスの形になる — これがGraphQLの最大の特徴です。

REST vs GraphQL

REST APIとGraphQLの違いを具体的に見てみましょう。 ユーザーのプロフィールと投稿一覧を取得するケースを比較します。

// === REST API の場合 ===
// リクエスト1: ユーザー情報を取得
GET /api/users/1
// レスポンス: { id, name, email, address, phone, ... }
// → 不要なフィールド(address, phone)も含まれる

// リクエスト2: ユーザーの投稿を取得
GET /api/users/1/posts
// レスポンス: [{ id, title, body, createdAt, ... }, ...]

// リクエスト3: 各投稿のコメント数を取得
GET /api/posts/1/comments/count
GET /api/posts/2/comments/count
// → N+1リクエスト問題

// === GraphQL の場合 ===
// 1回のリクエストですべて取得
query {
  user(id: "1") {
    name
    email
    posts {
      title
      commentCount
    }
  }
}

REST API

  • • 複数のエンドポイント
  • • サーバーがレスポンス構造を決定
  • • HTTPメソッドで操作を区別
  • • キャッシュが容易(HTTPキャッシュ)

GraphQL

  • • 単一エンドポイント
  • • クライアントがデータ構造を指定
  • • Query / Mutation で操作を区別
  • • キャッシュには専用ライブラリが必要

Over-fetching と Under-fetching

REST APIでよく発生する2つの問題を、GraphQLがどう解決するか見てみましょう。

// Over-fetching(過剰取得)
// ユーザー名だけ欲しいのに、すべてのフィールドが返ってくる
GET /api/users/1
// → { id, name, email, address, phone, avatar, bio, ... }
// 実際に使うのは name だけ...

// Under-fetching(過少取得)
// 1つの画面に必要なデータが1回のリクエストで取れない
GET /api/users/1        // ユーザー情報
GET /api/users/1/posts  // 投稿一覧
GET /api/users/1/friends // 友達一覧
// → 3回もリクエストが必要...

// GraphQL なら1回で必要なデータだけ取得
query {
  user(id: "1") {
    name          # nameだけ指定
    posts {       # 投稿も一緒に
      title
    }
    friends {     # 友達も一緒に
      name
      avatar
    }
  }
}

GraphQLはクライアントが必要なフィールドを明示的に指定するため、 過不足のないデータ取得が実現できます。

GraphQLの型システム

GraphQLは強力な型システムを持っています。 スキーマとして型を定義することで、APIの仕様が明確になり、 クライアントとサーバー間の契約として機能します。

# GraphQL スキーマの例
type User {
  id: ID!           # Non-nullable(必須)
  name: String!     # 文字列型(必須)
  email: String!
  age: Int          # 整数型(nullable)
  isActive: Boolean!
  posts: [Post!]!   # Post型の配列(必須)
}

type Post {
  id: ID!
  title: String!
  body: String!
  author: User!     # リレーション
  createdAt: String!
}

# ルート型:クエリのエントリポイント
type Query {
  user(id: ID!): User
  users: [User!]!
  post(id: ID!): Post
}

# ミューテーション:データの変更操作
type Mutation {
  createUser(name: String!, email: String!): User!
  updateUser(id: ID!, name: String): User
  deleteUser(id: ID!): Boolean!
}

! は Non-nullable(nullを許可しない)を意味します。次のレッスンで型定義を詳しく学びます。

GraphQL Playground

GraphQLにはPlayground(またはGraphiQL)という 対話的なIDEが付属しています。ブラウザ上でクエリを書いて即座に実行でき、 スキーマのドキュメントも自動生成されます。

# Playground でクエリを試す

# 1. 変数を使ったクエリ
query GetUser($id: ID!) {
  user(id: $id) {
    name
    email
    posts {
      title
    }
  }
}

# Variables パネルに入力
{
  "id": "1"
}

# 2. イントロスペクション(スキーマ情報の取得)
query {
  __schema {
    types {
      name
      description
    }
  }
}

# 3. 特定の型の情報を取得
query {
  __type(name: "User") {
    name
    fields {
      name
      type {
        name
        kind
      }
    }
  }
}

Apollo Serverを起動すると、デフォルトで Apollo Sandbox が利用可能です。 スキーマの探索やクエリのテストに非常に便利です。

まとめ

  • GraphQLはクライアントが必要なデータの形を指定できるクエリ言語
  • REST APIのOver-fetchingUnder-fetchingを解決する
  • 強力な型システムにより、APIの仕様が明確でドキュメント自動生成が可能
  • 単一エンドポイントで効率的なデータ取得を実現
  • Playgroundで対話的にクエリをテストできる