T-CREATOR

Cursor × 生成 AI で変わる開発フロー:要件定義からレビューまでの新常識

Cursor × 生成 AI で変わる開発フロー:要件定義からレビューまでの新常識

開発現場で AI がコードを書いてくれるのは、もはや珍しいことではありませんね。でも、AI エディタの真価は「コードを生成する」だけではないんです。要件定義から設計、実装、そしてレビューに至るまで、開発フロー全体がどう変わるのか。今回は Cursor を例に、生成 AI がもたらす開発プロセスの「新常識」を一緒に見ていきましょう。

背景

従来の開発フローとその課題

これまでのソフトウェア開発は、要件定義、設計、実装、テスト、レビューといった明確なフェーズに分かれていました。各フェーズで専門知識を持つエンジニアが集まり、ドキュメントを作成し、コードを書き、レビューを重ねる。この流れは確立されていますが、フェーズ間の情報伝達コストや、ドキュメント作成の負担が大きいという課題がありました。

AI エディタの登場

近年、GitHub Copilot や Amazon CodeWhisperer など、AI がコード補完をサポートするツールが広く普及しました。さらに Cursor のような AI ネイティブなエディタは、単なる補完を超えて「会話ベースでコードを生成」「プロジェクト全体を理解して提案」といった高度な機能を提供しています。

開発フロー全体を見渡したとき、Cursor × 生成 AI の組み合わせは、要件定義の段階から最終的なレビューまで、すべてのフェーズに影響を及ぼす可能性を秘めているのです。

以下の図は、従来の開発フローと AI を活用した開発フローの比較を示します。

mermaidflowchart LR
  req["要件定義"] --> design["設計"]
  design --> impl["実装"]
  impl --> test["テスト"]
  test --> review["レビュー"]
  review --> deploy["デプロイ"]

  req2["要件定義<br/>(AI 対話)"] --> design2["設計<br/>(AI 提案)"]
  design2 --> impl2["実装<br/>(AI 生成)"]
  impl2 --> test2["テスト<br/>(AI 自動)"]
  test2 --> review2["レビュー<br/>(AI 支援)"]
  review2 --> deploy2["デプロイ"]

  subgraph traditional["従来フロー"]
    req
    design
    impl
    test
    review
    deploy
  end

  subgraph ai_flow["AI 活用フロー"]
    req2
    design2
    impl2
    test2
    review2
    deploy2
  end

この図から分かるように、AI は各フェーズで人間の作業を補完し、スピードと品質の両立を可能にします。

図で理解できる要点

  • 従来フローは人間が各フェーズを順次実行
  • AI 活用フローでは各フェーズに AI が介入し、対話・提案・生成で効率化
  • フェーズ間の移行がスムーズになる

課題

ドキュメント作成の負担

要件定義や設計では、仕様書や設計書を詳細に記述する必要があります。しかし、これらのドキュメントは作成に時間がかかる上、プロジェクトが進むにつれて更新が追いつかず、実装と乖離してしまうことも少なくありません。

コンテキストスイッチのコスト

要件を理解し、設計に落とし込み、コードを書く。この一連の流れでは、頭の中でのコンテキストスイッチが頻繁に発生します。特に複数のタスクを並行して進める場合、「あれ、この機能の仕様はどうだったっけ?」と振り返る時間が積み重なり、生産性を低下させます。

レビューの属人化

コードレビューは品質向上に欠かせませんが、レビュアーのスキルや経験に依存しがちです。また、レビュー観点が統一されていない場合、指摘内容にばらつきが生じ、レビューの質が安定しません。

以下の図は、従来フローにおける主な課題を整理したものです。

mermaidflowchart TD
  start["開発プロセス"] --> doc["ドキュメント作成"]
  doc --> burden["作成・更新の負担"]
  start --> context["コンテキストスイッチ"]
  context --> cost["生産性の低下"]
  start --> review_issue["レビューの属人化"]
  review_issue --> quality["品質のばらつき"]

図で理解できる要点

  • ドキュメント作成の負担が大きく、更新が追いつかない
  • コンテキストスイッチにより生産性が低下
  • レビューがレビュアーのスキルに依存し、品質が不安定

解決策

Cursor による AI 対話型開発

Cursor は、エディタ内で AI と対話しながらコードを生成・編集できる環境を提供します。これにより、要件定義から実装、レビューまでを一貫したコンテキストで進められるようになります。

要件定義フェーズ:対話で仕様を明確化

従来は仕様書を読み込んでから実装に入りましたが、Cursor では AI に「この機能を実現するには何が必要?」と尋ねることで、必要な要件を対話的に洗い出せます。

例えば、以下のように Cursor のチャット機能で要件を整理できます。

typescript// Cursor のチャット例
// ユーザー: 「ユーザー認証機能を追加したい。必要なファイルと実装ステップを教えて。」
// AI: 「以下のステップで進めましょう。
//   1. auth.ts でトークン検証ロジックを実装
//   2. middleware.ts で認証チェックを追加
//   3. login.tsx でフォームとAPI連携を実装
//   各ステップの詳細コードを生成しますか?」

このように、仕様をドキュメントに落とし込む前に、AI と対話しながら要件を具体化できます。

設計フェーズ:AI による提案とレビュー

設計段階では、「この構成で問題ないか」「もっと良い設計はないか」を AI に相談できます。Cursor は、プロジェクト全体のコードベースを把握しているため、既存の設計パターンに沿った提案を返してくれます。

以下は、API 設計を AI に相談する例です。

typescript// ユーザー: 「REST API の設計を考えているんだけど、以下のエンドポイントで大丈夫?」
// GET /users/:id
// POST /users
// PUT /users/:id
// DELETE /users/:id

// AI: 「基本的な CRUD は揃っていますね。以下の追加も検討してみてください。
//   - GET /users でユーザー一覧取得
//   - PATCH /users/:id で部分更新
//   - バージョニング(/v1/users)も検討してみては?」

AI の提案を受けながら、設計をブラッシュアップしていけます。

実装フェーズ:コンテキストを保ったまま生成

実装では、Cursor の Cmd + K(Mac)や Ctrl + K(Windows)でインラインコード生成を活用します。コメントで意図を書くだけで、AI が実装を提案してくれるため、コンテキストスイッチを最小限に抑えられます。

以下は、ユーザー認証ミドルウェアの生成例です。

typescript// middleware.ts

// ユーザー認証を行うミドルウェア
// トークンが有効な場合のみ次の処理へ進む

Cursor でこのコメントを書いた後、Cmd + K で以下のコードが生成されます。

typescriptimport { NextRequest, NextResponse } from 'next/server';
import { verifyToken } from '@/lib/auth';

export async function authMiddleware(req: NextRequest) {
  const token = req.headers
    .get('authorization')
    ?.split(' ')[1];

  if (!token) {
    return NextResponse.json(
      { error: '認証トークンが必要です' },
      { status: 401 }
    );
  }

  const isValid = await verifyToken(token);

  if (!isValid) {
    return NextResponse.json(
      { error: 'トークンが無効です' },
      { status: 403 }
    );
  }

  return NextResponse.next();
}

このように、自然言語でやりたいことを書くだけで、実装が進みます。

テストフェーズ:AI によるテストコード生成

テストコードも、AI に任せられます。実装したコードを選択し、「このコードのテストを書いて」と指示するだけで、Jest や Vitest のテストコードが生成されます。

以下は、先ほどのミドルウェアのテストコード生成例です。

typescript// authMiddleware.test.ts

import { describe, it, expect, vi } from 'vitest';
import { authMiddleware } from './middleware';
import { verifyToken } from '@/lib/auth';
import { NextRequest } from 'next/server';

// verifyToken 関数をモック化
vi.mock('@/lib/auth');

ミドルウェアのテストケースを定義します。

typescriptdescribe('authMiddleware', () => {
  it('トークンがない場合は401を返す', async () => {
    const req = new NextRequest('http://localhost:3000/api/users');
    const res = await authMiddleware(req);

    expect(res.status).toBe(401);
    const json = await res.json();
    expect(json.error).toBe('認証トークンが必要です');
  });

トークンが無効な場合のテストも追加します。

typescriptit('トークンが無効な場合は403を返す', async () => {
  const req = new NextRequest(
    'http://localhost:3000/api/users',
    {
      headers: { authorization: 'Bearer invalid_token' },
    }
  );

  vi.mocked(verifyToken).mockResolvedValue(false);

  const res = await authMiddleware(req);
  expect(res.status).toBe(403);
});

トークンが有効な場合のテストも網羅します。

typescript  it('トークンが有効な場合は次の処理へ進む', async () => {
    const req = new NextRequest('http://localhost:3000/api/users', {
      headers: { authorization: 'Bearer valid_token' }
    });

    vi.mocked(verifyToken).mockResolvedValue(true);

    const res = await authMiddleware(req);
    expect(res).toBeUndefined(); // NextResponse.next() は undefined を返す
  });
});

このように、実装と同時にテストコードも AI が生成してくれるため、テスト駆動開発(TDD)のサイクルも回しやすくなります。

レビューフェーズ:AI による静的解析と提案

コードレビューでは、Cursor が「このコードに問題はないか」「改善点はないか」を自動で指摘してくれます。また、レビュアーが見落としがちなセキュリティリスクやパフォーマンス問題も、AI が検出してくれるため、レビューの質が向上します。

以下は、AI によるレビュー指摘の例です。

typescript// レビュー対象コード
export async function getUserData(userId: string) {
  const data = await fetch(
    `https://api.example.com/users/${userId}`
  );
  return data.json();
}

Cursor に「このコードをレビューして」と依頼すると、以下のような指摘が返ってきます。

typescript// AI のレビューコメント:
// 1. エラーハンドリングが不足しています
// 2. fetch が失敗した場合の処理を追加してください
// 3. レスポンスのステータスコードをチェックしましょう
// 4. 型安全性のために戻り値の型を明示してください

// 改善後のコード
export async function getUserData(
  userId: string
): Promise<User> {
  try {
    const response = await fetch(
      `https://api.example.com/users/${userId}`
    );

    if (!response.ok) {
      throw new Error(
        `HTTP error! status: ${response.status}`
      );
    }

    const data = await response.json();
    return data as User;
  } catch (error) {
    console.error(
      'ユーザーデータの取得に失敗しました:',
      error
    );
    throw error;
  }
}

このように、AI がレビュアーの視点でコードを改善してくれます。

以下の図は、Cursor × 生成 AI による開発フローの全体像を示します。

mermaidflowchart TD
  req_chat["要件定義<br/>(AI 対話で仕様整理)"] --> design_propose["設計<br/>(AI が構成提案)"]
  design_propose --> impl_gen["実装<br/>(コメント→コード生成)"]
  impl_gen --> test_auto["テスト<br/>(AI がテストコード生成)"]
  test_auto --> review_ai["レビュー<br/>(AI が指摘・改善提案)"]
  review_ai --> deploy_final["デプロイ"]

  impl_gen -->|コンテキスト保持| req_chat
  test_auto -->|即座にフィードバック| impl_gen
  review_ai -->|品質向上| impl_gen

図で理解できる要点

  • 要件定義から実装、テスト、レビューまで AI が一貫してサポート
  • コンテキストを保ったまま各フェーズをスムーズに移行
  • フィードバックループが短く、品質向上のサイクルが速い

具体例

実際のプロジェクトでの活用例

ここでは、Next.js を使った Web アプリケーション開発で、Cursor × 生成 AI を活用した具体例を紹介します。

ステップ 1:要件定義を対話で整理

プロジェクトの要件を Cursor のチャット機能で整理します。

typescript// Cursor チャット例
// ユーザー: 「ブログ投稿機能を作りたい。必要な機能をリストアップして。」

// AI の返答:
// 以下の機能が必要です。
// 1. 投稿一覧表示(GET /api/posts)
// 2. 投稿詳細表示(GET /api/posts/:id)
// 3. 新規投稿作成(POST /api/posts)
// 4. 投稿編集(PUT /api/posts/:id)
// 5. 投稿削除(DELETE /api/posts/:id)
// 6. マークダウン対応
// 7. タグ機能
// 8. 画像アップロード

この対話を通じて、必要な機能が明確になります。

ステップ 2:データモデルの設計

次に、データモデルを AI と一緒に設計します。

typescript// types/post.ts

// ブログ投稿のデータモデル
export interface Post {
  id: string;
  title: string;
  content: string; // マークダウン形式
  authorId: string;
  tags: string[];
  imageUrl?: string;
  createdAt: Date;
  updatedAt: Date;
  published: boolean;
}

AI に「このモデルで足りない項目はある?」と尋ねると、以下の提案が返ってきます。

typescript// AI の提案:
// - slug: SEO 用の URL フレンドリーな ID
// - excerpt: 記事の要約(一覧表示用)
// - viewCount: 閲覧数

export interface Post {
  id: string;
  slug: string; // 追加
  title: string;
  excerpt: string; // 追加
  content: string;
  authorId: string;
  tags: string[];
  imageUrl?: string;
  viewCount: number; // 追加
  createdAt: Date;
  updatedAt: Date;
  published: boolean;
}

このように、AI の提案を取り入れながらモデルを完成させます。

ステップ 3:API エンドポイントの実装

Next.js の App Router で API エンドポイントを実装します。

typescript// app/api/posts/route.ts

import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';

// 投稿一覧を取得する GET ハンドラ
export async function GET(req: NextRequest) {
  const posts = await prisma.post.findMany({
    where: { published: true },
    orderBy: { createdAt: 'desc' },
    include: {
      author: { select: { name: true, avatar: true } },
    },
  });

  return NextResponse.json(posts);
}

新規投稿を作成する POST ハンドラも追加します。

typescript// 新規投稿を作成する POST ハンドラ
export async function POST(req: NextRequest) {
  const body = await req.json();
  const { title, content, tags, authorId, imageUrl } = body;

  // バリデーション
  if (!title || !content || !authorId) {
    return NextResponse.json(
      { error: 'title, content, authorId は必須です' },
      { status: 400 }
    );
  }

  // slug を生成(タイトルから)
  const slug = title.toLowerCase().replace(/\s+/g, '-');

  const post = await prisma.post.create({
    data: {
      title,
      slug,
      content,
      tags,
      authorId,
      imageUrl,
      published: false, // デフォルトは非公開
      viewCount: 0,
    },
  });

  return NextResponse.json(post, { status: 201 });
}

このコードは、コメントで意図を書いた後、Cursor が自動生成したものです。

ステップ 4:フロントエンドの実装

投稿一覧を表示するページを実装します。

typescript// app/posts/page.tsx

import { Post } from '@/types/post';

// サーバーコンポーネントで投稿一覧を取得
async function getPosts(): Promise<Post[]> {
  const res = await fetch(
    'http://localhost:3000/api/posts',
    {
      cache: 'no-store', // 毎回最新データを取得
    }
  );

  if (!res.ok) {
    throw new Error('投稿一覧の取得に失敗しました');
  }

  return res.json();
}

投稿一覧を表示するコンポーネントを実装します。

typescriptexport default async function PostsPage() {
  const posts = await getPosts();

  return (
    <div className='container mx-auto px-4 py-8'>
      <h1 className='text-3xl font-bold mb-6'>
        ブログ記事一覧
      </h1>

      <div className='grid gap-6 md:grid-cols-2 lg:grid-cols-3'>
        {posts.map((post) => (
          <article
            key={post.id}
            className='border rounded-lg p-4 hover:shadow-lg transition'
          >
            {post.imageUrl && (
              <img
                src={post.imageUrl}
                alt={post.title}
                className='w-full h-48 object-cover rounded mb-4'
              />
            )}

            <h2 className='text-xl font-semibold mb-2'>
              {post.title}
            </h2>
            <p className='text-gray-600 mb-4'>
              {post.excerpt}
            </p>

            <div className='flex gap-2 mb-4'>
              {post.tags.map((tag) => (
                <span
                  key={tag}
                  className='bg-blue-100 text-blue-800 px-2 py-1 rounded text-sm'
                >
                  {tag}
                </span>
              ))}
            </div>

            <a
              href={`/posts/${post.slug}`}
              className='text-blue-600 hover:underline'
            >
              続きを読む →
            </a>
          </article>
        ))}
      </div>
    </div>
  );
}

このコードも、Cursor が Tailwind CSS を考慮して生成してくれたものです。

ステップ 5:テストコードの生成

API エンドポイントのテストを AI に生成してもらいます。

typescript// app/api/posts/route.test.ts

import { describe, it, expect, vi } from 'vitest';
import { GET, POST } from './route';
import { prisma } from '@/lib/prisma';
import { NextRequest } from 'next/server';

// Prisma をモック化
vi.mock('@/lib/prisma', () => ({
  prisma: {
    post: {
      findMany: vi.fn(),
      create: vi.fn(),
    },
  },
}));

GET エンドポイントのテストケースを追加します。

typescriptdescribe('GET /api/posts', () => {
  it('公開済み投稿の一覧を返す', async () => {
    const mockPosts = [
      { id: '1', title: 'テスト投稿1', published: true },
      { id: '2', title: 'テスト投稿2', published: true },
    ];

    vi.mocked(prisma.post.findMany).mockResolvedValue(
      mockPosts
    );

    const req = new NextRequest(
      'http://localhost:3000/api/posts'
    );
    const res = await GET(req);
    const json = await res.json();

    expect(json).toEqual(mockPosts);
  });
});

POST エンドポイントのテストケースも追加します。

typescriptdescribe('POST /api/posts', () => {
  it('必須項目が不足している場合は400を返す', async () => {
    const req = new NextRequest(
      'http://localhost:3000/api/posts',
      {
        method: 'POST',
        body: JSON.stringify({ title: 'テスト' }), // content と authorId が不足
      }
    );

    const res = await POST(req);
    expect(res.status).toBe(400);
  });

  it('正しいデータで投稿を作成する', async () => {
    const newPost = {
      title: 'テスト投稿',
      content: 'テスト内容',
      authorId: 'user123',
      tags: ['テスト'],
    };

    vi.mocked(prisma.post.create).mockResolvedValue({
      id: '1',
      slug: 'test-post',
      ...newPost,
      published: false,
      viewCount: 0,
      createdAt: new Date(),
      updatedAt: new Date(),
    });

    const req = new NextRequest(
      'http://localhost:3000/api/posts',
      {
        method: 'POST',
        body: JSON.stringify(newPost),
      }
    );

    const res = await POST(req);
    const json = await res.json();

    expect(res.status).toBe(201);
    expect(json.title).toBe('テスト投稿');
  });
});

このように、実装と並行してテストコードも生成できます。

ステップ 6:AI によるコードレビュー

最後に、Cursor に全体のコードをレビューしてもらいます。

typescript// AI のレビューコメント:
// 1. エラーハンドリングを強化してください
//    - prisma のクエリ失敗時の処理を追加
//    - fetch 失敗時のフォールバック UI を用意
// 2. セキュリティ対策を追加してください
//    - CSRF トークンの検証
//    - XSS 対策(マークダウンのサニタイズ)
// 3. パフォーマンス改善の提案
//    - 投稿一覧のページネーション
//    - 画像の遅延読み込み(lazy loading)
// 4. アクセシビリティの改善
//    - alt 属性の必須化
//    - キーボードナビゲーション対応

これらの指摘を受けて、コードを改善していきます。

以下の図は、今回の開発フローを時系列で示したものです。

mermaidsequenceDiagram
  actor Dev as 開発者
  participant Cursor as Cursor AI
  participant Code as コードベース

  Dev->>Cursor: 要件を相談
  Cursor->>Dev: 機能リスト提案

  Dev->>Cursor: データモデル設計依頼
  Cursor->>Dev: モデル定義+改善提案

  Dev->>Cursor: API 実装依頼
  Cursor->>Code: コード生成
  Code->>Dev: 実装完了

  Dev->>Cursor: テストコード生成依頼
  Cursor->>Code: テストコード生成

  Dev->>Cursor: コードレビュー依頼
  Cursor->>Dev: 改善点を指摘

  Dev->>Code: 修正反映
  Code->>Dev: 完成

図で理解できる要点

  • 開発者と AI が対話しながら進める
  • 各フェーズで AI がコードを生成・レビュー
  • フィードバックを即座に反映できる

開発時間の短縮効果

従来の開発フローでは、この規模の機能を実装するのに 2〜3 日かかることが多いですが、Cursor × 生成 AI を活用することで、以下のような時間短縮が実現できます。

| フェーズ | 従来 | AI 活用 | 短縮率 | | # | --- | --- | --- | | 1 | 要件定義 | 4 時間 | 1 時間 | ★★★ | | 2 | 設計 | 4 時間 | 1.5 時間 | ★★ | | 3 | 実装 | 8 時間 | 3 時間 | ★★★ | | 4 | テスト作成 | 4 時間 | 1 時間 | ★★★ | | 5 | レビュー | 2 時間 | 0.5 時間 | ★★ | | 6 | 合計 | 22 時間 | 7 時間 | ★★★ |

このように、全体で約 68% の時間短縮が可能になります。

まとめ

Cursor × 生成 AI の組み合わせは、開発フローの「すべてのフェーズ」に影響を与えます。要件定義では対話を通じて仕様を明確化し、設計では AI の提案を受けながらアーキテクチャを決定できます。実装ではコンテキストを保ったままコードを生成し、テストコードも同時に作成することで、品質を担保しながら開発スピードを上げられるのです。

そして、レビューフェーズでは AI が静的解析を行い、セキュリティリスクやパフォーマンス問題を指摘してくれるため、レビューの質が向上します。これまでのように「レビュアーのスキルに依存する」状況から脱却し、誰でも一定水準以上のレビューを受けられるようになるのです。

もちろん、AI がすべてを完璧にこなすわけではありません。最終的な判断は人間が行う必要がありますし、ドメイン知識やビジネスロジックは開発者自身が理解していなければなりません。しかし、AI を「開発パートナー」として活用することで、より創造的な部分に時間を使えるようになるでしょう。

Cursor × 生成 AI がもたらす開発フローの変化は、単なる「効率化」ではなく、開発者の働き方そのものを変える可能性を秘めています。ぜひ、あなたのプロジェクトでも試してみてください。

関連リンク