「Cloudflare Workers Tech Talks in Fukuoka #1」登壇レポート 〜 Honoを技術選定したAI要件定義プラットフォームAcsimでの意思決定

重岡 正 ·  Wed, November 12, 2025

福岡で開催されたコミュニティイベント「Cloudflare Workers Tech Talks in Fukuoka #1」に登壇する機会をいただきました。

本記事では、当日の発表内容について、資料と共に共有します。

登壇内容

以下、当日の登壇資料 Honoを技術選定したAI要件定義プラットフォームAcsimでの意思決定 から一部抜粋します。

🎯 発表概要

AI要件定義プラットフォーム Acsim の開発において、Hono + @hono/zod-openapi を採用した理由と、それがもたらした開発体験について紹介しました。

OpenAPIを活用したスキーマ駆動開発により以下を実現👇

  • Frontend・API間の型情報共有と実装速度の向上
  • コンパイル時・実行時の両面での型安全性確保
  • TanStack Queryとの高い親和性による開発体験の向上

背景: 課題の整理

解決したかった課題

  • Frontend・API間の実装速度の向上

    • 実装の一貫性を保ちたい
    • 開発体験を改善したい
  • 型情報の共有による品質向上

    • 型不一致によるバグを防ぎたい
    • リファクタリングを安全にしたい

決定: OpenAPIを使ったスキーマ駆動開発

アーキテクチャ

API (Hono + @hono/zod-openapi)
    ↓
OpenAPI Schema 生成
    ↓
Frontend (orval)
    ↓
型情報 + TanStack Query Client 生成

なぜHonoか: @hono/zod-openapi の選定理由

1. TypeScriptネイティブな記述

const route = createRoute({
  method: 'post',
  path: '/users',
  request: { body: { content: { 'application/json': { schema: UserSchema } } } },
  responses: { 200: { content: { 'application/json': { schema: UserSchema } } } }
});
  • YAML/JSONではなくTypeScriptで記述可能
  • 学習コストが低い

2. Honoとの高い親和性

  • Honoの開発者が作成したライブラリ
  • Honoのミドルウェアとシームレスに統合
  • フレームワークとスキーマ定義が一体化

3. 言語非依存の拡張性

  • OpenAPIは統一規格
  • 将来的に別言語へ移行する際も活用可能

なぜorvalか: Frontend側のコード生成

TanStack Queryとの親和性

// 自動生成されたコード
export const useGetUsers = () => {
  return useQuery({
    queryKey: ['users'],
    queryFn: () => getUsersApi(),
  });
};
  • TanStack Query用のhooksを自動生成
  • Query Key管理を自動化
  • リクエスト処理を簡略化

他の選択肢との比較

検討した選択肢

方式採用理由
orvalでAPI/Frontend両方生成Middlewareの差し込みが困難
openapi-generatorTanStack Queryとの連携で設定量が多い
@hono/zod-openapi + orval学習コスト・親和性が最適

メリット: 得られた開発体験

1. 型安全性の確保

  • Frontend・API間の型不一致を防止
  • コンパイル時にエラーを検出

2. 開発速度の向上

  • APIクライアントコードの自動生成
  • ボイラープレートの削減

3. 保守性の向上

  • Query Key管理の自動化
  • 一貫性のあるコードベース

デメリット: トレードオフ

運用上のコスト

  • API変更時にOpenAPI Schemaの更新が必要

    • 自動生成の仕組みで軽減
  • OpenAPI Schemaの記述コスト

    • TypeScriptで記述できるため学習コストは低い
  • orvalの設定コスト

    • 初期設定は必要だが、一度設定すれば再利用可能

実践例: レスポンススキーマバリデーションミドルウェア

背景と課題

フロントエンドとAPI間は型定義により型安全性が保証されているが、バックエンド側のレスポンスには問題がありました:

  • 型チェックの限界: TypeScriptの型は必要なプロパティの存在のみをチェックし、余分なプロパティを検出できない
  • セキュリティリスク: パスワードなどの機密情報を誤ってレスポンスに含めてもコンパイルエラーにならない
  • レビューだけでは不十分: 人的チェックだけで防ぐのは困難かつ影響度が大きい

解決策

実行時にZodスキーマでレスポンスをパースすることで:

  1. 型定義に含まれないプロパティを自動的に除外
  2. 機密情報の誤送信を防止
  3. レスポンスの形式を保証

使い方

...createResponsesAndMiddleware({
  response: {
    schema: getAsIsPatternResponseSchema,
    status: 200,
    description: "asIsの業務パターンの詳細を取得します",
  },
}),

実装のポイント

export const createResponsesAndMiddleware = <T extends z.ZodSchema, U extends ContentfulStatusCode>({
  response,
  middleware: _middleware = [],
}: {
  response: { schema: T; status: U; description: string };
  middleware?: MiddlewareHandler[];
}) => {
  const { schema, status, description } = response;
 
  const responses: { [key in U]: { content: { "application/json": { schema: T } }; description: string } } = {
    [status]: {
      content: {
        "application/json": {
          schema,
        },
      },
      description,
    },
  };
 
  // レスポンススキーマバリデーションミドルウェアを自動で適用
  const middleware = [responseSchemaValidationMiddleware(schema, status), ..._middleware];
 
  return { responses, middleware };
};

実装のポイント

export const responseSchemaValidationMiddleware = <T extends ZodSchema, U extends ContentfulStatusCode>(
  schema: T,
  status: U
): MiddlewareHandler => {
  return async (c, next) => {
    await next();
 
    // 成功ステータスコード(200-299)のJSONレスポンスのみを検証
    if (c.res.headers.get("Content-Type") !== "application/json") return;
    if (!isSuccessStatusCode(c.res.status)) return;
 
    const responseData = await c.res.json();
    const result = schema.safeParse(responseData);
 
    if (!result.success) {
      // パース失敗時は500エラーを返し、問題を即座に検出
      c.res = c.json({ message: "Response schema validation failed", errors: result.error.flatten().fieldErrors }, 500);
      return;
    }
 
    // ZodのsafeParseにより余分なプロパティを安全に除外
    c.res = c.json(result.data, status);
  };
};

実践例: レスポンススキーマバリデーションミドルウェア

効果

型安全性をコンパイル時+実行時の両方で担保:

  • セキュリティ向上: 機密情報の誤送信を防止
  • データ整合性: レスポンスの形式を保証
  • 開発体験: 問題を即座に検出・修正可能

これにより、スキーマ駆動開発のメリットを最大限に活用できています。

まとめ

Honoを選んだ理由

  1. TypeScriptネイティブな開発体験
  2. スキーマ駆動開発による型安全性
  3. TanStack Queryとの高い親和性
  4. 学習コストの低さ

結果

  • 型安全な開発体験の実現
  • 開発速度の向上
  • 保守性の高いコードベース

参考資料

最後に

当日ご参加いただいた皆様、Cloudflare社の皆様、そしてHonoの作者である yusukebe さん、登壇の機会をくださった seike460 さん、本当にありがとうございました!

福岡での初開催となったCloudflare Workers Tech Talksは、他の登壇者の方々の発表も非常に刺激的で、CloudflareやHonoコミュニティの熱量を肌で感じることができました。

以上、Honoでスキーマ駆動開発を実践していきたい、現場からお送りしました。

参考情報