0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

REST APIからGraphQLへ:Webサービスのデータ取得を効率化する設計入門

0
Posted at

はじめに

Webサービスの規模が大きくなると、フロントエンドとバックエンドの間でやり取りするデータ量も増えていきます。

初期段階ではREST APIでも十分対応できますが、画面数や機能が増えると、

  • 必要なデータを取得するために複数APIを呼び出す
  • 不要なデータまで返ってくる
  • API仕様変更の影響範囲が広がる
  • フロントエンドとバックエンドの調整が増える

といった課題が発生することがあります。

こうした問題を解決する方法のひとつが GraphQL です。

本記事では、REST APIとGraphQLの違いを整理しながら、WebサービスでGraphQLを利用する基本的な考え方を紹介します。

KRCLUBでも、Webサービスの拡張性と開発効率を高めるため、API設計やデータ取得方式の最適化に注目しています。


1. REST APIの基本

REST APIでは、リソースごとにエンドポイントを用意することが一般的です。

例えば、

GET /api/users/1001
GET /api/users/1001/posts
GET /api/users/1001/favorites

という形です。

シンプルで理解しやすく、多くのWebサービスで利用されています。

しかし、複雑な画面では複数のAPIを呼ぶ必要があります。

例えばユーザープロフィール画面で、

  • ユーザー情報
  • 最近の記事
  • お気に入り
  • フォロー情報

を表示する場合、複数リクエストが必要になることがあります。


2. GraphQLとは

GraphQLでは、クライアントが必要なデータを指定して取得します。

例えば、

query {
  user(id: "1001") {
    name
    profileImage
    posts {
      title
      createdAt
    }
  }
}

このように、必要なフィールドだけを指定できます。

レスポンス例:

{
  "data": {
    "user": {
      "name": "Example User",
      "profileImage": "/images/user.png",
      "posts": [
        {
          "title": "GraphQL Introduction",
          "createdAt": "2026-10-19"
        }
      ]
    }
  }
}

クライアントが必要な情報だけを取得できる点が特徴です。


3. Over-fetchingを減らす

REST APIでは、エンドポイントが固定されているため、不要なデータまで返されることがあります。

例えば、

{
  "id": 1001,
  "name": "User A",
  "email": "example@example.com",
  "address": "...",
  "createdAt": "...",
  "settings": {}
}

というレスポンスのうち、

name

だけ必要だったとしても、すべて取得してしまう場合があります。

これをOver-fetchingと呼びます。

GraphQLでは、

query {
  user(id: "1001") {
    name
  }
}

のように必要な情報だけ取得できます。


4. Under-fetchingを減らす

逆に、1回のAPIリクエストだけでは必要なデータが足りないこともあります。

例えば、

GET /users/1001

を呼び出した後、

GET /users/1001/posts

さらに、

GET /users/1001/favorites

を呼び出す場合です。

これをUnder-fetchingと呼ぶことがあります。

GraphQLでは1回のQueryでまとめて取得できます。

query {
  user(id: "1001") {
    name

    posts {
      title
    }

    favorites {
      title
    }
  }
}

5. GraphQL Schema

GraphQLではSchemaを定義します。

例:

type User {
  id: ID!
  name: String!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String
}

Query:

type Query {
  user(id: ID!): User
  posts: [Post!]!
}

Schemaによって、

  • どのデータが存在するか
  • どの型なのか
  • どのフィールドを取得できるか

が明確になります。


6. Resolverの役割

GraphQLでは、各フィールドのデータを取得する処理をResolverと呼びます。

Node.jsの簡単な例:

const resolvers = {
  Query: {
    user: async (_, { id }) => {
      return database.getUser(id);
    }
  },

  User: {
    posts: async (user) => {
      return database.getPostsByUser(user.id);
    }
  }
};

GraphQLサーバーはQueryを受け取ると、必要なResolverを実行します。


7. N+1問題

GraphQLで注意したい代表的な問題がN+1問題です。

例えばユーザー10人と、それぞれの記事を取得するとします。

1 query
→ users取得

10 queries
→ 各userの記事取得

結果として、

1 + 10 = 11 queries

になる可能性があります。

ユーザー数が100人なら、さらにクエリ数が増えます。


8. DataLoaderでN+1問題を改善する

N+1問題を改善する代表的な方法がDataLoaderです。

複数のリクエストをまとめて処理します。

例えば、

User 1 posts
User 2 posts
User 3 posts

を個別に取得するのではなく、

SELECT *
FROM posts
WHERE user_id IN (1, 2, 3);

のようにまとめます。

Node.jsではDataLoaderライブラリを利用できます。

import DataLoader from "dataloader";

const postLoader = new DataLoader(
  async (userIds) => {
    const posts =
      await database.getPostsByUserIds(userIds);

    return userIds.map((id) =>
      posts.filter(
        (post) => post.userId === id
      )
    );
  }
);

これによってデータベースアクセスを削減できます。


9. Mutationでデータを更新する

GraphQLではデータ更新にMutationを利用します。

Schema:

type Mutation {
  updateProfile(
    name: String!
  ): User!
}

Query:

mutation {
  updateProfile(
    name: "New Name"
  ) {
    id
    name
  }
}

REST APIでいう、

POST
PUT
PATCH
DELETE

に相当する操作をMutationとして表現します。


10. GraphQLのキャッシュ

REST APIではURL単位でキャッシュしやすいという特徴があります。

一方GraphQLは、

/graphql

という1つのエンドポイントを利用することが多いため、HTTPキャッシュだけでは管理しにくい場合があります。

そのため、

  • Apollo Client
  • Relay
  • Redis
  • CDN
  • Application Cache

などを組み合わせます。


11. Apollo Clientによるフロントエンドキャッシュ

Reactアプリケーションでは、Apollo Clientを利用するケースがあります。

import {
  ApolloClient,
  InMemoryCache
} from "@apollo/client";

const client = new ApolloClient({
  uri: "/graphql",
  cache: new InMemoryCache()
});

取得したデータをクライアント側へキャッシュできます。

同じデータを再度必要とする場合、キャッシュから取得できる可能性があります。


12. Query Complexityを制御する

GraphQLではクライアントが自由にQueryを組み立てられるため、非常に複雑なQueryを送信される可能性があります。

例えば、

User
 ↓
Posts
 ↓
Comments
 ↓
Authors
 ↓
Posts
 ↓
Comments

のようにネストが深くなると、サーバー負荷が増加します。

そのため、

  • Depth Limit
  • Complexity Limit
  • Timeout
  • Rate Limit

などを設定することが重要です。


13. 認証・認可も必要

GraphQLを導入しても、セキュリティ設計は必要です。

例えば、

query {
  user(id: "1001") {
    email
  }
}

というQueryがあった場合、本当にそのユーザー情報を閲覧する権限があるかを確認する必要があります。

Resolver側で、

Authentication
+
Authorization

を実装します。


14. RESTとGraphQLはどちらが良いのか

GraphQLが常にRESTより優れているわけではありません。

RESTが向いているケース:

  • API構造がシンプル
  • エンドポイント数が少ない
  • HTTPキャッシュを重視
  • CRUD中心

GraphQLが向いているケース:

  • データ構造が複雑
  • クライアントごとに必要データが異なる
  • フロントエンド開発が活発
  • 複数データソースを統合したい

重要なのは、サービス要件に合わせて選択することです。


15. GraphQL Gatewayという考え方

大規模なサービスでは、GraphQLを複数バックエンドの統合レイヤーとして利用することもできます。

例えば、

Web App
   ↓
GraphQL Gateway
   ↓
User Service
Content Service
Search Service
Recommendation Service

フロントエンド側ではGraphQLだけを利用し、内部では複数サービスからデータを取得します。

これによって、クライアント側の実装をシンプルにできます。


16. KRCLUBが注目するAPI設計

KRCLUBでは、Webサービスの成長に合わせて、フロントエンドとバックエンドのデータ連携をどのように効率化するかという点にも注目しています。

特に、

  • APIレスポンス最適化
  • GraphQL
  • キャッシュ設計
  • データベース負荷軽減
  • フロントエンド開発効率

といった技術は、サービス規模が大きくなるほど重要になります。

APIは単なるデータ取得手段ではありません。

フロントエンド開発速度やシステム拡張性にも影響する重要な設計要素です。


17. AIサービスとGraphQL

AI機能を含むWebサービスでもGraphQLを利用できます。

例えば、

query {
  content(id: "101") {
    title
    summary
    recommendation {
      title
    }
  }
}

という形で、

  • 通常コンテンツ
  • AI要約
  • AI推薦

を一つのデータモデルとして扱うこともできます。

ただしAI処理はレスポンス時間が長くなる場合があります。

そのため、

GraphQL
+
Cache
+
Async Processing

などを組み合わせることが重要です。


まとめ

GraphQLは、複雑化するWebサービスのデータ取得を効率化するための選択肢のひとつです。

特に重要なポイントは、

  • Over-fetching削減
  • Under-fetching削減
  • Schema設計
  • Resolver
  • DataLoader
  • キャッシュ
  • Query Complexity
  • 認証・認可

です。

ただし、GraphQLを導入すれば自動的にパフォーマンスが向上するわけではありません。

Resolver設計やデータベースアクセスを適切に管理しなければ、逆に負荷が増える可能性もあります。

KRCLUBでも、安定性と開発効率を両立するため、REST API、GraphQL、キャッシュ、データ処理を含めたバックエンド設計に注目しています。

Webサービスが成長するほど、「どのようにデータを取得するか」は、ユーザー体験と開発効率の両方を左右する重要な技術テーマになるでしょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?