一般社団法人 全国個人事業主支援協会

COLUMN コラム

  • GraphQL APIの設計原則:スキーマファーストで始めるAPI開発

なぜGraphQLなのか

REST APIが抱えるオーバーフェッチ(不要なデータの取得)とアンダーフェッチ(複数回のリクエストが必要)の問題を解決するために、Facebookが開発したのがGraphQLです。クライアントが必要なデータを正確に指定できるため、ネットワーク効率が向上し、特にモバイルアプリケーションでの体験が大幅に改善されます。

しかしGraphQLの設計を誤ると、パフォーマンスやセキュリティの問題を招きます。スキーマファースト開発の原則に従い、堅牢なAPI設計を目指しましょう。

スキーマファースト開発とは

スキーマファースト開発では、実装に先立ってGraphQLスキーマ(SDL:Schema Definition Language)を定義します。これがAPIの契約として機能し、フロントエンドとバックエンドが並行して開発を進められます。

type User {
id: ID!
name: String!
email: String!
posts(first: Int, after: String): PostConnection!
createdAt: DateTime!
}

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

type PostConnection {
edges: [PostEdge!]!
pageInfo: PageInfo!
}

type PostEdge {
node: Post!
cursor: String!
}

type Query {
user(id: ID!): User
posts(first: Int, after: String, filter: PostFilter): PostConnection!
}

input PostFilter {
status: PostStatus
authorId: ID
}

このスキーマでは、Relay式のコネクションパターンを採用しています。カーソルベースのページネーションは、オフセットベースと比較して大規模データセットでのパフォーマンスが優れています。

リゾルバの実装

スキーマを定義したら、各フィールドのリゾルバを実装します。Apollo Serverを使った例を見てみましょう。

const resolvers = {
Query: {
user: async (_, { id }, { dataSources }) => {
return dataSources.userAPI.getUser(id);
},
posts: async (_, { first, after, filter }, { dataSources }) => {
return dataSources.postAPI.getPosts({ first, after, filter });
},
},
User: {
posts: async (parent, { first, after }, { dataSources }) => {
return dataSources.postAPI.getPostsByAuthor(parent.id, { first, after });
},
},
Post: {
author: async (parent, _, { loaders }) => {
return loaders.userLoader.load(parent.authorId);
},
},
};

PostのauthorリゾルバでDataLoaderを使用している点に注目してください。N+1問題を解決するために、DataLoaderによるバッチ処理は必須のテクニックです。

セキュリティとパフォーマンスの考慮

GraphQLではクライアントが任意のクエリを発行できるため、セキュリティ対策が不可欠です。クエリの深さ制限、複雑度の制限、レート制限を必ず設定しましょう。また、本番環境ではイントロスペクションを無効にすることが推奨されます。

パフォーマンス面では、Persisted Queriesの導入が効果的です。クライアントがクエリ全文ではなくハッシュ値のみを送信するため、リクエストサイズの削減と不正クエリの防止を同時に実現できます。キャッシュ戦略としてはレスポンスキャッシュに加え、フィールドレベルのキャッシュヒントを活用することで、きめ細かなキャッシュ制御が可能になります。

スキーマ設計のベストプラクティス

優れたGraphQLスキーマを設計するためのポイントをまとめます。Null許容性を厳密に設計し、必須フィールドには必ず感嘆符を付けること。ミューテーションにはInput型を使い、レスポンスにはPayload型を用いて成功・失敗を明確に表現すること。列挙型を積極的に活用して、取りうる値を制限すること。これらの原則を守ることで、型安全で使いやすいAPIが実現できます。

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア