ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-04-08上級

Antigravity で API ファースト開発を極める — OpenAPI 仕様からコード自動生成・テスト・ドキュメント一括構築

Antigravity の AI エージェントを活用し、OpenAPI 仕様を起点にバックエンド・フロントエンド・テスト・ドキュメントを一括自動生成する API ファースト開発の実践手法を体系的に解説します。

antigravity435openapiapi-firstcode-generation2swaggertypescript26testing15documentation4

取り組みの背景 — なぜ API ファースト開発が重要なのか

モダンなソフトウェア開発において、フロントエンドとバックエンドを並行開発する体制は当たり前になりましました。しかし、口頭やドキュメントだけで API の仕様を共有していると、実装の食い違いが発生し、統合テストの段階で大量のバグが噴出するという問題を多くのチームが経験しています。

API ファースト開発とは、まず API の仕様(コントラクト)を定義し、それを単一の信頼できる情報源(Single Source of Truth)として開発を進める手法です。OpenAPI(旧 Swagger)仕様を中心に据えることで、バックエンドのスタブ生成、フロントエンドの型定義、テストケースの自動生成、そして API ドキュメントの自動公開まで、すべてを一つの仕様ファイルから派生させることが可能になります。

Antigravity の AI エージェントは、この API ファースト開発のワークフローと極めて相性が良い設計です。ここではOpenAPI 仕様の設計から始めて、コード自動生成、テスト、ドキュメント生成、CI/CD パイプラインへの統合まで、実務で使える完全なワークフローを体系的に解説します。

なお、API 設計の基礎やサーバーレス構成に興味のある方は Antigravity でサーバーレス API を効率的に構築 — Hono + Cloudflare Workers 実践ガイド もあわせてご参照ください。

OpenAPI 仕様の基礎と設計原則

OpenAPI 3.1 の構造

OpenAPI 3.1 は JSON Schema との完全互換を達成したバージョンであり、2026年現在のデファクトスタンダードです。基本構造は以下の通りです。

# openapi.yaml — プロジェクトの API 仕様書
openapi: "3.1.0"
info:
  title: "My SaaS API"
  version: "1.0.0"
  description: "ユーザー管理と課金を担うコア API"
servers:
  - url: "https://api.example.com/v1"
    description: "本番環境"
  - url: "http://localhost:3000/v1"
    description: "ローカル開発"
paths:
  /users:
    get:
      operationId: listUsers
      summary: "ユーザー一覧を取得"
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        "200":
          description: "成功"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserListResponse"
components:
  schemas:
    User:
      type: object
      required: [id, email, createdAt]
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        name:
          type: string
        createdAt:
          type: string
          format: date-time
    UserListResponse:
      type: object
      properties:
        users:
          type: array
          items:
            $ref: "#/components/schemas/User"
        total:
          type: integer
        page:
          type: integer

設計原則:「API を使う側」の視点で考える

良い API 設計の鍵は、実装者ではなく利用者の視点に立つことです。Antigravity のエージェントに仕様書作成を依頼する際も、以下の原則をプロンプトに含めると品質が大幅に向上します。

  • リソース指向: URL パスは名詞(/users, /orders)で、動詞は HTTP メソッドで表現する
  • 一貫性のある命名: operationIdlistUsers, getUser, createUser のように 動詞 + リソース名 で統一する
  • エラーレスポンスの標準化: RFC 7807(Problem Details)形式で全エンドポイント共通のエラー構造を定義する
  • ページネーション: カーソルベースまたはオフセットベースを統一し、components/parameters で再利用する

Antigravity で OpenAPI 仕様を効率的に作成する

AI エージェントによる仕様書生成

Antigravity の Manager Surface からエージェントに仕様書の生成を依頼する方法が最も効率的です。以下のようなプロンプトで、実用的な仕様書を生成できます。

# Antigravity プロンプト例
以下の要件に基づいて OpenAPI 3.1 仕様書を YAML で作成してください。
 
## サービス概要
- ECサイトの商品管理 API
- 認証は Bearer トークン(JWT)
- ページネーションはカーソルベース
 
## エンドポイント
1. 商品一覧(フィルタ・ソート対応)
2. 商品詳細
3. 商品作成(管理者のみ)
4. 商品更新(管理者のみ)
5. 商品削除(管理者のみ)
 
## 制約
- エラーレスポンスは RFC 7807 準拠
- 全レスポンスに rate-limit ヘッダーを含める
- components/schemas を活用してスキーマを再利用する

Antigravity のエージェントはコンテキスト内の既存コードを参照するため、プロジェクト内に既にモデル定義(Prisma スキーマや TypeORM エンティティなど)がある場合、自動的にそれらと整合性のある仕様を生成します。

Editor View でのインライン編集

仕様書の細部を調整するには、Editor View のインライン AI コマンドが便利です。仕様ファイルを開いた状態で、特定のパスやスキーマにカーソルを当て、Ctrl+I(インラインコマンド)を起動します。

# インラインコマンドの例
「このエンドポイントに rate limiting のレスポンスヘッダー
(X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset)を追加して」

AI がスキーマの文脈を理解した上でヘッダー定義を components/headers に追加し、各レスポンスから $ref で参照する構造を自動生成します。

コード自動生成パイプラインの構築

TypeScript バックエンド(Hono + Zod)の自動生成

OpenAPI 仕様から TypeScript のサーバーコードを生成するパイプラインを構築します。ここでは openapi-typescriptopenapi-zod-client を組み合わせるアプローチを紹介します。

# 必要なパッケージのインストール
npm install openapi-typescript openapi-zod-client -D
 
# 型定義の生成
npx openapi-typescript openapi.yaml -o src/generated/api-types.ts
 
# Zod スキーマの生成
npx openapi-zod-client openapi.yaml -o src/generated/api-schemas.ts

生成された型定義を Hono のルーターで活用する実装例です。

// src/routes/users.ts
import { Hono } from "hono";
import { zValidator } from "@hono/zod-validator";
import { listUsersQuerySchema, createUserBodySchema } from "../generated/api-schemas";
import type { paths } from "../generated/api-types";
 
// 型安全なレスポンス型
type ListUsersResponse =
  paths["/users"]["get"]["responses"]["200"]["content"]["application/json"];
 
const users = new Hono();
 
users.get(
  "/",
  zValidator("query", listUsersQuerySchema),
  async (c) => {
    const { page, limit } = c.req.valid("query");
    // DB からユーザーを取得(Prisma の例)
    const [items, total] = await Promise.all([
      prisma.user.findMany({
        skip: (page - 1) * limit,
        take: limit,
        orderBy: { createdAt: "desc" },
      }),
      prisma.user.count(),
    ]);
    // レスポンスは ListUsersResponse 型と互換
    const response: ListUsersResponse = {
      users: items,
      total,
      page,
    };
    return c.json(response);
  }
);
 
export default users;

フロントエンド API クライアントの自動生成

フロントエンド側では openapi-fetch を使うことで、型安全な API クライアントを自動生成できます。

// src/lib/api-client.ts
import createClient from "openapi-fetch";
import type { paths } from "../generated/api-types";
 
// 型安全な API クライアント
const client = createClient<paths>({
  baseUrl: process.env.NEXT_PUBLIC_API_URL,
  headers: {
    Authorization: `Bearer ${getAccessToken()}`,
  },
});
 
// 使用例 — パス・パラメータ・レスポンスすべてが型安全
async function fetchUsers(page: number = 1) {
  const { data, error } = await client.GET("/users", {
    params: {
      query: { page, limit: 20 },
    },
  });
  if (error) {
    // error の型も OpenAPI 仕様から推論される
    throw new ApiError(error);
  }
  // data.users — User[] 型が推論される
  return data;
}

この方法の最大の利点は、OpenAPI 仕様を更新して型を再生成するだけで、バックエンドとフロントエンドの型が自動的に同期されることです。

Antigravity エージェントによるテスト自動生成

API テストの自動生成

Antigravity のエージェントに OpenAPI 仕様を読み込ませ、テストコードを自動生成する手法です。

# Antigravity プロンプト例
openapi.yaml の全エンドポイントに対して、
以下の観点でテストケースを Vitest で生成してください:
 
1. 正常系(200/201 レスポンス)
2. バリデーションエラー(400)
3. 認証エラー(401)
4. 権限エラー(403)
5. 存在しないリソース(404)
6. レート制限(429)
 
各テストには明確な説明文とアサーションを含めてください。

生成されるテストコードの例です。

// tests/api/users.test.ts
import { describe, it, expect, beforeAll } from "vitest";
import { createTestClient } from "../helpers/test-client";
 
describe("GET /users", () => {
  const client = createTestClient();
 
  it("ページネーション付きでユーザー一覧を取得できる", async () => {
    const res = await client.get("/users?page=1&limit=10");
    expect(res.status).toBe(200);
    expect(res.body.users).toBeInstanceOf(Array);
    expect(res.body.users.length).toBeLessThanOrEqual(10);
    expect(res.body.total).toBeTypeOf("number");
    expect(res.body.page).toBe(1);
  });
 
  it("limit の上限を超えると 400 を返す", async () => {
    const res = await client.get("/users?limit=999");
    expect(res.status).toBe(400);
    expect(res.body.type).toContain("validation-error");
    // RFC 7807 形式のエラーレスポンスを検証
    expect(res.body).toHaveProperty("title");
    expect(res.body).toHaveProperty("detail");
  });
 
  it("認証なしでアクセスすると 401 を返す", async () => {
    const unauthClient = createTestClient({ auth: false });
    const res = await unauthClient.get("/users");
    expect(res.status).toBe(401);
  });
});
 
describe("POST /users", () => {
  const adminClient = createTestClient({ role: "admin" });
 
  it("管理者がユーザーを作成できる", async () => {
    const res = await adminClient.post("/users", {
      body: {
        email: "new@example.com",
        name: "New User",
      },
    });
    expect(res.status).toBe(201);
    expect(res.body.id).toBeDefined();
    expect(res.body.email).toBe("new@example.com");
  });
 
  it("一般ユーザーは作成権限がなく 403 を返す", async () => {
    const userClient = createTestClient({ role: "user" });
    const res = await userClient.post("/users", {
      body: { email: "test@example.com", name: "Test" },
    });
    expect(res.status).toBe(403);
  });
});

コントラクトテスト — 仕様と実装の乖離を検出

API ファースト開発で最も重要なのは、仕様と実装が常に一致していることを保証するコントラクトテストです。

// tests/contract/openapi-contract.test.ts
import { describe, it, expect } from "vitest";
import SwaggerParser from "@apidevtools/swagger-parser";
import Ajv from "ajv";
import addFormats from "ajv-formats";
import { createTestClient } from "../helpers/test-client";
 
describe("OpenAPI Contract Tests", () => {
  let api: any;
  let ajv: Ajv;
 
  beforeAll(async () => {
    // OpenAPI 仕様をパース
    api = await SwaggerParser.dereference("openapi.yaml");
    ajv = new Ajv({ allErrors: true, strict: false });
    addFormats(ajv);
  });
 
  it("GET /users のレスポンスが仕様と一致する", async () => {
    const client = createTestClient();
    const res = await client.get("/users");
 
    // 仕様からスキーマを取得
    const schema =
      api.paths["/users"].get.responses["200"]
        .content["application/json"].schema;
 
    // レスポンスが仕様に準拠しているか検証
    const validate = ajv.compile(schema);
    const valid = validate(res.body);
 
    if (!valid) {
      console.error("Schema violations:", validate.errors);
    }
    expect(valid).toBe(true);
  });
});

このコントラクトテストを CI に組み込むことで、「仕様書を更新したが実装を忘れた」「実装を変更したが仕様書を更新しなかった」というヒューマンエラーを自動的に検出できます。

API ドキュメントの自動生成と公開

Redoc / Swagger UI の統合

OpenAPI 仕様から美しい API ドキュメントを自動生成し、デプロイする方法です。

// src/app/api/docs/route.ts — Next.js API Route でドキュメントを配信
import { readFileSync } from "fs";
import path from "path";
 
const specYaml = readFileSync(
  path.join(process.cwd(), "openapi.yaml"),
  "utf-8"
);
 
export async function GET() {
  const html = `<!DOCTYPE html>
<html>
<head>
  <title>API Documentation</title>
  <meta charset="utf-8" />
  <link href="https://fonts.googleapis.com/css?family=Inter:300,400,600" rel="stylesheet">
  <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
</head>
<body>
  <div id="redoc-container"></div>
  <script>
    Redoc.init('/api/docs/spec', {
      theme: {
        colors: { primary: { main: '#1a73e8' } },
        typography: { fontFamily: 'Inter, sans-serif' },
      },
      hideDownloadButton: false,
      expandResponses: '200,201',
    }, document.getElementById('redoc-container'));
  </script>
</body>
</html>`;
  return new Response(html, {
    headers: { "Content-Type": "text/html" },
  });
}

Antigravity エージェントによるドキュメント品質向上

仕様書のドキュメント品質を向上させるためのプロンプトパターンです。

# Antigravity プロンプト例
openapi.yaml の以下の点を改善してください:
 
1. 全エンドポイントに description を追加(ユースケースを含める)
2. 全パラメータに example 値を追加
3. レスポンスに実用的な example を追加
4. tags でエンドポイントをグループ化
5. セキュリティスキームの説明を充実させる

CI/CD パイプラインへの統合

GitHub Actions による自動検証パイプライン

OpenAPI 仕様の変更を起点に、型生成・テスト・ドキュメント生成を自動実行するパイプラインです。

# .github/workflows/api-first.yaml
name: API First Pipeline
on:
  push:
    paths:
      - "openapi.yaml"
      - "src/**"
  pull_request:
    paths:
      - "openapi.yaml"
 
jobs:
  validate-and-generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          cache: "npm"
 
      - run: npm ci
 
      # 1. OpenAPI 仕様のバリデーション
      - name: Validate OpenAPI spec
        run: npx @redocly/cli lint openapi.yaml
 
      # 2. 型定義の再生成
      - name: Generate TypeScript types
        run: npx openapi-typescript openapi.yaml -o src/generated/api-types.ts
 
      # 3. Zod スキーマの再生成
      - name: Generate Zod schemas
        run: npx openapi-zod-client openapi.yaml -o src/generated/api-schemas.ts
 
      # 4. 生成コードに差分がないか確認
      - name: Check for uncommitted generated files
        run: |
          git diff --exit-code src/generated/ || {
            echo "❌ Generated files are out of date!"
            echo "Run: npm run generate:api and commit the changes"
            exit 1
          }
 
      # 5. 型チェック
      - name: TypeScript type check
        run: npx tsc --noEmit
 
      # 6. コントラクトテスト
      - name: Run contract tests
        run: npx vitest run tests/contract/
 
      # 7. API テスト
      - name: Run API tests
        run: npx vitest run tests/api/

Breaking Change 検出

API の後方互換性を破壊する変更を PR の段階で検出する仕組みです。

# GitHub Actions の追加ステップ
      - name: Detect breaking changes
        if: github.event_name == 'pull_request'
        run: |
          # メインブランチの仕様を取得
          git fetch origin main
          git show origin/main:openapi.yaml > /tmp/openapi-base.yaml
          # 差分を検出
          npx @redocly/cli diff /tmp/openapi-base.yaml openapi.yaml \
            --fail-on-incompatible

この設定により、「レスポンスの必須フィールドを削除した」「エンドポイントの URL を変更した」といった互換性を破壊する変更が PR のチェックで自動的にブロックされます。

実践的な設計パターン集

パターン 1: バージョニング戦略

# URL パスベースのバージョニング
servers:
  - url: "https://api.example.com/v1"
  - url: "https://api.example.com/v2"
 
# ヘッダーベースのバージョニング
paths:
  /users:
    get:
      parameters:
        - name: API-Version
          in: header
          schema:
            type: string
            enum: ["2026-01-01", "2026-04-01"]
            default: "2026-04-01"

パターン 2: エラーレスポンスの標準化(RFC 7807)

components:
  schemas:
    ProblemDetail:
      type: object
      required: [type, title, status]
      properties:
        type:
          type: string
          format: uri
          description: "エラータイプを識別する URI"
          # 例: "https://api.example.com/errors/validation"
        title:
          type: string
          description: "人間が読めるエラータイトル"
        status:
          type: integer
          description: "HTTP ステータスコード"
        detail:
          type: string
          description: "エラーの詳細な説明"
        instance:
          type: string
          format: uri
          description: "このエラー発生のインスタンスURI"
        errors:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
              message:
                type: string

パターン 3: カーソルベースページネーション

# components/parameters で再利用可能に定義
components:
  parameters:
    CursorParam:
      name: cursor
      in: query
      description: "次のページの起点となるカーソル値"
      schema:
        type: string
    LimitParam:
      name: limit
      in: query
      schema:
        type: integer
        default: 20
        minimum: 1
        maximum: 100
  schemas:
    PaginationMeta:
      type: object
      properties:
        hasNext:
          type: boolean
        nextCursor:
          type: string
          nullable: true
        total:
          type: integer

まとめ

API ファースト開発は、最初に仕様を定義する一手間がかかるように見えますが、開発が進むにつれてその投資は何倍ものリターンを生みます。Antigravity の AI エージェントを活用することで、仕様書の作成・型生成・テスト自動生成・ドキュメント公開のすべてを高速に回せるようになり、「仕様と実装の乖離」という開発チームの永遠の課題を根本から解消できます。

まずは小さなプロジェクトで openapi.yaml を1ファイル作成し、型生成とコントラクトテストの仕組みを導入してみてください。その効果を実感したら、既存プロジェクトへの段階的な導入に進みましょう。

セキュリティや認証パターンのさらに詳しい実装については Antigravity エージェントでセキュアな API バックエンドを構築する — 認証・バリデーション・レート制限の実装パターン も参照してみてください。また、GraphQL との比較に興味のある方は Antigravity × GraphQL + Apollo Server 実践チュートリアル もぜひご覧ください。

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

アプリ開発2026-06-30
Antigravity が書いたテストが全部グリーンなのに同じバグが再発するとき — 空回りするアサーションを計測する運用メモ
AI に書かせたテストがすべて通り、カバレッジも高いのに本番で同じ不具合が戻ってくる。原因はモック過多とトートロジー的なアサーションです。ミューテーションテストを正解とし、テストが実際に何を守っているかを実測して運用で立て直すメモです。
アプリ開発2026-05-04
Swift Testing × Antigravity — XCTest の限界を超えて AI 駆動テスト設計へ
Swift Testing フレームワークと Antigravity の組み合わせで iOS テスト品質を根本から変える実践ガイド。@Test・#expect マクロの活用から XCTest 移行戦略、Antigravity によるテスト自動生成まで体系的に解説します。
アプリ開発2026-05-03
Antigravity × TypeScript で作る冪等性キーと重複排除ストア本番設計ガイド
Stripe Webhook の二重課金や Temporal ワークフローの再実行で起きる重複処理を、冪等性キーと重複排除ストアで止める本番設計を、Antigravity を伴走者にして TypeScript で組み上げる実践ガイドです。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →