GraphQL — その概要、クエリ言語、モバイルプロジェクトでの応用

著者: IT Sectr 公開日: 2026-03-06 読了時間: 9 分

GraphQL — APIのためのクエリ言語であり、それらのクエリを実行するためのランタイムです。2012年にFacebookによって開発され、2015年にオープンソース化されました。サーバーが応答構造を決定するRESTとは異なり、GraphQLではクライアントが必要なデータを正確に指定できるため、overfetchingとunderfetchingの問題を完全に排除します。State of JavaScript Survey(2025)によると、調査対象の開発者の35%がGraphQLを使用しており、大企業ではGitHub、Shopify、Airbnb、The New York Timesが採用しています。GraphQLは3種類の操作をサポートしています:query(読み取り)、mutation(書き込み)、subscription(WebSocket経由のリアルタイム更新)。

重要ポイント

  • GraphQL — クライアントが応答構造を指定するクエリ言語
  • overfetching(余分なデータ)とunderfetching(データ不足)の問題を解決
  • 異なる種類の操作に対してquery、mutation、subscriptionをサポート
  • RESTのように複数のURLではなく、単一のendpoint(通常は/graphql)を使用
  • 厳密なスキーマを持つ型システムに基づく:すべての可能なデータが事前に記述される

GraphQLとは?

GraphQL — APIのための仕様およびランタイムであり、クライアントが受信するデータを完全に制御できるようにします。News Feedモバイルアプリケーションの問題を解決するためにFacebookのエンジニアによって開発され、2015年にオープンスタンダードとして公開されました。2018年以降、GraphQLはLinux FoundationとApollo、AWS、GitHub、SAPなどの企業の支援を受けてGraphQL Foundationによって管理されています。

各エンドポイントが固定のデータ構造を返すRESTとは異なり、GraphQLはクエリ文字列を受け付ける単一のエンドポイントを使用します。クライアントはクエリ内で必要なフィールドを記述し、サーバーは正確にそれらを返します。たとえば、クエリ { user(id: "1") { name email } } はユーザーの名前とメールのみを返し、RESTで取得する必要があったaddress、phone、createdAtなどの余分なフィールドは含まれません。

GraphQLは特定のデータベースや言語に縛られません。仕様はクエリと応答の形式のみを定義します。Node.js(graphql-js、Apollo Server)、Kotlin(graphql-kotlin、Netflix DGS Framework)、Python(Graphene、Strawberry)、Ruby(graphql-ruby)などの言語でサーバー実装が存在します。クライアントライブラリはiOS、Android、Web向けのApollo Clientを含むすべての主要プラットフォームで利用可能です。

GraphQLの仕組み

GraphQLアーキテクチャは、スキーマ(Schema)、リゾルバ(Resolvers)、GraphQLエンジン(GraphQL Engine)の3つの主要コンポーネントで構成されます。スキーマは、どのデータ型が利用可能か、どのクエリを実行でき、どの引数を受け付けるかを定義します。リゾルバは、各スキーマフィールドのデータを返すサーバー側の関数です。エンジンは着信クエリを受け取り、スキーマに対して検証し、適切なリゾルバを呼び出して応答を組み立てます。

クエリ処理の流れは次のとおりです:

  • クライアントがJSONボディ{ "query": "..." }を伴うPOSTリクエストを/graphqlに送信
  • サーバーがクエリを解析し、AST(抽象構文木)を構築してスキーマに対して検証
  • エンジンがASTを走査し、各フィールドのリゾルバを呼び出してデータを収集
  • 応答がJSON形式で返され、クエリ構造に厳密に一致

GraphQLアーキテクチャの主な利点はフィールドレベルの解決です。RESTでは、開発者はリソースのすべてのフィールド(余分なものも含む可能性あり)を取得するか、?fields=name,emailのような拡張機能に頼る必要があります。GraphQLでは、このようなフィルタリングが言語に組み込まれています:各クエリは必要なフィールドを明示的に指定し、サーバーは正確にそれらを返します。これは、転送されるデータ量が読み込み速度とデータ使用量に直接影響するモバイルアプリケーションにとって特に重要です。

