GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-04-29上級

NestJS で Gemini API バックエンドを設計する — DI・例外フィルタ・ガードを活かす実装パターン

NestJS の DI・例外フィルタ・ガードで保守しやすい Gemini API バックエンドを構築する実装パターンを解説します。SSE ストリーミング、Flash→Pro フォールバック、指数バックオフ・リトライ、レイテンシとトークンの実測まで実コードでまとめます。

gemini-api279nestjstypescript15backend2sse

プレミアム記事

Gemini API を Express や薄い Hono ベースで素早く立ち上げると、最初の数週間は快適です。しかし機能が増え、認可・レート制御・複数モデルの切り替え・例外メッセージのフォーマットといった「外側」が膨らんできた頃に、コードがコントローラに溜まり始めます。私自身、個人プロダクトでも企業案件でも、ここで一度 NestJS に作り直す判断をすることが多くなりました。NestJS の DI(依存性注入)、デコレータ、例外フィルタ、ガードといった仕組みは、AI バックエンド特有の「複雑な外側」をきれいに分離するのに非常に向いているからです。

ここではGemini API を NestJS で扱うときに私が落ち着いた「現場で消耗しにくい」実装パターンを、なるべく短いコードで共有します。Express で書いた場合と何が違うのか、そしてなぜそうするのかまで踏み込んで解説します。

なぜ Gemini API には NestJS が向いているのか

NestJS はもともと Angular に近い設計思想を持つ TypeScript 向けフレームワークで、DI と「Module / Controller / Provider」の3層構造を強制してきます。これが Gemini API のような「外部依存が多いサービス」を扱うときに効いてきます。

私が NestJS を選ぶ実利的な理由は3つあります。第一に、GeminiService を Provider として注入することで、コントローラ側のテストをモックに差し替えやすくなる点です。第二に、HttpException のサブクラスを定義すれば Gemini 特有の 429・503・コンテンツ違反エラーを @Catch() で一括ハンドリングできる点。第三に、Guard を組み合わせれば API キー認証や 1 ユーザーあたりのレートリミットを Controller 側のコードを汚さずに実現できる点です。Express でこれを真面目にやると、ミドルウェアの順序やエラー伝播でハマりがちでした。

プロジェクト構成と GeminiModule の作り方

最小構成では、GeminiModule を1つ作り、その中に GeminiServiceGoogleGenerativeAI クライアントのラッパー)を Provider として登録するのが基本形です。

// src/gemini/gemini.module.ts
import { Module } from '@nestjs/common';
import { GoogleGenerativeAI } from '@google/generative-ai';
import { GeminiService } from './gemini.service';
import { GeminiController } from './gemini.controller';
 
@Module({
  controllers: [GeminiController],
  providers: [
    {
      provide: 'GENAI_CLIENT',
      useFactory: () => new GoogleGenerativeAI(process.env.GEMINI_API_KEY!),
    },
    GeminiService,
  ],
  exports: [GeminiService],
})
export class GeminiModule {}

GoogleGenerativeAI 自体を Provider として切り出しているのがポイントです。テスト時には useFactory を差し替えるだけで完全なモッククライアントを注入でき、ネットワークを叩かずユニットテストが書けます。@google/generative-ai を直接 import して new するコードがコントローラに散らばると、これができなくなります。

GeminiService は単純に「モデル選択・プロンプト整形・レスポンス整形」の責務だけ持たせます。ストリーミングと一括取得をメソッド分割しておくと、後述の SSE 対応がきれいに書けます。

// src/gemini/gemini.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { GoogleGenerativeAI } from '@google/generative-ai';
 
@Injectable()
export class GeminiService {
  constructor(
    @Inject('GENAI_CLIENT') private readonly client: GoogleGenerativeAI,
  ) {}
 
  async generate(prompt: string, model = 'gemini-2.5-flash') {
    const m = this.client.getGenerativeModel({ model });
    const res = await m.generateContent(prompt);
    return res.response.text();
  }
 
  async *stream(prompt: string, model = 'gemini-2.5-flash') {
    const m = this.client.getGenerativeModel({ model });
    const res = await m.generateContentStream(prompt);
    for await (const chunk of res.stream) {
      yield chunk.text();
    }
  }
}

非同期ジェネレータを返す stream メソッドを用意しておくと、後で SSE でも WebSocket でも好きな伝送方式に流し込めます。フレームワークに依存しない形で逃げ場を作っておくのは、大事な現場のコツです。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
Flash → Pro のフォールバックを Service に閉じ込め、過負荷時だけ自動で切り替える実装
指数バックオフ + ジッタ付きリトライを Interceptor に集約し、Controller と Service を汚さない設計
1.2 万リクエストの実測: p50/p95 レイテンシとトークン消費、Pro へのフォールバック発火率の生データ
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

API / SDK2026-06-20
Gemini API × tRPC v11 × Prisma でつくる型安全 AI バックエンド — リアルタイムストリーミングからミドルウェア認証・本番運用まで
tRPC v11 の subscription で Gemini API ストリーミングをリアルタイム配信し、Prisma で型安全に会話を永続化する本番設計を解説します。ミドルウェア認証・レート制限・落とし穴対策まで実コード付きでまとめました。
API / SDK2026-06-25
Gemini API × TypeScript 型安全AIアプリケーション設計ガイド — Zodスキーマ・Structured Output・ストリーミングの統合アーキテクチャ
Gemini APIとTypeScriptで型安全なAIアプリケーションを構築する方法を解説。Zodバリデーション、Structured Output、ストリーミング、エラーハンドリングを統合した本番アーキテクチャを実装します。
API / SDK2026-06-14
Gemini API の本文が途中で切れる — finish_reason: MAX_TOKENS を検知して続きを継ぎ直す実装メモ
長文生成で末尾が文の途中でぷつりと切れる。原因の多くは finish_reason: MAX_TOKENS です。例外も 200 のまま静かに混入するこの事故を検知し、続きを継ぎ足して全文を取り戻す実装を、思考トークンの落とし穴とあわせてまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →