API設計

GraphQL入門!RESTとの違いと基本的な使い方

API設計

GraphQL入門!
RESTとの違いと基本的な使い方

GraphQLは必要なデータを必要な分だけ取得できるAPIクエリ言語です。RESTとの比較を交えて解説します。

こんな人向けの記事です

  • GraphQLの基本概念を理解したい人
  • REST APIの課題を感じている人
  • 効率的なAPI設計を学びたい人

Step 1GraphQLとは

GraphQLはFacebookが開発したAPIのクエリ言語です。クライアントが必要なデータの構造を指定してリクエストします。

GraphQLの特徴
# GraphQLの3つの特徴

# 1. 必要なデータだけ取得(Over-fetching解消)
# REST: GET /users/1 → 全フィールドが返る
# GraphQL: { user(id: 1) { name email } } → name と email だけ返る

# 2. 1回のリクエストで複数リソース取得(Under-fetching解消)
# REST: GET /users/1 → GET /users/1/posts → GET /users/1/followers
# GraphQL: 1回のクエリで全て取得可能

# 3. 型システムによる自己文書化
# スキーマがそのままAPIのドキュメントになる

Step 2RESTとの比較

REST vs GraphQL
# === REST API ===
# 複数のエンドポイント
# GET /api/users/1
# GET /api/users/1/posts
# GET /api/users/1/followers

# レスポンス(不要なデータも含まれる)
# {
#   "id": 1, "name": "田中", "email": "...",
#   "address": "...", "phone": "...",  ← 不要かも
#   "created_at": "..."
# }

# === GraphQL ===
# 単一エンドポイント: POST /graphql
# クエリで必要なデータだけ指定
# {
#   user(id: 1) {
#     name
#     posts { title }
#     followers { name }
#   }
# }

# レスポンス(リクエストした構造そのまま)
# {
#   "data": {
#     "user": {
#       "name": "田中",
#       "posts": [{"title": "記事1"}, {"title": "記事2"}],
#       "followers": [{"name": "佐藤"}, {"name": "鈴木"}]
#     }
#   }
# }
どちらを選ぶ?
シンプルなCRUD APIならREST、複雑なデータ関係や多様なクライアント(Web/モバイル)がある場合はGraphQLが有利です。

Step 3クエリの基本

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

# 複数リソースの同時取得
query {
  user(id: 1) {
    name
    posts(limit: 5) {
      title
      createdAt
    }
  }
  recentArticles(limit: 3) {
    title
    author { name }
  }
}

# 変数を使ったクエリ
query GetUser($userId: ID!, $postLimit: Int = 10) {
  user(id: $userId) {
    name
    email
    posts(limit: $postLimit) {
      title
      content
      comments {
        body
        author { name }
      }
    }
  }
}
# 変数: { "userId": "1", "postLimit": 5 }

# フラグメント(再利用可能なフィールドセット)
fragment UserBasic on User {
  id
  name
  email
}

query {
  user(id: 1) { ...UserBasic }
  admin: user(id: 99) { ...UserBasic role }
}

Step 4ミューテーション(データ変更)

GraphQLミューテーション
# データの作成
mutation {
  createUser(input: {
    name: "田中太郎"
    email: "tanaka@example.com"
  }) {
    id
    name
    email
  }
}

# データの更新
mutation {
  updateUser(id: 1, input: {
    name: "田中一郎"
  }) {
    id
    name
  }
}

# データの削除
mutation {
  deleteUser(id: 1) {
    success
    message
  }
}

# 変数を使ったミューテーション
mutation CreatePost($input: PostInput!) {
  createPost(input: $input) {
    id
    title
    author { name }
  }
}
# 変数: { "input": { "title": "新記事", "content": "本文" } }

Step 5スキーマ定義

GraphQLスキーマ(SDL)
# 型定義
type User {
  id: ID!           # !は必須(Non-null)
  name: String!
  email: String!
  age: Int
  posts: [Post!]!   # Postの配列(必須)
  createdAt: String!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
  comments: [Comment!]!
}

type Comment {
  id: ID!
  body: String!
  author: User!
}

# 入力型(ミューテーション用)
input CreateUserInput {
  name: String!
  email: String!
  age: Int
}

# クエリとミューテーションの定義
type Query {
  user(id: ID!): User
  users(limit: Int = 10, offset: Int = 0): [User!]!
  post(id: ID!): Post
}

type Mutation {
  createUser(input: CreateUserInput!): User!
  updateUser(id: ID!, input: CreateUserInput!): User!
  deleteUser(id: ID!): Boolean!
}

# Enum型
enum Role {
  ADMIN
  USER
  GUEST
}

Step 6実践:PythonでGraphQLサーバー

Python(Strawberry + FastAPI)
# pip install strawberry-graphql fastapi uvicorn
import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter

# 型定義
@strawberry.type
class User:
    id: int
    name: str
    email: str

# サンプルデータ
users_db = [
    User(id=1, name="田中太郎", email="tanaka@example.com"),
    User(id=2, name="佐藤花子", email="sato@example.com"),
]

# クエリ
@strawberry.type
class Query:
    @strawberry.field
    def users(self) -> list[User]:
        return users_db

    @strawberry.field
    def user(self, id: int) -> User | None:
        return next((u for u in users_db if u.id == id), None)

# ミューテーション
@strawberry.type
class Mutation:
    @strawberry.mutation
    def create_user(self, name: str, email: str) -> User:
        new_id = max(u.id for u in users_db) + 1
        user = User(id=new_id, name=name, email=email)
        users_db.append(user)
        return user

schema = strawberry.Schema(query=Query, mutation=Mutation)
app = FastAPI()
app.include_router(GraphQLRouter(schema), prefix="/graphql")

# uvicorn main:app → http://localhost:8000/graphql
GraphiQL
Strawberryには開発用のGraphiQL(グラフィクル)UIが組み込まれており、ブラウザでクエリを試せます。

まとめ

  • GraphQLは必要なデータだけを1回のリクエストで取得
  • Over-fetching/Under-fetchingを解消
  • Query(読み取り)とMutation(変更)の2種類の操作
  • スキーマ(型定義)がAPIドキュメントになる
  • PythonではStrawberry + FastAPIで簡単に構築