Query、Mutation、Subscription

GraphQLは3種類の操作を定義しており、それぞれが特定の対話シナリオに対応しています。Query — データ読み取り用で、RESTのGETに相当します。Mutation — データ変更用(作成、更新、削除)で、POST/PUT/DELETEに相当します。Subscription — WebSocket経由のリアルタイム更新用で、従来のRESTには直接の類似点はありません(WebSocketやServer-Sent Eventsなどの追加ソリューションが必要です)。

基本的なクエリ構文は直感的です:

js
// 引数を持つ単純なクエリ
query {
    user(id: "42") {
        name
        email
        avatarUrl
    }
}

// 変更されたデータを返すMutation
mutation {
    updateProfile(name: "イヴァン") {
        id
        name
        updatedAt
    }
}

// Subscription — リアルタイム更新をリッスン
subscription {
    newMessage(chatId: "chat_1") {
        id
        text
        sender { name }
    }
}

Queryは並列に実行されます — 同じレベルのすべてのフィールドが同時に読み込まれます。これにより、複数のラウンドトリップなしで、関連データ(ユーザーとその投稿)を1回のリクエストで読み込むことができます。Mutationは順次実行されます — 1つのリクエスト内のミューテーションは宣言順に1つずつ実行されます。SubscriptionはWebSocketを介した永続的な接続を確立し、サーバーはイベント発生時にデータを送信します。

操作は、データをクエリから分離するための変数、条件付きフィールドを含めるためのディレクティブ(@include、@skip)、フィールドセットを再利用するためのフラグメントを受け入れることができます。これらの機能により、GraphQLクエリは柔軟で再利用可能になり、複数の画面とコンポーネントを持つ大規模プロジェクトで特に重要です。

GraphQLのスキーマと型システム

GraphQLの中核には、すべての可能なデータとAPI操作を記述する型システムがあります。スキーマは、サーバーが返すことができる型と受け付けるクエリの記述です。スキーマはSchema Definition Language(SDL)で記述され、クライアントとサーバー間の契約として機能します。クライアントはイントロスペクション(特別なクエリ__schemaがAPIの完全な説明を返す)を通じてスキーマを取得できます。

ブログのスキーマ例:

js
// SDL — Schema Definition Language
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
    posts(page: Int): [Post!]!
}

感嘆符(!)は非nullフィールドを示します — 応答に存在することが保証されます。角括弧[ ]はリストを示します。GraphQLはスカラー型(Int、Float、String、Boolean、ID)、オブジェクト型、enum、union、interface、入力型(ミューテーション引数用)をサポートします。厳密な型付けはAPIを自己文書化し、クライアントツールがコード(TypeScript型、Kotlinデータクラス、Swift構造体)を生成できるようにします。

イントロスペクションはRESTにはないGraphQLのユニークな機能です。クライアントはスキーマにクエリを送信し、すべての型、フィールド、引数、ディレクティブの完全な説明を取得できます。これはGraphiQLやApollo Studioなどのツールの基盤であり、開発者向けにドキュメントとオートコンプリートを自動生成します。イントロスペクションを使用して、スキーマが期待される構造に準拠しているかを確認する自動テストを作成することもできます。

GraphQLとRESTの比較

GraphQLとRESTの選択は、API設計における主要なアーキテクチャ上の決定の1つです。両方のアプローチには長所と短所があり、選択はプロジェクトの具体的な要件に依存します。RESTはシンプルさと汎用性で優れ、GraphQLは柔軟性とクエリ効率で優れています。比較表を見てみましょう。

基準RESTGraphQL
応答構造固定、サーバー定義柔軟、クライアント定義
Overfetching頻繁 — サーバーがすべてのフィールドを返すなし — クライアントが必要なフィールドのみ要求
リクエスト数複数のラウンドトリップすべてのデータに対して1回のリクエスト
キャッシュネイティブHTTPキャッシュ手動設定が必要
型付け組み込みなし(形式に依存)SDLスキーマによる厳密な型付け
ツールcurl、Postman、SwaggerGraphiQL、Apollo Studio、イントロスペクション
ファイルアップロードmultipartによるネイティブ対応追加プロトコルが必要
パフォーマンス予測可能、最適化が容易ネストされたクエリの複雑さに依存

GraphQLの主な欠点はキャッシュの複雑さです。RESTでは、HTTPキャッシュはURLレベルで機能します:/api/users/42へのリクエストは常に同じ構造を返し、応答はURLでキャッシュできます。GraphQLでは、すべてのリクエストが単一のエンドポイントに送られ、応答構造はリクエストボディに依存します。この問題を解決するために、Apollo Clientはクライアント側で正規化されたキャッシュを使用し、応答をidごとに個別のエンティティに分割し、新しいデータを受信すると自動的に更新します。

もう1つの重要な側面はN+1問題です。ネストされたデータ(例:ユーザーの投稿と各投稿へのコメント)を要求する場合、GraphQLはリストの各項目に対して個別のSQLクエリを実行する可能性があります。これはDataLoaderを使用して解決されます — 個々のリクエストを1つのバッチにグループ化し、単一のHTTPリクエスト内で結果をキャッシュするユーティリティです。RESTでは、開発者がサーバー側で応答構造を制御するため、この問題はそれほど顕著ではありません。

GraphQLクエリの例

Apollo Clientを使用したKotlinモバイルアプリケーションでのGraphQLの実践的な例を見てみましょう。例は一般的なシナリオを示しています:プロフィール画面のデータ読み込み(query)、新しい投稿の作成(mutation)、新しいコメントの購読(subscription)。各例にはGraphQLクエリとクライアント側コードの両方が含まれています。

Query:投稿を含むプロフィールの読み込み

1つのGraphQLクエリで、ユーザー、その最新の投稿、フォロワーの総数を読み込みます。RESTでは、少なくとも2〜3回のリクエスト(/users/42、/users/42/posts、/users/42/stats)が必要です。GraphQLはそれらを1回のラウンドトリップに統合し、低速接続での画面読み込み時間を短縮します。

kotlin
// GraphQLクエリ(.graphqlファイル内)
query ProfileScreen($userId: ID!) {
    user(id: $userId) {
        name
        bio
        avatarUrl
        posts(limit: 10) {
            id
            title
            createdAt
        }
        followersCount
        followingCount
    }
}

// クライアント側の呼び出し(Apollo Client + Kotlin)
val response = apolloClient
    .query(ProfileScreenQuery(userId = "42"))
    .execute()
binding.nameText.text = response.data?.user?.name

Mutation:新しい投稿の作成

ミューテーションはリソースを作成するだけでなく、UI更新のための現在のデータも返します。__typenameフィールドはApollo Clientによってキャッシュの正規化に使用されます — クライアントはミューテーションの成功応答時にキャッシュ内のPostレコードを自動的に更新します。

kotlin
// GraphQLミューテーション
mutation CreatePost($input: CreatePostInput!) {
    createPost(input: $input) {
        id
        title
        createdAt
        author {
            id
            name
        }
    }
}

// input型を使用したミューテーション呼び出し
val input = CreatePostInput(
    title = "GraphQLに関する新しい投稿",
    content = "GraphQLはAPIの操作を簡素化します..."
)
val result = apolloClient
    .mutation(CreatePostMutation(input))
    .execute()

モバイル開発におけるRESTに対するGraphQLの重要な利点は自動コード生成です。Kotlin用のApollo Client(Apollo GraphQL)は、ビルド時に.graphqlファイルから型安全なクラスを生成します。サーバーがスキーマを変更した場合、クエリが更新されるまでプロジェクトはビルドされません。これにより、応答構造の変更が開発中に気付かれない可能性があるRESTに特有のランタイムエラーを防止します。

