1. 前提:TCP/IPモデルにおける位置づけ
TCP/IPモデルは、ネットワーク通信を4つの層に分けて整理したモデルです。
| 層 | 名称 | 代表的なプロトコル・技術 | API設計スタイル |
|---|---|---|---|
| 第4層 | アプリケーション層 | HTTP, DNS, SMTP, FTP | GraphQL, REST |
| 第3層 | トランスポート層 | TCP, UDP | - |
| 第2層 | インターネット層 | IP | - |
| 第1層 | ネットワークインターフェース層 | Ethernet, Wi-Fi | - |
GraphQLとRESTは、ともに第4層アプリケーション層に位置します。HTTPプロトコルを利用してデータをやり取りするAPI設計スタイルであり、HTTPそのものとは別の概念です。
HTTPは「データをどのような形式で運ぶか」を定めた通信プロトコル。GraphQL・RESTは「APIをどう設計するか」という設計思想・アーキテクチャです。
2. Web APIとは
APIはApplication Programming Interfaceの略で、ソフトウェア同士が互いに機能やデータをやり取りするための取り決めです。
Web APIは、HTTPを通じてネットワーク越しにアクセスできるAPIを指します。クライアント(ブラウザ、モバイルアプリ、他のサーバー等)がHTTPリクエストを送り、サーバーが処理結果をHTTPレスポンスとして返します。
Web APIにより、フロントエンドとバックエンドの分離、マイクロサービス間の連携、外部サービスとの統合などが実現できます。
RESTとGraphQLは、このWeb APIをどのように設計するかというアプローチの違いです。
3. REST
歴史的背景
RESTはRepresentational State Transferの略で、2000年にRoy Fieldingが博士論文で提唱したアーキテクチャスタイルです。Webの設計原則を形式化したもので、HTTPの仕様策定にも関わったFieldingがWebのスケーラビリティを支える設計思想として整理しました。
設計原則
RESTは以下の原則に基づきます。
リソース指向: すべてのデータを「リソース」として捉え、URIで一意に識別します。/users/123はID123のユーザーというリソースを指します。
統一インターフェース: HTTPメソッドでリソースへの操作を表現します。GET(取得)、POST(作成)、PUT(更新)、DELETE(削除)という標準化された操作を使います。
ステートレス: 各リクエストは独立しており、サーバーはクライアントの状態を保持しません。必要な情報はすべてリクエストに含めます。
クライアント・サーバー分離: クライアントとサーバーは独立して進化できます。
REST APIのリクエスト/レスポンス例
GET /users/123 HTTP/1.1
Host: api.example.com
{
"id": 123,
"name": "山田太郎",
"email": "yamada@example.com",
"department": "開発部",
"createdAt": "2024-01-15T09:00:00Z"
}
メリット
- HTTPの標準仕様に沿っており、理解しやすい
- キャッシュ機構を活用しやすい
- ツールやライブラリが豊富
課題
Over-fetching: クライアントが必要としないフィールドも含めて全データが返されます。上記例でnameだけ欲しい場合も全フィールドが返ります。
Under-fetching: 関連データを取得するために複数回のリクエストが必要になります。ユーザー情報とその投稿一覧を取得するには/users/123と/users/123/postsの2回リクエストが必要です。
4. GraphQL
歴史的背景
GraphQLは2012年にFacebook社内で開発され、2015年にオープンソースとして公開されました。モバイルアプリの複雑なデータ取得要件と、REST APIのOver-fetching/Under-fetching問題を解決するために生まれました。
設計思想
クライアント主導: クライアントが必要なデータ構造をクエリで宣言します。サーバーはその形式でのみ応答します。
単一エンドポイント: 通常/graphqlという単一のエンドポイントに対してすべてのリクエストを送ります。RESTのように複数のエンドポイントを使い分ける必要がありません。
強い型システム: スキーマによってAPIの構造が厳密に定義されます。クライアントは事前にどのようなデータが取得可能か把握できます。
基本構文
GraphQLには3つの操作タイプがあります。
Query: データの取得(RESTのGETに相当)
query {
user(id: "123") {
name
email
}
}
Mutation: データの作成・更新・削除(RESTのPOST/PUT/DELETEに相当)
mutation {
createUser(name: "山田太郎", email: "yamada@example.com") {
id
name
}
}
Subscription: リアルタイムデータの購読(WebSocketを利用)
subscription {
messageAdded(roomId: "456") {
content
sender {
name
}
}
}
スキーマと型システム
GraphQL APIはスキーマで構造を定義します。
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
type Query {
user(id: ID!): User
users: [User!]!
}
!は非null、[Type]は配列を表します。この定義により、クライアントは何が取得可能か、どのような型で返されるかを正確に把握できます。
GraphQL APIのメリット
- 必要なデータのみを過不足なく取得できる
- 1回のリクエストで関連データも含めて取得可能
- スキーマによる型安全性とドキュメント自動生成
- Subscriptionによるリアルタイム通信のサポート
課題
- 学習コストがRESTより高い
- キャッシュ戦略が複雑(単一エンドポイントのためHTTPキャッシュが効きにくい)
- クエリの複雑さによるサーバー負荷の制御が必要
- ファイルアップロードの標準仕様がない
5. REST vs GraphQL比較
設計思想の違い
| 観点 | REST | GraphQL |
|---|---|---|
| データ構造の決定権 | サーバー | クライアント |
| エンドポイント | リソースごとに複数 | 単一(/graphql) |
| データ取得 | 固定されたレスポンス形式 | クエリで必要なフィールドを指定 |
| 型システム | 任意(OpenAPI等で定義可能) | 必須(スキーマで厳密に定義) |
| リアルタイム通信 | 別途WebSocket等を実装 | Subscriptionで標準サポート |
ユースケース別の適性
RESTが適するケース
- シンプルなCRUD操作が中心
- キャッシュを積極的に活用したい
- チームがRESTに習熟している
- 公開APIとして広く提供する(学習コストが低い)
GraphQLが適するケース
- 複雑なデータ関係を1回のリクエストで取得したい
- モバイルアプリなど帯域幅の節約が重要
- フロントエンドの要件変更が頻繁
- リアルタイム機能が必要
- 複数のクライアント(Web、iOS、Android)が異なるデータを必要とする
選定基準
技術選定の際は以下を検討します。
チームのスキルセット: GraphQLは学習コストが高いため、チームの習熟度を考慮します。
アプリケーションの特性: データ関係が複雑でリアルタイム性が求められるならGraphQL、シンプルなAPIならRESTが妥当です。
クライアントの多様性: 複数プラットフォームで異なるデータ要件があるならGraphQLの柔軟性が活きます。
インフラ・運用面: GraphQLはキャッシュやクエリ制御の設計が必要です。既存インフラとの相性も考慮します。
どちらが優れているという話ではなく、要件に応じた適切な選択が重要です。両者を組み合わせて使うケースもあります。