REST と GraphQL の概要
Web APIの設計手法として、RESTとGraphQLは最も広く使われている2つのアプローチです。どちらにも長所と短所があり、プロジェクトの要件に応じた選択が重要です。
REST とは
REST(Representational State Transfer)は、HTTPメソッドとURLでリソースを操作するアーキテクチャスタイルです。
GET /api/users # ユーザー一覧
GET /api/users/123 # ユーザー詳細
POST /api/users # ユーザー作成
PUT /api/users/123 # ユーザー更新
DELETE /api/users/123 # ユーザー削除
GraphQL とは
GraphQL は、クライアントが必要なデータの形を指定してクエリを送るクエリ言語です。
query {
user(id: 123) {
name
email
posts {
title
createdAt
}
}
}
比較表
| 項目 | REST | GraphQL |
|---|---|---|
| エンドポイント | リソースごとに複数 | 単一エンドポイント |
| データ取得 | サーバーが決めた形 | クライアントが指定 |
| オーバーフェッチ | 起きやすい | 起きない |
| アンダーフェッチ | 起きやすい | 起きない |
| キャッシュ | HTTPキャッシュが使える | 独自のキャッシュが必要 |
| ファイルアップロード | 標準的 | 追加ライブラリが必要 |
| 学習コスト | 低い | やや高い |
| ツール・エコシステム | 非常に豊富 | 急速に成長中 |
| リアルタイム | WebSocket等を別途用意 | Subscriptionで対応 |
| 型定義 | OpenAPI/Swagger | スキーマで自動 |
REST のメリット・デメリット
メリット
1. HTTPの仕組みをフル活用できる
# キャッシュヘッダーがそのまま使える
GET /api/users/123
Cache-Control: max-age=3600
ETag: "abc123"
# ステータスコードが明確
200 OK
201 Created
404 Not Found
2. シンプルで理解しやすい
URLを見ればどのリソースにアクセスしているかが明確です。
3. ツールが豊富
curl、Postman、OpenAPI/Swagger、各言語のHTTPクライアントなど、成熟したエコシステムがあります。
デメリット
1. オーバーフェッチ(余分なデータを取得)
// ユーザー名だけ欲しいのに全フィールドが返ってくる
GET /api/users/123
{
"id": 123,
"name": "田中太郎",
"email": "[email protected]",
"address": "...",
"phone": "...",
"createdAt": "...",
"updatedAt": "..."
}
2. アンダーフェッチ(複数リクエストが必要)
# ユーザーとその投稿を取得するのに2回リクエストが必要
GET /api/users/123
GET /api/users/123/posts
3. バージョニングの悩み
/api/v1/users
/api/v2/users # フィールド追加時に新バージョンが必要
GraphQL のメリット・デメリット
メリット
1. 必要なデータだけ取得できる
# 名前だけ欲しい場合
query {
user(id: 123) {
name
}
}
# 投稿も含めて欲しい場合(1リクエストで完結)
query {
user(id: 123) {
name
posts {
title
}
}
}
2. 型システムが強力
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
スキーマから自動的にドキュメントとTypeScriptの型が生成されます。
3. バージョニングが不要
フィールドの追加は後方互換性を保ちます。不要になったフィールドは @deprecated を付けるだけです。
type User {
id: ID!
name: String!
fullName: String! # 新フィールド
email: String! @deprecated(reason: "Use contactEmail instead")
contactEmail: String!
}
デメリット
1. N+1問題
query {
users { # 1回のクエリ
posts { # ユーザーごとに1回ずつDB問い合わせ → N+1
title
}
}
}
解決策: DataLoaderパターンを使う。
2. HTTPキャッシュが使えない
すべてのリクエストが POST /graphql なので、HTTPレベルのキャッシュが効きません。Apollo Client等のクライアントキャッシュで対応します。
3. ファイルアップロードが面倒
GraphQLの仕様にはファイルアップロードが含まれていません。graphql-upload 等の追加ライブラリが必要です。
選定基準
REST を選ぶべきケース
- シンプルなCRUD API: リソースが明確で関連が少ない
- パブリックAPI: サードパーティ開発者が使いやすい
- キャッシュが重要: CDNでのHTTPキャッシュを活用したい
- ファイル操作が多い: アップロード・ダウンロードが頻繁
- チームがRESTに慣れている: 学習コストを抑えたい
GraphQL を選ぶべきケース
- 複雑なデータ関連: ネストした関連データが多い
- 複数クライアント: Web・モバイル・デスクトップで異なるデータが必要
- 頻繁なUI変更: フロントエンドの変更にバックエンドが追従しなくて良い
- リアルタイム機能: Subscriptionでチャットや通知を実装
- マイクロサービス: 複数サービスのデータを1つのエンドポイントで統合
実装例
REST(Express.js)
const express = require('express');
const app = express();
// ユーザー一覧
app.get('/api/users', async (req, res) => {
const users = await db.users.findAll();
res.json(users);
});
// ユーザー詳細
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
if (!user) return res.status(404).json({ error: 'Not found' });
res.json(user);
});
// ユーザー作成
app.post('/api/users', async (req, res) => {
const user = await db.users.create(req.body);
res.status(201).json(user);
});
GraphQL(Apollo Server)
const typeDefs = `
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
author: User!
}
type Query {
users: [User!]!
user(id: ID!): User
}
type Mutation {
createUser(name: String!, email: String!): User!
}
`;
const resolvers = {
Query: {
users: () => db.users.findAll(),
user: (_, { id }) => db.users.findById(id),
},
User: {
posts: (user) => db.posts.findByUserId(user.id),
},
Mutation: {
createUser: (_, { name, email }) =>
db.users.create({ name, email }),
},
};
ハイブリッドアプローチ
REST と GraphQL は排他的ではありません。組み合わせて使うことも有効です。
/api/upload → REST(ファイルアップロード)
/api/webhooks → REST(Webhook受信)
/graphql → GraphQL(データ取得・更新)
まとめ
| 判断軸 | REST | GraphQL |
|---|---|---|
| シンプルさ重視 | ○ | |
| 柔軟なデータ取得 | ○ | |
| HTTPキャッシュ | ○ | |
| 型安全 | ○ | |
| 学習コスト | 低い | やや高い |
最終的には「チームのスキル」「プロジェクトの複雑さ」「クライアントの多様性」で判断しましょう。どちらを選んでも、一貫した設計と適切なドキュメントが最も重要です。
APIのレスポンスを整形して確認するには、AssistyのJSONフォーマッターをご活用ください。ブラウザ上でJSONを見やすく整形・バリデーションできます。