T-CREATOR

Cline 中心の開発プロセス設計:要求 → 設計 → 実装 → 検証の最短動線

Cline 中心の開発プロセス設計:要求 → 設計 → 実装 → 検証の最短動線

AI による開発支援ツールが次々と登場する中、Cline は「要求から検証まで」の全プロセスを一貫してサポートできる点で注目を集めています。プロジェクトの初期段階から最終検証まで、開発者が本来集中すべき価値創出に専念できる環境を提供してくれるのです。

本記事では、Cline を中心に据えた開発プロセスの設計方法と、要求定義から設計、実装、検証までの最短動線を構築する実践的なアプローチを解説します。

背景

従来の開発プロセスにおける課題

従来のソフトウェア開発では、要求定義、設計、実装、検証という各フェーズが独立しており、フェーズ間の情報伝達にコストがかかっていました。要求仕様書を作成し、設計書に落とし込み、実装してテストする、という流れでは、各段階でのコンテキストスイッチが発生し、開発速度が低下していたのです。

また、AI コーディングアシスタントの登場により、実装速度は飛躍的に向上しましたが、要求理解や設計判断、検証の自動化といった上流・下流工程との連携が課題として残っていました。

Cline の登場とその特徴

Cline は、VS Code をはじめとする統合開発環境に組み込まれる AI エージェント型のコーディングアシスタントです。単なるコード補完ツールではなく、以下の特徴を持っています。

#特徴説明
1Plan/Act モードコード実装前にプロジェクト全体を理解し、計画を立案
2透明性の確保すべての変更を開発者がレビュー・承認可能
3マルチモデル対応Claude、OpenAI、OpenRouter など複数の AI モデルをサポート
4ターミナル統合コマンド実行、ファイル編集、ブラウザ自動化まで一貫対応
5セキュリティ重視クライアントサイド実行でコードが外部サーバーに送信されない

これらの特徴により、Cline は開発プロセス全体を通じた一貫したサポートが可能になっています。

以下の図は、Cline のアーキテクチャ概要を示しています。

mermaidflowchart TB
  dev["開発者"] -->|要求入力| cline["Cline エージェント"]
  cline -->|コンテキスト分析| ast["AST 解析"]
  cline -->|計画立案| plan["Plan モード"]
  cline -->|実装実行| act["Act モード"]

  act -->|ファイル操作| files["ファイル編集"]
  act -->|コマンド実行| terminal["ターミナル"]
  act -->|UI テスト| browser["ブラウザ自動化"]

  files --> review["変更レビュー"]
  terminal --> review
  browser --> review

  review -->|承認/拒否| dev

この図から、Cline が要求を受け取り、計画を立て、実装し、開発者にレビューを促すという一連のフローが確認できます。

課題

開発プロセスにおける分断

従来の開発現場では、以下のような分断が発生していました。

1. 要求と設計の分断

要求定義書に記載された内容が、設計段階で技術的制約により大きく変更されるケースが頻発します。その結果、当初の要求意図が失われたり、仕様変更のたびに要求定義書を更新する手間が発生していました。

2. 設計と実装の分断

設計書に記載されたアーキテクチャやクラス図が、実装段階で「実現困難」「パフォーマンス問題」などの理由で変更されることがあります。こうした変更は設計書に反映されず、ドキュメントと実装の乖離が進んでいきます。

3. 実装と検証の分断

実装完了後、テストフェーズで初めて不具合が発見され、大規模な修正が必要になるケースも少なくありません。これは、実装中にリアルタイムでの検証が行われていないことが原因です。

以下の図は、従来の開発プロセスにおける課題を可視化したものです。

mermaidflowchart LR
  req["要求定義"] -->|文書化| design["設計"]
  design -->|仕様書| impl["実装"]
  impl -->|完成後| test["検証"]

  req -.->|意図が伝わらない| design
  design -.->|乖離が発生| impl
  impl -.->|後戻りコスト大| test

  style req fill:#ffcccc
  style design fill:#ffcccc
  style impl fill:#ffcccc
  style test fill:#ffcccc

この図から、各フェーズ間での情報伝達のロスや後戻りコストが見て取れます。

AI ツール単体では解決できない問題

AI コーディングアシスタントは実装を高速化しますが、以下の問題は解決できませんでした。

#問題詳細
1要求理解の浅さプロンプトベースの指示では、複雑なビジネス要求を正確に伝えられない
2設計意図の欠如コード生成は得意だが、アーキテクチャ全体を考慮した設計提案は苦手
3検証の不完全性生成されたコードが動作するかどうかを開発者が手動で確認する必要がある

これらの問題を解決するには、AI ツールを単独で使うのではなく、開発プロセス全体を見直し、AI をプロセスの中心に据える必要があります。

解決策

Cline を軸とした統合開発プロセス

Cline を中心に据えることで、要求から検証までを一貫して管理できる開発プロセスを構築できます。ポイントは、以下の 4 つのフェーズを シームレスに接続 することです。

統合プロセスの全体像

以下の図は、Cline を中心とした統合開発プロセスの全体像を示しています。

mermaidflowchart TB
  req_start["要求定義"] --> plan_phase["設計・計画"]
  plan_phase --> impl_phase["実装"]
  impl_phase --> verify_phase["検証"]
  verify_phase -->|フィードバック| req_start

  subgraph cline_core["Cline コア"]
    context["コンテキスト管理"]
    agent["エージェント実行"]
    review["変更レビュー"]
  end

  req_start -.->|要求を理解| context
  context -.->|計画を立案| plan_phase
  plan_phase -.->|コード生成| agent
  agent -.->|変更を提案| impl_phase
  impl_phase -.->|承認プロセス| review
  review -.->|自動検証| verify_phase

この図から、Cline がすべてのフェーズで一貫してコンテキストを管理し、各フェーズ間のギャップを埋めていることがわかります。

フェーズ 1:要求定義の構造化

Cline を活用した要求定義では、自然言語での対話を通じて要求を構造化していきます。

要求の入力方法

Cline に対して、以下のような形式で要求を伝えます。

typescript// Cline への要求入力例
/**
 * 要求:ユーザー認証機能の追加
 *
 * 背景:
 * - 現在のシステムには認証機能がない
 * - セキュリティ強化のため JWT ベースの認証を導入したい
 *
 * 要件:
 * - ユーザー登録・ログイン・ログアウト機能
 * - JWT トークンによる認証
 * - リフレッシュトークン機能
 * - パスワードのハッシュ化(bcrypt 使用)
 */

このように要求を構造化することで、Cline は要求の背景、制約、期待される成果物を正確に理解できます。

Cline による要求の分析

Cline は入力された要求を分析し、以下の情報を抽出します。

typescript// Cline が抽出する要求情報
interface RequirementAnalysis {
  // 機能名
  featureName: string;

  // ビジネス価値
  businessValue: string;

  // 技術的制約
  technicalConstraints: string[];

  // 依存関係
  dependencies: string[];

  // リスク要因
  risks: string[];
}

この分析結果をもとに、Cline は次の設計フェーズに必要な情報を準備します。

フェーズ 2:設計・計画の自動化

Cline の Plan モード を活用することで、実装前に全体設計を可視化できます。

Plan モードの起動

Plan モードでは、Cline がプロジェクト全体を分析し、実装計画を立案します。

typescript// Plan モードでの分析対象
interface PlanAnalysis {
  // プロジェクト構造の把握
  projectStructure: {
    directories: string[];
    keyFiles: string[];
    dependencies: Record<string, string>;
  };

  // AST 解析による既存コードの理解
  codeAnalysis: {
    functions: FunctionSignature[];
    classes: ClassDefinition[];
    imports: ImportStatement[];
  };

  // 変更影響範囲の特定
  impactAnalysis: {
    filesToModify: string[];
    filesToCreate: string[];
    potentialConflicts: string[];
  };
}

Cline は AST(抽象構文木)解析を通じて、既存コードの構造を深く理解し、変更が必要なファイルや新規作成すべきファイルを特定します。

設計の可視化

Cline が生成する実装計画には、以下の要素が含まれます。

#要素説明
1アーキテクチャ設計ディレクトリ構造、モジュール分割、依存関係
2API 設計エンドポイント定義、リクエスト/レスポンス形式
3データモデル設計データベーススキーマ、型定義
4実装手順ステップバイステップの実装ガイド

以下は、Cline が生成する実装計画の例です。

typescript// Cline が生成する実装計画
interface ImplementationPlan {
  // ステップごとの作業内容
  steps: Array<{
    order: number;
    description: string;
    files: string[];
    dependencies: number[]; // 先行ステップの番号
  }>;

  // 推定所要時間
  estimatedTime: {
    development: number; // 分単位
    testing: number;
    review: number;
  };

  // リスク評価
  risks: Array<{
    description: string;
    severity: 'low' | 'medium' | 'high';
    mitigation: string;
  }>;
}

この計画を開発者がレビューし、承認することで、次の実装フェーズに進みます。

フェーズ 3:実装の自動化と承認フロー

Cline の Act モード では、立案された計画に基づいて実装を進めます。重要なのは、すべての変更が開発者の承認を経て適用される点です。

Act モードの実行フロー

以下の図は、Act モードにおける実装フローを示しています。

mermaidsequenceDiagram
  participant Dev as 開発者
  participant Cline as Cline
  participant FS as ファイルシステム
  participant Term as ターミナル

  Dev->>Cline: 実装指示
  Cline->>Cline: 計画に基づく実装コード生成
  Cline->>Dev: 変更内容の提示
  Dev->>Cline: 承認 or 修正指示

  alt 承認された場合
    Cline->>FS: ファイル編集実行
    Cline->>Term: 必要なコマンド実行
    Cline->>Dev: 実行結果報告
  else 修正指示の場合
    Cline->>Cline: コード再生成
    Cline->>Dev: 修正版提示
  end

このフローにより、AI が生成したコードが無条件で適用されることはなく、開発者が常にコントロールを維持できます。

ファイル編集の実行

Cline はファイル編集時に、以下のような安全性確保の仕組みを持っています。

typescript// Cline のファイル編集機能
interface FileEditOperation {
  // 編集対象ファイル
  targetFile: string;

  // 変更内容
  changes: Array<{
    type: 'create' | 'modify' | 'delete';
    lineStart: number;
    lineEnd: number;
    newContent: string;
  }>;

  // バックアップ情報
  backup: {
    enabled: boolean;
    restorePoint: string;
  };

  // リンター/コンパイラエラーの監視
  errorMonitoring: {
    enabled: boolean;
    autoRollback: boolean;
  };
}

Cline は変更後にリンターやコンパイラのエラーを監視し、問題が発生した場合は自動的にロールバックすることも可能です。

ターミナルコマンドの実行

実装に伴うパッケージインストールやビルドコマンドも、Cline が自動実行します。

typescript// ターミナルコマンド実行の例
interface TerminalExecution {
  // 実行するコマンド
  command: string;

  // 実行ディレクトリ
  workingDirectory: string;

  // 環境変数
  env: Record<string, string>;

  // タイムアウト設定
  timeout: number;

  // 実行結果の取得
  result: {
    stdout: string;
    stderr: string;
    exitCode: number;
  };
}

以下は、Cline がターミナルコマンドを実行する際の具体例です。

bash# パッケージのインストール
yarn add jsonwebtoken bcrypt

# 型定義のインストール
yarn add -D @types/jsonwebtoken @types/bcrypt

# データベースマイグレーション
yarn prisma migrate dev --name add_user_auth

これらのコマンドも、実行前に開発者に確認を求めます。

フェーズ 4:検証の自動化

実装完了後、Cline はブラウザ自動化機能を使って動作確認を行います。

ブラウザ自動化による E2E テスト

Cline は Playwright などのツールと連携し、実装した機能の動作を自動検証できます。

typescript// ブラウザ自動化テストの例
interface BrowserAutomation {
  // テストシナリオ
  scenario: Array<{
    step: number;
    action: 'navigate' | 'click' | 'input' | 'assert';
    target: string;
    value?: string;
    expected?: string;
  }>;

  // スクリーンショット取得
  screenshots: {
    enabled: boolean;
    path: string;
  };

  // テスト結果
  result: {
    passed: boolean;
    failures: string[];
  };
}

以下は、ユーザー認証機能のテストシナリオ例です。

typescript// 認証機能のテストシナリオ
const authTestScenario = [
  {
    step: 1,
    action: 'navigate',
    target: 'http://localhost:3000/signup',
  },
  {
    step: 2,
    action: 'input',
    target: '#email',
    value: 'test@example.com',
  },
  {
    step: 3,
    action: 'input',
    target: '#password',
    value: 'SecurePass123!',
  },
  {
    step: 4,
    action: 'click',
    target: '#signup-button',
  },
  {
    step: 5,
    action: 'assert',
    target: '#success-message',
    expected: 'アカウントが作成されました',
  },
];

このテストシナリオを Cline が自動実行し、結果を開発者に報告します。

リアルタイムエラー検出

Cline はリンターやコンパイラのエラーを監視し、問題を即座に報告します。

typescript// エラー監視の仕組み
interface ErrorMonitoring {
  // 監視対象
  targets: Array<{
    type: 'linter' | 'compiler' | 'test';
    command: string;
  }>;

  // 検出されたエラー
  errors: Array<{
    file: string;
    line: number;
    column: number;
    message: string;
    severity: 'error' | 'warning' | 'info';
  }>;

  // 自動修正の提案
  autoFixSuggestions: Array<{
    error: string;
    fix: string;
  }>;
}

エラーが検出された場合、Cline は自動修正の提案も行います。

typescript// 自動修正提案の例
const autoFixExample = {
  error: 'Missing semicolon at line 42',
  fix: 'Add semicolon at the end of the statement',
  code: `
    // 修正前
    const result = await authenticateUser(email, password)

    // 修正後
    const result = await authenticateUser(email, password);
  `,
};

開発者はこの提案を承認するだけで、エラーを即座に修正できます。

継続的フィードバックループ

検証結果は次の要求定義にフィードバックされ、継続的な改善サイクルを形成します。

以下の図は、フィードバックループの全体像を示しています。

mermaidflowchart LR
  verify["検証結果"] -->|合格| release["リリース"]
  verify -->|不合格| analysis["原因分析"]
  analysis -->|要求の見直し| req["要求定義"]
  analysis -->|設計の見直し| plan["設計・計画"]
  analysis -->|実装の修正| impl["実装"]

  req --> plan
  plan --> impl
  impl --> verify

この図から、検証で問題が見つかった場合、適切なフェーズに戻って修正が行われることがわかります。

具体例

ここでは、実際に Cline を使って「ユーザー認証機能」を実装する具体例を紹介します。

ステップ 1:要求定義

開発者は Cline に対して、以下のような要求を入力します。

typescript/**
 * 機能:JWT ベースのユーザー認証機能
 *
 * 背景:
 * - Next.js で構築された Web アプリケーションに認証機能を追加
 * - 既存の PostgreSQL データベースにユーザーテーブルを追加
 *
 * 要件:
 * 1. ユーザー登録機能
 *    - メールアドレスとパスワードで登録
 *    - パスワードは bcrypt でハッシュ化
 *
 * 2. ログイン機能
 *    - メールアドレスとパスワードで認証
 *    - JWT アクセストークン(有効期限 15 分)を発行
 *    - JWT リフレッシュトークン(有効期限 7 日)を発行
 *
 * 3. ログアウト機能
 *    - クライアント側でトークンを削除
 *
 * 4. 保護されたエンドポイント
 *    - /api/profile は認証が必要
 *
 * 技術スタック:
 * - Next.js 14 (App Router)
 * - TypeScript
 * - Prisma (ORM)
 * - PostgreSQL
 * - jsonwebtoken
 * - bcrypt
 */

この要求を Cline が受け取ります。

ステップ 2:設計・計画

Cline は Plan モードで以下のような実装計画を生成します。

typescript// Cline が生成する実装計画
const implementationPlan = {
  steps: [
    {
      order: 1,
      description: 'Prisma スキーマにユーザーモデルを追加',
      files: ['prisma/schema.prisma'],
      dependencies: [],
    },
    {
      order: 2,
      description: 'データベースマイグレーションを実行',
      files: ['prisma/migrations/'],
      dependencies: [1],
    },
    {
      order: 3,
      description: '認証ユーティリティ関数を作成',
      files: [
        'src/lib/auth/hash.ts',
        'src/lib/auth/jwt.ts',
        'src/lib/auth/validate.ts',
      ],
      dependencies: [],
    },
    {
      order: 4,
      description: 'ユーザー登録 API エンドポイントを実装',
      files: ['src/app/api/auth/signup/route.ts'],
      dependencies: [2, 3],
    },
    {
      order: 5,
      description: 'ログイン API エンドポイントを実装',
      files: ['src/app/api/auth/login/route.ts'],
      dependencies: [2, 3],
    },
    {
      order: 6,
      description: 'トークンリフレッシュ API を実装',
      files: ['src/app/api/auth/refresh/route.ts'],
      dependencies: [2, 3],
    },
    {
      order: 7,
      description: '認証ミドルウェアを実装',
      files: ['src/middleware/auth.ts'],
      dependencies: [3],
    },
    {
      order: 8,
      description: '保護されたエンドポイントを実装',
      files: ['src/app/api/profile/route.ts'],
      dependencies: [7],
    },
  ],
  estimatedTime: {
    development: 120, // 2 時間
    testing: 30, // 30 分
    review: 15, // 15 分
  },
  risks: [
    {
      description: 'JWT シークレットキーの管理',
      severity: 'high',
      mitigation: '環境変数で管理し、.env.example に記載',
    },
    {
      description: 'パスワードポリシーの実装',
      severity: 'medium',
      mitigation:
        '最小文字数、複雑さをバリデーションで確保',
    },
  ],
};

開発者はこの計画をレビューし、承認します。

ステップ 3:実装

Cline は Act モードで実装を開始します。以下は実装の各ステップです。

ステップ 3-1:Prisma スキーマの定義

まず、ユーザーモデルをデータベーススキーマに追加します。

prisma// prisma/schema.prisma

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

// ユーザーモデルの追加
model User {
  id            String   @id @default(uuid())
  email         String   @unique
  passwordHash  String
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
}

このスキーマ定義により、ユーザー情報を格納するテーブル構造が決まります。

ステップ 3-2:マイグレーションの実行

Cline はターミナルで以下のコマンドを実行します。

bash# データベースマイグレーションを実行
yarn prisma migrate dev --name add_user_model

# Prisma Client を生成
yarn prisma generate

これにより、データベースにユーザーテーブルが作成されます。

ステップ 3-3:認証ユーティリティの実装

次に、パスワードハッシュ化と JWT 生成の関数を実装します。

typescript// src/lib/auth/hash.ts

import bcrypt from 'bcrypt';

// パスワードをハッシュ化する
export async function hashPassword(
  password: string
): Promise<string> {
  const saltRounds = 10;
  return bcrypt.hash(password, saltRounds);
}

// パスワードを検証する
export async function verifyPassword(
  password: string,
  hash: string
): Promise<boolean> {
  return bcrypt.compare(password, hash);
}

パスワードのハッシュ化には bcrypt を使用し、安全性を確保します。

typescript// src/lib/auth/jwt.ts

import jwt from 'jsonwebtoken';

// JWT シークレットキー(環境変数から取得)
const JWT_SECRET =
  process.env.JWT_SECRET || 'fallback-secret';
const REFRESH_SECRET =
  process.env.REFRESH_SECRET || 'fallback-refresh-secret';

// JWT ペイロードの型定義
interface JWTPayload {
  userId: string;
  email: string;
}

// アクセストークンを生成(有効期限 15 分)
export function generateAccessToken(
  payload: JWTPayload
): string {
  return jwt.sign(payload, JWT_SECRET, {
    expiresIn: '15m',
  });
}

// リフレッシュトークンを生成(有効期限 7 日)
export function generateRefreshToken(
  payload: JWTPayload
): string {
  return jwt.sign(payload, REFRESH_SECRET, {
    expiresIn: '7d',
  });
}

JWT トークンの生成関数では、アクセストークンとリフレッシュトークンで異なるシークレットキーと有効期限を設定しています。

typescript// src/lib/auth/jwt.ts(続き)

// アクセストークンを検証
export function verifyAccessToken(
  token: string
): JWTPayload | null {
  try {
    return jwt.verify(token, JWT_SECRET) as JWTPayload;
  } catch (error) {
    return null;
  }
}

// リフレッシュトークンを検証
export function verifyRefreshToken(
  token: string
): JWTPayload | null {
  try {
    return jwt.verify(token, REFRESH_SECRET) as JWTPayload;
  } catch (error) {
    return null;
  }
}

トークン検証関数は、期限切れや不正なトークンを検出します。

ステップ 3-4:ユーザー登録 API の実装

ユーザー登録エンドポイントを実装します。

typescript// src/app/api/auth/signup/route.ts

import { NextRequest, NextResponse } from "next/server";
import { PrismaClient } from "@prisma/client";
import { hashPassword } from "@/lib/auth/hash";

const prisma = new PrismaClient();

// POST /api/auth/signup
export async function POST(request: NextRequest) {
  try {
    // リクエストボディを取得
    const { email, password } = await request.json();

    // バリデーション
    if (!email || !password) {
      return NextResponse.json(
        { error: "メールアドレスとパスワードは必須です" },
        { status: 400 }
      );
    }

    // パスワードの強度チェック
    if (password.length < 8) {
      return NextResponse.json(
        { error: "パスワードは 8 文字以上である必要があります" },
        { status: 400 }
      );
    }

リクエストの検証を行い、必須項目やパスワード強度をチェックします。

typescript// src/app/api/auth/signup/route.ts(続き)

    // 既存ユーザーのチェック
    const existingUser = await prisma.user.findUnique({
      where: { email },
    });

    if (existingUser) {
      return NextResponse.json(
        { error: "このメールアドレスは既に登録されています" },
        { status: 409 }
      );
    }

    // パスワードをハッシュ化
    const passwordHash = await hashPassword(password);

    // ユーザーを作成
    const user = await prisma.user.create({
      data: {
        email,
        passwordHash,
      },
    });

    // レスポンス(パスワードハッシュは含めない)
    return NextResponse.json(
      {
        message: "ユーザー登録が完了しました",
        user: {
          id: user.id,
          email: user.email,
        },
      },
      { status: 201 }
    );
  } catch (error) {
    console.error("ユーザー登録エラー:", error);
    return NextResponse.json(
      { error: "サーバーエラーが発生しました" },
      { status: 500 }
    );
  }
}

ユーザー作成後、パスワードハッシュを含まない安全なレスポンスを返します。

ステップ 3-5:ログイン API の実装

ログインエンドポイントを実装します。

typescript// src/app/api/auth/login/route.ts

import { NextRequest, NextResponse } from "next/server";
import { PrismaClient } from "@prisma/client";
import { verifyPassword } from "@/lib/auth/hash";
import { generateAccessToken, generateRefreshToken } from "@/lib/auth/jwt";

const prisma = new PrismaClient();

// POST /api/auth/login
export async function POST(request: NextRequest) {
  try {
    // リクエストボディを取得
    const { email, password } = await request.json();

    // バリデーション
    if (!email || !password) {
      return NextResponse.json(
        { error: "メールアドレスとパスワードは必須です" },
        { status: 400 }
      );
    }

    // ユーザーを検索
    const user = await prisma.user.findUnique({
      where: { email },
    });

    if (!user) {
      return NextResponse.json(
        { error: "メールアドレスまたはパスワードが正しくありません" },
        { status: 401 }
      );
    }

ユーザーが存在しない場合も、詳細なエラーメッセージを返さず、セキュリティを確保します。

typescript// src/app/api/auth/login/route.ts(続き)

    // パスワードを検証
    const isPasswordValid = await verifyPassword(password, user.passwordHash);

    if (!isPasswordValid) {
      return NextResponse.json(
        { error: "メールアドレスまたはパスワードが正しくありません" },
        { status: 401 }
      );
    }

    // JWT トークンを生成
    const payload = {
      userId: user.id,
      email: user.email,
    };

    const accessToken = generateAccessToken(payload);
    const refreshToken = generateRefreshToken(payload);

    // レスポンス
    return NextResponse.json(
      {
        message: "ログインに成功しました",
        accessToken,
        refreshToken,
        user: {
          id: user.id,
          email: user.email,
        },
      },
      { status: 200 }
    );
  } catch (error) {
    console.error("ログインエラー:", error);
    return NextResponse.json(
      { error: "サーバーエラーが発生しました" },
      { status: 500 }
    );
  }
}

ログイン成功時には、アクセストークンとリフレッシュトークンの両方を返します。

ステップ 3-6:認証ミドルウェアの実装

保護されたエンドポイントで使用する認証ミドルウェアを実装します。

typescript// src/middleware/auth.ts

import { NextRequest, NextResponse } from 'next/server';
import { verifyAccessToken } from '@/lib/auth/jwt';

// 認証ミドルウェア
export function authMiddleware(request: NextRequest) {
  // Authorization ヘッダーを取得
  const authHeader = request.headers.get('Authorization');

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

  // トークンを抽出
  const token = authHeader.substring(7);

  // トークンを検証
  const payload = verifyAccessToken(token);

  if (!payload) {
    return NextResponse.json(
      { error: '無効または期限切れのトークンです' },
      { status: 401 }
    );
  }

  // ユーザー情報をヘッダーに追加して次の処理に渡す
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('X-User-Id', payload.userId);
  requestHeaders.set('X-User-Email', payload.email);

  return NextResponse.next({
    request: {
      headers: requestHeaders,
    },
  });
}

このミドルウェアは、トークンを検証し、ユーザー情報をリクエストヘッダーに追加します。

ステップ 3-7:保護されたエンドポイントの実装

認証が必要なプロフィール取得エンドポイントを実装します。

typescript// src/app/api/profile/route.ts

import { NextRequest, NextResponse } from 'next/server';
import { PrismaClient } from '@prisma/client';
import { authMiddleware } from '@/middleware/auth';

const prisma = new PrismaClient();

// GET /api/profile
export async function GET(request: NextRequest) {
  // 認証ミドルウェアを実行
  const authResult = authMiddleware(request);
  if (authResult.status !== 200) {
    return authResult;
  }

  try {
    // ミドルウェアが追加したユーザー ID を取得
    const userId = request.headers.get('X-User-Id');

    if (!userId) {
      return NextResponse.json(
        { error: 'ユーザー情報が取得できません' },
        { status: 401 }
      );
    }

    // ユーザー情報を取得
    const user = await prisma.user.findUnique({
      where: { id: userId },
      select: {
        id: true,
        email: true,
        createdAt: true,
        updatedAt: true,
      },
    });

    if (!user) {
      return NextResponse.json(
        { error: 'ユーザーが見つかりません' },
        { status: 404 }
      );
    }

    return NextResponse.json({ user }, { status: 200 });
  } catch (error) {
    console.error('プロフィール取得エラー:', error);
    return NextResponse.json(
      { error: 'サーバーエラーが発生しました' },
      { status: 500 }
    );
  }
}

認証ミドルウェアを通過したリクエストのみが、ユーザープロフィール情報を取得できます。

ステップ 4:検証

実装が完了したら、Cline はブラウザ自動化でテストを実行します。

テストシナリオの実行

Cline は以下のテストシナリオを自動実行します。

typescript// テストシナリオ
const testScenarios = [
  {
    name: 'ユーザー登録テスト',
    steps: [
      {
        action: 'POST',
        url: 'http://localhost:3000/api/auth/signup',
        body: {
          email: 'test@example.com',
          password: 'SecurePass123!',
        },
        expectedStatus: 201,
      },
    ],
  },
  {
    name: 'ログインテスト',
    steps: [
      {
        action: 'POST',
        url: 'http://localhost:3000/api/auth/login',
        body: {
          email: 'test@example.com',
          password: 'SecurePass123!',
        },
        expectedStatus: 200,
      },
    ],
  },
  {
    name: '保護されたエンドポイントテスト',
    steps: [
      {
        action: 'GET',
        url: 'http://localhost:3000/api/profile',
        headers: {
          Authorization: 'Bearer <access_token>',
        },
        expectedStatus: 200,
      },
    ],
  },
];

これらのテストが自動実行され、結果が報告されます。

テスト結果の確認

Cline は以下のようなテスト結果を報告します。

typescript// テスト結果
const testResults = {
  summary: {
    total: 3,
    passed: 3,
    failed: 0,
  },
  details: [
    {
      name: 'ユーザー登録テスト',
      status: 'passed',
      duration: 234, // ms
    },
    {
      name: 'ログインテスト',
      status: 'passed',
      duration: 198,
    },
    {
      name: '保護されたエンドポイントテスト',
      status: 'passed',
      duration: 156,
    },
  ],
};

すべてのテストが成功したことが確認できました。

開発プロセスの可視化

以下の図は、今回の実装プロセス全体を可視化したものです。

mermaidflowchart TB
  req["要求定義<br/>JWT 認証機能"] --> plan["設計・計画<br/>8 ステップの計画"]
  plan --> impl1["実装 1<br/>Prisma スキーマ"]
  impl1 --> impl2["実装 2<br/>マイグレーション"]
  impl2 --> impl3["実装 3<br/>認証ユーティリティ"]
  impl3 --> impl4["実装 4<br/>API エンドポイント"]
  impl4 --> verify["検証<br/>自動テスト実行"]
  verify -->|合格| done["完了"]

  style req fill:#e1f5ff
  style plan fill:#fff4e1
  style impl1 fill:#e8f5e9
  style impl2 fill:#e8f5e9
  style impl3 fill:#e8f5e9
  style impl4 fill:#e8f5e9
  style verify fill:#f3e5f5
  style done fill:#c8e6c9

この図から、要求定義から完了までのスムーズな流れが確認できます。

まとめ

Cline を中心に据えた開発プロセスは、要求から検証までを一貫して管理し、以下のメリットをもたらします。

#メリット詳細
1開発速度の向上Plan/Act モードにより、設計と実装がシームレスに連携
2品質の確保すべての変更を開発者がレビューし、自動テストで検証
3コンテキストの維持要求から検証まで一貫したコンテキストで開発
4安全性の確保クライアントサイド実行でコードが外部に送信されない
5フィードバックの高速化リアルタイムエラー検出と自動修正提案

従来の開発プロセスでは、各フェーズ間の情報伝達にコストがかかり、後戻りが頻発していました。Cline を活用することで、これらの課題を解決し、開発者が本来の価値創出に集中できる環境が実現します。

今後、AI エージェントを中心とした開発プロセスはさらに進化し、より高度な設計判断や自動最適化が可能になっていくでしょう。Cline はその先駆けとして、開発現場に新しい可能性をもたらしています。

関連リンク