はじめに: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では undefined と null が厳密に区別されますが、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 で関心を分離する設計思想は同じ
-
Pydantic は
class-validator+DTOの上位互換 - Swagger が自動生成されるので開発体験が良い
- Pythonエコシステム(LangChain, OpenAI SDK等)が使い放題
言語の壁は些細なものです。モダンなバックエンド開発の設計思想(DI、型安全性、非同期処理)が身についていれば、FastAPIの習得は1週間もあれば実務レベルに到達できます。
私はこの記事を書きながら、実際にAIチャットボットのバックエンドをFastAPIで構築しました。
次の記事では、今回の知識を活かして実装した 「FastAPI × Azure OpenAI によるストリーミングレスポンス(Server-Sent Events)」 の具体的なコードを解説します。
参考リンク
- FastAPI 公式ドキュメント (日本語訳が非常に充実しています)
著者:
@YushiYamamoto
株式会社プロドウガ CEO / AIアーキテクト
Next.js / TypeScript / n8nを活用した自律型アーキテクチャ設計を専門としています。
日々の自動化の検証結果や、ビジネス側の視点(ROI等)に関するより深い考察は、以下の公式サイトおよびnoteで発信しています。