エコシステム:Apollo、Relay、ツール

GraphQLのエコシステムには、開発と運用を簡素化するいくつかの主要なライブラリとツールが含まれています。Apollo Clientは最も人気のあるクライアントライブラリで、React、iOS、Android、Kotlin Multiplatformをサポートしています。FacebookのRelayは、データ管理とキャッシュへの独自のアプローチを持つReactアプリケーション向けの代替手段です。ApolloとRelayの選択は、プラットフォームとパフォーマンス要件によって異なります。

サーバー側では、Apollo Server(Node.js)、Netflix DGS Framework(Kotlin/Java)、graphql-rubyがリーダーです。スキーマ開発とクエリテストには、ブラウザに組み込まれたインタラクティブIDEであるGraphiQLが使用されます。Apollo Studioは、本番環境向けのパフォーマンスメトリクス、クエリトレーシング、スキーマ管理を提供します。別途注目すべきはGraphQL Code Generator — SDLスキーマからTypeScript、Kotlin、Swift、Dartの型を生成するツールです。

モバイル開発にとって特に重要なのはApollo Kotlin(Apollo GraphQL)です — コルーチン、Flow、Multiplatformをサポートし、完全にKotlinで記述されたライブラリです。Kotlin MultiplatformプロジェクトでAndroidとiOS向けに統一されたGraphQLクエリを使用できます。Apollo Kotlinはキャッシュを正規化し、フィールドレベルのエラー(部分エラー)をサポートし、.graphqlファイルからデータモデルを自動生成します。これにより、開発速度と型安全性が重要な大規模モバイルプロジェクトにおいて、GraphQLが好ましい選択肢となります。

よくある質問

GraphQLはRESTを置き換えるのですか?

GraphQLはRESTを置き換えるものではなく、代替アプローチを提供します。RESTは単純なCRUD API、HTTPキャッシュ、予測可能な負荷のパブリックAPIに適しています。GraphQLは多くの関連データを持つ複雑なインターフェースに最適です。

RESTからGraphQLへの移行は難しいですか?

移行は段階的に可能です:GraphQLは既存のRESTサービスの前でゲートウェイとして機能できます。多くの企業は古いAPIを停止せずにRESTと並行してGraphQLを追加しています。完全な置き換えにはリゾルバの書き換えが必要です。

GraphQLのN+1問題とは何ですか?

N+1は、リストの各項目に対して個別のデータベースクエリが実行されるときに発生します。DataLoader — 個々のリクエストを1つにバッチ化し、単一のHTTPリクエスト内で結果をキャッシュするライブラリを使用して解決されます。

GraphQLはファイルアップロードをどのように扱いますか?

GraphQL仕様はファイルアップロードを直接定義していません。実際には、base64エンコーディング(大容量ファイルには非効率的)、graphql-multipart-request-specプロトコルによるmultipartリクエスト、またはファイル用の別個のRESTエンドポイントが使用されます。

GraphQLは安全ですか?

GraphQLのセキュリティには追加の対策が必要です:ネストの深さの制限、クエリの複雑さの制限、操作レベルのレート制限。公開スキーマのイントロスペクションはデータ構造を明らかにする可能性があります — 本番環境では無効にすることをお勧めします。

まとめ

  • GraphQL — クライアントが応答構造を制御し、overfetchingとunderfetchingを排除するクエリ言語
  • 3種類の操作:query(読み取り)、mutation(書き込み)、subscription(リアルタイム)
  • 単一のエンドポイントと厳密な型システム(SDLスキーマ)を使用
  • RESTとは異なり、複数のラウンドトリップの問題を解決 — すべてのデータを1回のリクエストで取得
  • N+1問題を防ぐためにDataLoaderと手動キャッシュ設定が必要
  • 主要クライアント:Apollo Client(Android、iOS、Web)とRelay(React)
  • 多くの関連エンティティとモバイルアプリケーションを持つ複雑なインターフェースに最適

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください