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-fetchingとUnder-fetchingを解決する - 強力な型システムにより、APIの仕様が明確でドキュメント自動生成が可能
- 単一エンドポイントで効率的なデータ取得を実現
- Playgroundで対話的にクエリをテストできる