「GraphQL APIを設計したいけれど、スキーマの粒度をどうすべきかわからない」「N+1問題が怖くて導入を躊躇している」「REST APIからGraphQLへの移行方法が見えない」——GraphQL導入時に多くのエンジニアが抱える悩みです。
Gemini CLI(Google Antigravity)を使えば、スキーマ設計・リゾルバ実装・DataLoaderによるN+1対策まで、GraphQL開発の全工程を効率的に進められます。本記事では、実プロジェクトを想定した実践テクニックを解説します。
この記事を3秒でまとめると
- Gemini CLIはGraphQLスキーマの設計からコード生成まで一貫してサポート
- DataLoaderパターンでN+1問題を自動解決する実装が可能
- REST→GraphQL移行もスキーマ自動生成で効率化できる

なぜGemini CLIでGraphQL開発なのか
GraphQLは、クライアントが必要なデータだけを取得できる柔軟なAPI仕様として、2026年現在も採用が拡大しています。GitHub API v4、Shopify、Hasuraなど多くのプラットフォームがGraphQLを採用しています。
しかし、GraphQLの導入には独自の学習コストがあります。
GraphQL開発の課題
- スキーマ設計: Type・Query・Mutation・Subscriptionの適切な粒度
- N+1問題: リレーション解決時のクエリ爆発
- 認証・認可: フィールドレベルのアクセス制御
- エラーハンドリング: GraphQL固有のエラーレスポンス設計
- パフォーマンス: クエリの深度制限・複雑度分析
Gemini CLIはGeminiモデルの大規模コンテキスト窓を活かし、プロジェクト全体のスキーマ・リゾルバ・型定義を横断的に理解した上でコードを生成します。既存のRESTエンドポイントを読み取ってGraphQLスキーマに変換する、といった作業も得意です。
Gemini CLIの優位性
| 機能 | Gemini CLI | 手動開発 |
|---|---|---|
| スキーマ設計 | ER図からType自動生成 | 手動で定義 |
| リゾルバ実装 | DataLoader込みで生成 | N+1を見落としがち |
| 型定義(codegen) | GraphQL Code Generator設定も自動 | 設定が煩雑 |
| テスト生成 | クエリ・ミューテーション両方 | テスト不足になりがち |
| ドキュメント | SDL + 説明文を同時生成 | 後回しになりがち |
GraphQLスキーマ設計
Gemini CLIでスキーマを自動生成
プロンプト: SES案件管理システムのGraphQLスキーマを設計してください。
以下のエンティティを含めてください:
- User(エンジニア)
- Project(SES案件)
- Skill(技術スキル)
- Application(応募)
リレーション: User ←→ Skill(多対多)、Project → Skill(必須スキル)、
User → Application → Project
Relay仕様のConnection/Edgeパターンを使ってください。
Gemini CLIが生成するスキーマ:
type Query {
"""案件を検索"""
projects(
first: Int
after: String
filter: ProjectFilter
): ProjectConnection!
"""案件詳細を取得"""
project(id: ID!): Project
"""エンジニア情報を取得"""
user(id: ID!): User
"""自分のプロフィール"""
me: User!
}
type Mutation {
"""案件に応募"""
applyToProject(input: ApplyInput!): ApplyPayload!
"""案件を作成"""
createProject(input: CreateProjectInput!): CreateProjectPayload!
"""プロフィールを更新"""
updateProfile(input: UpdateProfileInput!): UpdateProfilePayload!
}
type Project implements Node {
id: ID!
title: String!
description: String
unitPrice: Int!
remotePolicy: RemotePolicy!
location: Location!
requiredSkills: [Skill!]!
applications(first: Int, after: String): ApplicationConnection!
startDate: DateTime!
createdAt: DateTime!
updatedAt: DateTime!
}
type User implements Node {
id: ID!
name: String!
email: String!
skills: [UserSkill!]!
applications(first: Int, after: String): ApplicationConnection!
createdAt: DateTime!
}
type Skill implements Node {
id: ID!
name: String!
category: SkillCategory!
}
type UserSkill {
skill: Skill!
yearsOfExperience: Int!
level: SkillLevel!
}
enum RemotePolicy {
FULL
PARTIAL
NONE
}
enum SkillLevel {
BEGINNER
INTERMEDIATE
ADVANCED
EXPERT
}
enum SkillCategory {
LANGUAGE
FRAMEWORK
DATABASE
CLOUD
DEVOPS
OTHER
}
"""Relay Node interface"""
interface Node {
id: ID!
}
"""Relay Connection pattern"""
type ProjectConnection {
edges: [ProjectEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type ProjectEdge {
cursor: String!
node: Project!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
input ProjectFilter {
skills: [String!]
minPrice: Int
maxPrice: Int
remotePolicy: RemotePolicy
prefecture: String
}
input ApplyInput {
projectId: ID!
message: String!
}
scalar DateTime
Relay仕様のConnectionパターンを使う理由: ページネーションの標準化、キャッシュの効率化、クライアントフレームワーク(Relay・Apollo)との親和性が高いためです。Gemini CLIはこのパターンを正確に生成できます。
リゾルバ実装とN+1問題の解決
DataLoaderパターンの自動実装
GraphQL最大の落とし穴であるN+1問題を、Gemini CLIに依頼して解決しましょう。
プロンプト: 上記スキーマのリゾルバをNode.js + TypeScriptで実装してください。
graphql-yoga + Pothos(旧GraphQL Nexus)を使い、
DataLoaderでN+1問題を解決してください。
import DataLoader from 'dataloader';
// DataLoaderファクトリ
export function createLoaders(db: PrismaClient) {
return {
skillsByProjectId: new DataLoader<string, Skill[]>(
async (projectIds) => {
const relations = await db.projectSkill.findMany({
where: { projectId: { in: [...projectIds] } },
include: { skill: true },
});
const map = new Map<string, Skill[]>();
for (const rel of relations) {
const existing = map.get(rel.projectId) ?? [];
existing.push(rel.skill);
map.set(rel.projectId, existing);
}
return projectIds.map((id) => map.get(id) ?? []);
}
),
userById: new DataLoader<string, User | null>(
async (userIds) => {
const users = await db.user.findMany({
where: { id: { in: [...userIds] } },
});
const map = new Map(users.map((u) => [u.id, u]));
return userIds.map((id) => map.get(id) ?? null);
}
),
};
}
DataLoaderは同一リクエスト内で同じキーへのアクセスを自動的にバッチ化します。Gemini CLIに「N+1を防いで」と指示するだけで、適切なDataLoaderの設定とリゾルバへの組み込みまで一括で生成してくれます。
フィールドレベル認可の実装
プロンプト: GraphQLリゾルバにフィールドレベルの認可を追加してください。
- unitPrice: ログインユーザーのみ閲覧可能
- email: 本人またはadminのみ
- applications: 案件作成者のみ
Pothosのauthスコープを使ってください。
GraphQL Code Generatorとの連携
型安全なクライアント自動生成
プロンプト: GraphQL Code Generatorの設定を生成してください。
- サーバー側: リゾルバの型定義
- クライアント側: TypedDocumentNodeでReact Queryと連携
- テスト用: モック生成プラグイン
# codegen.yml
schema: ./src/schema/**/*.graphql
generates:
src/generated/server-types.ts:
plugins:
- typescript
- typescript-resolvers
config:
contextType: ../context#GraphQLContext
mappers:
Project: ../models#ProjectModel
User: ../models#UserModel
src/generated/client-types.ts:
documents: ./src/graphql/**/*.graphql
plugins:
- typescript
- typescript-operations
- typed-document-node
src/generated/mocks.ts:
plugins:
- typescript-mock-data
config:
typesFile: ./client-types.ts
REST APIからGraphQLへの移行
既存のREST APIをGraphQLに移行する際も、Gemini CLIが強力にサポートします。
移行戦略
- Phase 1: RESTエンドポイントを分析し、GraphQLスキーマを自動設計
- Phase 2: GraphQLゲートウェイ(Apollo Federation)でREST APIをラップ
- Phase 3: クライアントを段階的にGraphQLに移行
- Phase 4: RESTエンドポイントを廃止
プロンプト: 以下のOpenAPI仕様を読み取り、
対応するGraphQLスキーマを生成してください。
RESTのGET/POST/PUT/DELETEを
Query/Mutationに適切にマッピングしてください。
Gemini CLIは100万トークン以上のコンテキスト窓を持つため、大規模なOpenAPI仕様書でも一括で処理できます。これはREST→GraphQL移行の設計フェーズで大きなアドバンテージです。
テストとモニタリング
GraphQLクエリのテスト自動生成
プロンプト: 以下のGraphQLスキーマに対する統合テストを生成してください。
- 正常系: CRUD操作の一連のフロー
- 異常系: 認証なし、バリデーションエラー、存在しないID
- エッジケース: 空リスト、最大ページネーション、深いネスト
vitestを使用してください。
import { describe, it, expect, beforeAll } from 'vitest';
import { createTestServer } from './helpers';
describe('Projects API', () => {
let server: TestServer;
beforeAll(async () => {
server = await createTestServer();
});
it('案件一覧をページネーション付きで取得', async () => {
const result = await server.execute({
query: `
query ListProjects($first: Int!, $after: String) {
projects(first: $first, after: $after) {
edges {
cursor
node { id title unitPrice }
}
pageInfo { hasNextPage endCursor }
totalCount
}
}
`,
variables: { first: 10 },
});
expect(result.errors).toBeUndefined();
expect(result.data?.projects.edges.length).toBeLessThanOrEqual(10);
expect(result.data?.projects.totalCount).toBeGreaterThanOrEqual(0);
});
it('認証なしでunitPriceにアクセスするとエラー', async () => {
const result = await server.executeUnauthenticated({
query: `{ projects(first: 1) { edges { node { unitPrice } } } }`,
});
expect(result.errors).toBeDefined();
expect(result.errors?.[0]?.message).toContain('認証');
});
});
パフォーマンスモニタリング
GraphQL APIの本番運用では、クエリの複雑度やレスポンスタイムの監視が重要です。
プロンプト: GraphQL APIに以下のモニタリングを追加してください。
1. クエリの深度制限(最大10)
2. コスト分析(フィールドごとのコスト定義)
3. スロークエリログ(500ms以上)
4. Apollo Studio互換のトレーシング
SES案件でのGraphQL需要
市場動向
| 技術領域 | GraphQL採用率 | 主な案件 |
|---|---|---|
| フロントエンド | 高い | React + Apollo/urql |
| BFF(Backend for Frontend) | 急増中 | API集約・最適化 |
| マイクロサービスゲートウェイ | 増加中 | Apollo Federation |
| CMS/EC | 高い | Shopify・Contentful |
| モバイルアプリ | 増加中 | 帯域最適化 |
単価相場(2026年目安)
| スキルレベル | 月額単価目安 |
|---|---|
| GraphQL基礎(クライアント利用) | 55〜70万円 |
| GraphQL中級(サーバー実装) | 70〜90万円 |
| GraphQL上級(Federation設計) | 85〜110万円 |
まとめ
- Gemini CLIでスキーマ設計を自動化 — Relay仕様のConnectionパターンも対応
- DataLoaderでN+1問題を解決 — Gemini CLIがリゾルバとLoaderをセットで生成
- GraphQL Code Generatorで型安全 — サーバー/クライアント/テスト用の型を一括生成
- REST→GraphQL移行を効率化 — OpenAPIからスキーマ自動変換
- テストとモニタリングを自動化 — 統合テスト・深度制限・スロークエリログ
GraphQLの設計・実装にGemini CLIを組み込むことで、スキーマ設計からテストまでの工数を大幅に削減できます。SES案件でもGraphQL需要は拡大中——今からスキルを磨いて、高単価案件を獲得しましょう。