「Cloudflare Workers Tech Talks in Fukuoka #1」登壇レポート 〜 Honoを技術選定したAI要件定義プラットフォームAcsimでの意思決定
福岡で開催されたコミュニティイベント「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-generator | ❌ | TanStack Queryとの連携で設定量が多い |
| @hono/zod-openapi + orval | ✅ | 学習コスト・親和性が最適 |
メリット: 得られた開発体験
1. 型安全性の確保
- Frontend・API間の型不一致を防止
- コンパイル時にエラーを検出
2. 開発速度の向上
- APIクライアントコードの自動生成
- ボイラープレートの削減
3. 保守性の向上
- Query Key管理の自動化
- 一貫性のあるコードベース
デメリット: トレードオフ
運用上のコスト
-
API変更時にOpenAPI Schemaの更新が必要
- 自動生成の仕組みで軽減
-
OpenAPI Schemaの記述コスト
- TypeScriptで記述できるため学習コストは低い
-
orvalの設定コスト
- 初期設定は必要だが、一度設定すれば再利用可能
実践例: レスポンススキーマバリデーションミドルウェア
背景と課題
フロントエンドとAPI間は型定義により型安全性が保証されているが、バックエンド側のレスポンスには問題がありました:
- 型チェックの限界: TypeScriptの型は必要なプロパティの存在のみをチェックし、余分なプロパティを検出できない
- セキュリティリスク: パスワードなどの機密情報を誤ってレスポンスに含めてもコンパイルエラーにならない
- レビューだけでは不十分: 人的チェックだけで防ぐのは困難かつ影響度が大きい
解決策
実行時にZodスキーマでレスポンスをパースすることで:
- 型定義に含まれないプロパティを自動的に除外
- 機密情報の誤送信を防止
- レスポンスの形式を保証
使い方
...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を選んだ理由
- TypeScriptネイティブな開発体験
- スキーマ駆動開発による型安全性
- TanStack Queryとの高い親和性
- 学習コストの低さ
結果
- 型安全な開発体験の実現
- 開発速度の向上
- 保守性の高いコードベース
参考資料
最後に
当日ご参加いただいた皆様、Cloudflare社の皆様、そしてHonoの作者である yusukebe さん、登壇の機会をくださった seike460 さん、本当にありがとうございました!
福岡での初開催となったCloudflare Workers Tech Talksは、他の登壇者の方々の発表も非常に刺激的で、CloudflareやHonoコミュニティの熱量を肌で感じることができました。
以上、Honoでスキーマ駆動開発を実践していきたい、現場からお送りしました。