2
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NestJS使いがFastAPIを触ったら実家のような安心感だった。DI、デコレータ、Pydanticによる型安全なバックエンド開発

2
Last updated at Posted at 2026-02-18

はじめに:NestJS歴4年の私がPythonに手を出した理由

私はこれまで4年間、NestJS(TypeScript)でバックエンドを開発してきました。DDD(ドメイン駆動設計)に基づいたアーキテクチャ設計や、class-validatorによる堅牢な型安全性を重視した開発が信条でした。

しかし最近、生成AI(LLM)アプリケーション開発の案件に携わる機会が増え、Pythonエコシステムとの遭遇が避けられなくなりました。最初は「動的型付け言語のPythonで大規模開発なんて…」と正直抵抗がありました。

ところが、重い腰を上げてFastAPIを触ってみたら、「あれ、こいつはNestJSの親戚か?」 と感じるほど設計思想が似通っていたのです。

この記事では、TypeScript/NestJSエンジニアがFastAPIを最短で習得するための、概念の対応表を提供します。言語は違っても、モダンなバックエンド開発の本質(DI、型安全性、宣言的記述)は同じでした。

概念対応表:NestJS vs FastAPI

まずは全体像を掴むため、主要な概念の対応表をまとめました。

概念 NestJS (TypeScript) FastAPI (Python) 共通点・所感
DTO/バリデーション class-validator Pydantic (BaseModel) 「型定義=バリデーション」 という思想が完全一致
DI(依存性注入) @Injectable() Depends() テスト容易性と関心の分離を実現
ルーティング @Controller() / @Get() @app.get() デコレータ構文で直感的
非同期処理 async/await (Node.js) async / await どちらもシングルスレッド・イベントループモデル
ドキュメント 手動設定 (@ApiProperty) 自動生成 FastAPIの圧勝。コードを書けばドキュメントになる
型システム TypeScript (静的解析) Python Type Hints (実行時解析) アプローチは違うが、開発体験は近い

1. DTOとバリデーション:class-validator vs Pydantic

NestJSでは、DTO(Data Transfer Object)クラスにデコレータをつけてバリデーションを行いますが、FastAPIではPydanticがその役割を担います。

NestJS (TypeScript) の場合

// create-user.dto.ts
import { IsString, IsEmail, MinLength, IsOptional } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @MinLength(2)
  name: string;
  
  @IsEmail()
  email: string;
  
  @IsOptional()
  @IsString()
  bio?: string;
}

FastAPI (Python) の場合

# schemas.py
from pydantic import BaseModel, EmailStr, Field
from typing import Optional

class CreateUserRequest(BaseModel):
    name: str = Field(..., min_length=2)  # Fieldで制約を追加
    email: EmailStr  # 型そのものがバリデーションロジックを持つ
    bio: Optional[str] = None  # Optionalで省略可能

ここがすごい:
Pydanticは「型定義」がそのまま「実行時のバリデーションロジック」になります。TypeScriptでは型はコンパイル後に消えますが、Pydanticでは生きています。


2. 依存性注入(DI):@Injectable vs Depends

NestJSの最大の特徴であるDIシステム。FastAPIにも同様の機能が Depends として存在します。これにより、ビジネスロジックとコントローラーを綺麗に分離できます。

NestJS (TypeScript) の場合

// users.service.ts
@Injectable()
export class UserService {
  constructor(@InjectRepository(User) private userRepo: Repository<User>) {}
  // ...
}

// users.controller.ts
@Controller('users')
export class UserController {
  constructor(private userService: UserService) {} // コンストラクタ注入

  @Get(':id')
  async getUser(@Param('id') id: string) {
    return this.userService.findById(id);
  }
}

FastAPI (Python) の場合

FastAPIのDIは、クラスではなく関数ベースで解決するのが一般的ですが、やっていることは同じです。

# dependencies.py
from fastapi import Depends
from sqlalchemy.orm import Session

# DBセッションを注入するDependency
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

# Service層への注入
def get_user_service(db: Session = Depends(get_db)) -> UserService:
    return UserService(db)

# main.py (Controller相当)
@app.get("/users/{user_id}")
async def get_user(
    user_id: str, 
    service: UserService = Depends(get_user_service) # ここで注入!
):
    return service.find_by_id(user_id)

テスト時のメリット:
NestJSで Test.createTestingModule().overrideProvider(...) をするように、FastAPIでも app.dependency_overrides を使って、テスト時にServiceやDBをモックに差し替えることが可能です。


3. Swaggerドキュメント:手動 vs 自動

ここが最大のカルチャーショックでした。NestJSではSwaggerのために大量のデコレータを書く必要がありましたが、FastAPIは**「何もしなくていい」**のです。

NestJS (TypeScript) の場合

// 書くのが大変...
export class CreateUserDto {
  @ApiProperty({ description: 'ユーザー名', example: '山田太郎' })
  @IsString()
  name: string;
}

FastAPI (Python) の場合

Pydanticモデルと型ヒントを書くだけです。

class CreateUserRequest(BaseModel):
    name: str 
    # これだけでSwagger UIに型情報と必須チェックが反映される

サーバーを起動して /docs にアクセスすると、完璧なOpenAPI仕様書が生成されています。これは開発スピードに直結する大きなアドバンテージです。


4. TypeScript使いが陥る「Pythonの罠」

と、ここまで褒めちぎりましたが、TypeScript脳のままPythonを書くとハマるポイントもあります。

落とし穴①:Optional の扱い

TypeScriptでは undefinednull が厳密に区別されますが、Pythonには None しかありません。「値が存在しない」ことを表現する場合は常に Optional[Type] = None を使います。

落とし穴②:実行時の型安全性

Pythonの型ヒント(Type Hints)は、あくまで「ヒント」であり、実行時に無視されます。

# Pydanticを使わない関数
def add(a: int, b: int) -> int:
    return a + b

add("1", "2") # エラーにならず "12" が返ってくる!恐怖!

教訓: APIの入出力や重要なロジックには必ず Pydantic を使いましょう。Pydanticを通すことで、Pythonでも堅牢な型安全性を担保できます。


まとめ:明日から書ける

FastAPIは、NestJSエンジニアにとって「実家のような安心感」 があるフレームワークです。

  • DI で関心を分離する設計思想は同じ
  • Pydanticclass-validator + DTO の上位互換
  • Swagger が自動生成されるので開発体験が良い
  • Pythonエコシステム(LangChain, OpenAI SDK等)が使い放題

言語の壁は些細なものです。モダンなバックエンド開発の設計思想(DI、型安全性、非同期処理)が身についていれば、FastAPIの習得は1週間もあれば実務レベルに到達できます。

私はこの記事を書きながら、実際にAIチャットボットのバックエンドをFastAPIで構築しました。
次の記事では、今回の知識を活かして実装した 「FastAPI × Azure OpenAI によるストリーミングレスポンス(Server-Sent Events)」 の具体的なコードを解説します。

参考リンク


著者:
@YushiYamamoto
株式会社プロドウガ CEO / AIアーキテクト
Next.js / TypeScript / n8nを活用した自律型アーキテクチャ設計を専門としています。
日々の自動化の検証結果や、ビジネス側の視点(ROI等)に関するより深い考察は、以下の公式サイトおよびnoteで発信しています。

2
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?