Upgrade to Pro — share decks privately, control downloads, hide ads and more …

HonoConf2026登壇資料

Avatar for Ki Ki
October 11, 2026
56

 HonoConf2026登壇資料

mental-spaceのHonoConf2026登壇資料です!

Avatar for Ki

Ki

October 11, 2026

Transcript

  1. TUNAG 技術スタック‧アーキテクチャ変遷タイムライン 創業期 (2016 - 2018) 急成⻑期 (2019 - 2022)

    分離期 (2023 - 2024) 現代‧深化期 (2025-) ▪ バックエンド ▪ バックエンド ▪ バックエンド ▪ バックエンド ‧Rails 5系モノリス on EC2 ‧Aurora MySQL v1 / S3 ‧Amazon ECS (Docker化) ‧Rails 5.1 → 6.1 Upgrade ‧AWS Lambda 併⽤ ‧Rails 7.0 / 7.1 / Ruby 3.2 ‧Aurora MySQL v3化 ‧サービス分割 ▪ フロントエンド ▪ フロントエンド ‧Ruby 3.4 / 共通基盤MS化 ‧モジュラーモノリス ‧Google Cloud移⾏ ‧AI統合 (TUNAG AX) ※ERB/jQuery/React混在 ‧Rails内 React/TS同居 ‧Redux / redux-saga導⼊ ※ERB/jQuery/React混在 ‧Rails内 React/TS同居 ‧Redux / redux-saga導⼊ ‧Next.js移⾏ (分離) ‧Strangler Figパターン ▪ フロントエンド ▪ サブサービス ‧Rails使⽤ ‧画⾯はNext.jsに同居 ▪ Honoサブサービス ‧TS統⼀ ‧モノレポ化 ▪ フロントエンド ‧Rails View (ERB) ‧jQuery / Vanilla JS ※ERB/jQuery/React混在 ‧Rails内 React/TS同居 ‧Redux / redux-saga導⼊ ‧Next.js+TSへの集約停⽌
  2. Next.js導⼊期のアーキテクチャ ユーザーブラウザ エッジルーティング層 移⾏済URLパス フロントエンド基盤 (Next.js) バックエンド基盤 (AWS ECS) Next.js

    on Vercel Rails 7.0 API / モジュラーモノリス (TypeScript / App Router / React 18) BFF / REST API リクエスト Client Request データ層 (DDD境界づけコンテキスト) AWS CloudFront Amazon Aurora MySQL v3 + CloudFront Functions (MySQL 8.0互換) レガシー画⾯ 未移⾏URLパス (未移⾏ERB/React)
  3. TUNAG 技術スタック‧アーキテクチャ変遷タイムライン 創業期 (2016 - 2018) 急成⻑期 (2019 - 2022)

    分離期 (2023 - 2024) 現代‧深化期 (2025-) ▪ バックエンド ▪ バックエンド ▪ バックエンド ▪ バックエンド ‧Rails 5系モノリス on EC2 ‧Aurora MySQL v1 / S3 ‧Amazon ECS (Docker化) ‧Rails 5.1 → 6.1 Upgrade ‧AWS Lambda 併⽤ ‧Rails 7.0 / 7.1 / Ruby 3.2 ‧Aurora MySQL v3化 ‧サービス分割 ▪ フロントエンド ▪ フロントエンド ‧Ruby 3.4 / 共通基盤MS化 ‧モジュラーモノリス ‧Google Cloud移⾏ ‧AI統合 (TUNAG AX) ※ERB/jQuery/React混在 ‧Rails内 React/TS同居 ‧Redux / redux-saga導⼊ ※ERB/jQuery/React混在 ‧Rails内 React/TS同居 ‧Redux / redux-saga導⼊ ‧Next.js移⾏ (分離) ‧Strangler Figパターン ▪ フロントエンド ▪ サブアプリ ‧Rails ‧Next.jsに同居 ▪ Honoサブサービス ‧TS統⼀ ‧モノレポ化 ▪ フロントエンド ‧Rails View (ERB) ‧jQuery / Vanilla JS ※ERB/jQuery/React混在 ‧Rails内 React/TS同居 ‧Redux / redux-saga導⼊ ‧Next.js+TSへの集約停⽌
  4. サブサービス導⼊期のアーキテクチャ ユーザーブラウザ エッジルーティング層 tunag-front バックエンド基盤 データ層 画⾯コードを同じリポジトリで管理 Next.js / Pages

    Router Rails 本体 (tunag) 未移⾏の既存画⾯ Rails⽣成HTML+⼀部React Rails API 本体の画⾯コード 認証‧共通API‧業務処理 Aurora MySQL (本体DB) 本体のNext.js∕React 画⾯ AWS CloudFront レガシー画⾯配信 (ERB) + CloudFront Functions 未移⾏機能の直描画 先⾏サブアプリの画⾯コード 先⾏サブアプリの Next.js∕React画⾯ 先⾏サブアプリのAPI Rails本体とは別リポジトリ‧別サービス ※代表的な通信経路。APIの中継経路は省略
  5. 新Honoアプリ;機能単位でのGit Repo分離 先⾏サブアプリの構成 新アプリの構成 (リポジトリ完全分離) 共通フロントエンド Repo (フロント領域が同⼀Repo内に同居) 共通フロントエンド Repo

    専⽤リポジトリ 本体機能 先⾏サブアプリ機能 本体機能 Frontend Component Frontend Component frontend フロントエンド React バックエンドAPI Hono 共通コアAPI 先⾏サブアプリAPI 本体Rails Rails Rails コア機能API ※ 共通フロントに依存が集約され、リポジトリ境界を跨ぐ開発が必要 ✔ Frontend/Backendが1つの専⽤Repoに完結し独⽴開発が可能
  6. React画⾯とHono APIを CloudFront経由で提供する /* 画⾯配信 クライアント CloudFront ブラウザ / WebView

    パスによるルーティング /api/* API通信 S3(画⾯配信) React / Vite ビルド成果物を配信 Lambda Function URL → Hono API Gatewayなしで直接実⾏ ※ API Gatewayを追加せず、Lambda Function URLとCloudFrontを直接接続してAPIを提供する構成 DynamoDB
  7. 認証が必要なリクエストは 共通処理を通る 例:POST /api/forms へのリクエスト処理フロー 全体共通ミドルウェア 認証対象(/api配下) 1. Sentry 2.

    ログ 3. 認証 4. 対象ルート エラー監視 pino / 受信‧応答 Cookie委譲‧検証 業務ロジック実⾏ 分岐例:/health ログ記録後に直接レスポンスを返却し、認証ミドルウェアは経由しない
  8. 認証失敗時は後続ルートへ進ませない ミドルウェア内の判定分岐 失敗時の応答対応 認証成功 Contextを設定して next() を呼ぶ 状態 / 種別

    応答内容 未認証 / ブラウザ ログイン画⾯へリダイレクト 未認証 / API 401 Unauthorized 後続ルート実⾏へ 認証失敗 エラーレスポンスを返して終了 後続ルートを遮断 外部サービス障害‧契約違反 503 Service Unavailable
  9. Honoの仕組みに、 独⾃処理とライブラリを組み合わせる 領域 Hono組み込み機能 Formsの実装⽅式 未使⽤ 認証 独⾃ミドルウェア + TUNAG認証

    未使⽤ Logger ⼊⼒検証 pino + 独⾃ミドルウェア validator / zod-validator 未使⽤ ※ Sentry連携:@sentry/hono は利⽤ ルート内でZodを直接適⽤ ミドルウェア機構⾃体は活⽤し、処理内容は既存基盤‧外部ライブラリを組み合わせる
  10. ※ サーバーをポート待ち受けさせずにテストを実⾏。 return setup.ts:jsonRequestの内部 app.request(path, init) as Promise; ExpressでもSupertest等で可能だが、Honoは標準でapp.request()を提供している。 app.request()で、

    HTTPの振る舞いを直接テストできる createTestApp (モック注⼊) Honoアプリ (インメモリ) Response 検証 form-routes.test.ts(抜粋) const res = await jsonRequest(app, 'POST', '/api/forms', { title: '新しいフォーム', }); expect(res.status).toBe(201); const body = await res.json(); expect(body.title).toBe('新しいフォーム');
  11. 同じHonoアプリを NodeとLambdaへ接続する ローカル開発 本番環境 @hono/node-server 共通 app.ts hono/aws-lambda Node.js HTTPサーバー

    Honoアプリ本体 AWS Lambda ハンドラー index.ts(説明⽤抜粋) serve({ fetch: app.fetch, port: config.port }); handler.ts(抜粋) export const handler: Handler = Sentry.wrapHandler(streamHandle(app));
  12. streamHandleと配信設定で サイズ上限へ対応 変更前:バッファモード:6MB 回答⼀覧取得時にLambdaの同期バッファレスポンス上限に達し、エ ラーとなる課題が発⽣ 設定変更の2つの箇所 1. Hono アプリ側 streamHandle(app)

    ストリーミング形式でレスポンスを返却するハンドラーを利⽤ 変更後:ストリーミング対応:200MB streamHandle + RESPONSE_STREAM 設定により⼤きな⼀覧配信に 対応 2. AWS設定側 RESPONSE_STREAM Lambda Function URLの呼び出しモードを変更
  13. API契約の整合性を改善するため、 RPCの価値を検討 現在の状態 fetch + 独⾃型 frontend: 独⾃ Form 型

    HTTP通信 backend: APIハンドラー 検討:Hono RPC による型共有 hc('/api') 今後の検討候補 型安全なクライアント backend: AppType 公開 ※ 採⽤決定や移⾏完了ではなく、契約不整合を防ぐための検討対象。⼊⼒の実⾏時検証は別途必要