「NestJS」タグアーカイブ

【NestJS入門シリーズ】第1章: NestJSとは何か?

1. NestJSの概要

NestJSは、TypeScriptを主に使用する、モジュールベースのサーバーサイドアプリケーションフレームワークです。Node.jsの基盤の上に構築されており、WebアプリケーションやAPI開発に特化しています。NestJSは、モダンなアーキテクチャを提供し、拡張性やスケーラビリティを強化しつつ、開発者が堅牢なアプリケーションを迅速に構築できるよう設計されています。

NestJSは、次のような特徴を持っています:

  • モジュールベースのアーキテクチャ: 機能ごとに分割し、管理しやすい構造を実現します。
  • TypeScriptによる型安全性: バグの発生を抑え、コードの品質を向上させます。
  • 依存性注入(Dependency Injection): 複雑な依存関係をシンプルに管理できる仕組みが提供されています。
  • ExpressやFastifyの統合: 内部でHTTPサーバーとしてこれらを使用し、効率的なサーバーサイド処理を実現します。

2. NestJSの特徴

NestJSは他のサーバーサイドフレームワークと比べて多くの利点があります。その中でも特に注目すべき点をいくつか挙げてみましょう。

2.1 TypeScriptによる開発

NestJSはTypeScriptをデフォルトでサポートしているため、型安全性が保証されます。TypeScriptは、JavaScriptに静的型付けを導入することで、開発時のエラーを減少させ、コードの保守性を向上させます。大規模なプロジェクトやチーム開発において特に有効で、開発者は信頼性の高いコードを書き続けることができます。

2.2 モジュールベースの設計

NestJSでは、アプリケーションをモジュール単位で分割することが推奨されています。これにより、機能ごとに異なるモジュールに分けて開発・管理することができ、コードの整理や再利用が容易になります。各モジュールは、コントローラーやサービスといった複数のコンポーネントを持ち、それらが一貫して動作するように設計されています。

2.3 依存性注入(Dependency Injection)

依存性注入(DI)は、クラスやサービス間の依存関係をNestJSが自動的に管理する仕組みです。これにより、開発者は複雑な依存関係をシンプルに扱うことができ、テストや保守が非常にしやすくなります。DIは、特にモジュールが増え、複数のサービスやコントローラーを利用する場面でその威力を発揮します。

2.4 テストのしやすさ

NestJSは、最初からテストを意識した設計がなされています。Jestなどのテストフレームワークを簡単に統合でき、依存関係をモックして効率的にユニットテストやインテグレーションテストを実行することができます。テストは、アプリケーションの品質を保つために重要であり、NestJSはそれをスムーズにサポートします。

3. NestJSのアーキテクチャ

NestJSは、以下の3つの基本コンポーネントで構成されています。

3.1 モジュール(Module)

NestJSアプリケーションは、基本的にモジュールを単位として構築されます。モジュールは、関連する機能をグループ化し、アプリケーションの構造を整理します。AppModuleは、すべてのNestJSアプリケーションに必要なルートモジュールです。各モジュールには、コントローラーやサービスを含めることができます。

3.2 コントローラー(Controller)

コントローラーは、HTTPリクエストを処理し、適切なレスポンスを返す役割を持ちます。各コントローラーは、リクエストパスとHTTPメソッドに基づいて、適切な処理を行うエンドポイントを定義します。

3.3 サービス(Service)

サービスは、ビジネスロジックを処理するクラスです。コントローラーから呼び出され、データの操作や外部APIの利用などを行います。サービスは、依存性注入によって他のクラスやコントローラーに提供されます。

4. まとめ

この第1章では、NestJSの基本的な概念や構造について学びました。NestJSは、モジュールベースの設計や依存性注入など、効率的かつ拡張性の高い開発環境を提供しており、今後の学習にも非常に有用です。

【NestJS入門シリーズ】第2章: NestJSの環境準備とプロジェクトセットアップ

1. 環境準備

NestJSを使ってアプリケーションを開発するためには、いくつかのツールとフレームワークをインストールする必要があります。以下に、その手順を詳しく説明します。

1.1 必要なソフトウェアのインストール

  1. Node.jsとnpmのインストールNode.jsは、JavaScriptをサーバーサイドで実行するためのランタイム環境です。npmはNode.jsに同梱されるパッケージマネージャーで、必要なライブラリやツールをインストールする際に利用します。
    • Node.jsの公式サイト(nodejs.org)から最新のLTS(長期サポート)バージョンをダウンロードしてインストールします。インストール後、以下のコマンドをターミナルで実行し、Node.jsとnpmが正しくインストールされているか確認します。
    node -v npm -v
    これにより、Node.jsとnpmのバージョンが表示されれば、インストールは成功です。
  2. NestJS CLIのインストールNestJS CLI(コマンドラインインターフェース)は、NestJSアプリケーションの作成や管理を効率的に行うためのツールです。以下のコマンドで、グローバルにNestJS CLIをインストールします。
    npm install -g @nestjs/cli
    インストールが完了したら、以下のコマンドでNestJS CLIが正常にインストールされたか確認します。
    nest --version

2. 新しいNestJSプロジェクトの作成

NestJS CLIを使って、新しいプロジェクトを簡単に作成できます。以下の手順に従って、プロジェクトをセットアップしていきましょう。

2.1 プロジェクトの生成

ターミナルを開き、次のコマンドを入力して新しいNestJSプロジェクトを作成します。

nest new my-first-nest-app

my-first-nest-appはプロジェクト名ですので、任意の名前に変更できます。コマンドを実行すると、プロジェクトの作成に必要な設定を尋ねられます。

  • Package managerの選択: npmまたはYarnのいずれかを選択します。通常はnpmを選ぶことが一般的です。

プロジェクトが作成されると、次のようなディレクトリ構成が生成されます。

cssコードをコピーするmy-first-nest-app
├── src
│   ├── app.controller.spec.ts
│   ├── app.controller.ts
│   ├── app.module.ts
│   ├── app.service.ts
│   └── main.ts
├── test
│   └── app.e2e-spec.ts
├── node_modules
├── package.json
├── tsconfig.build.json
├── tsconfig.json
└── nest-cli.json

2.2 プロジェクトの構成

  • src: アプリケーションのソースコードが含まれるディレクトリです。
  • test: テストコードが含まれるディレクトリです。
  • package.json: プロジェクトに依存するパッケージやスクリプトを管理するファイルです。
  • tsconfig.json: TypeScriptの設定ファイルです。
  • nest-cli.json: NestJS CLIの設定ファイルです。

3. NestJSアプリケーションの実行

プロジェクトの作成が完了したら、アプリケーションを実行してみましょう。ターミナルで以下のコマンドを実行します。

cd my-first-nest-app
npm run start

アプリケーションが正常に起動すると、次のようなメッセージが表示されます。

[Nest] 12345   - 2024-10-16 12:34:56   [NestFactory] Starting Nest application...
[Nest] 12345 - 2024-10-16 12:34:56 [InstanceLoader] AppModule dependencies initialized
[Nest] 12345 - 2024-10-16 12:34:56 [NestApplication] Nest application successfully started

デフォルトでは、アプリケーションはhttp://localhost:3000で実行されます。このURLにアクセスして、NestJSが正常に動作していることを確認しましょう。

ブラウザで以下のURLを入力します:

http://localhost:3000

何も設定していない状態では、NestJSのデフォルトのレスポンスは404 Not Foundとなります。

4. 簡単なHello World APIの作成

ここでは、NestJSの基本的な機能を理解するために、シンプルなHello WorldAPIを作成します。

4.1 コントローラーの作成

srcディレクトリ内に新しいコントローラーファイルを作成します。ファイル名はhello.controller.tsとしましょう。

src/hello.controller.ts:

import { Controller, Get } from '@nestjs/common';

@Controller('hello')
export class HelloController {
@Get()
getHello(): string {
return 'Hello World!';
}
}

4.2 サービスの作成

同様に、サービスを作成します。ファイル名はhello.service.tsとします。

src/hello.service.ts:

import { Injectable } from '@nestjs/common';

@Injectable()
export class HelloService {
getHello(): string {
return 'Hello World!';
}
}

4.3 モジュールへの追加

次に、コントローラーとサービスをアプリケーションのメインモジュールに登録します。src/app.module.tsを編集します。

src/app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { HelloController } from './hello.controller';
import { HelloService } from './hello.service';

@Module({
imports: [],
controllers: [AppController, HelloController],
providers: [AppService, HelloService],
})
export class AppModule {}

4.4 アプリケーションの再起動

アプリケーションを再起動します。ターミナルで以下のコマンドを実行してください。

npm run start

再度http://localhost:3000/helloにアクセスすると、「Hello World!」と表示されるはずです。これで簡単なAPIが完成しました。

5. まとめ

この章では、NestJSを使った開発環境の準備とプロジェクトのセットアップ方法を学びました。Node.jsとnpmのインストール、NestJS CLIの利用、プロジェクトの作成、アプリケーションの実行、そして簡単なAPIの構築について詳しく説明しました。

【NestJS入門シリーズ】第3章: NestJSのルーティングとミドルウェア

1. ルーティングとは

ルーティングは、HTTPリクエストを受け取り、それに対して適切なコントローラーのメソッドを呼び出すための仕組みです。NestJSでは、デコレーターを使ってルーティングを簡単に設定することができます。ここでは、基本的なルーティングの使い方と、パラメータ、クエリ、ボディを扱う方法について解説します。

2. 基本的なルーティングの設定

NestJSでは、コントローラーを使ってルーティングを定義します。以下に、簡単なユーザー関連のAPIを作成するためのコードを示します。

2.1 コントローラーの作成

まず、ユーザー関連のコントローラーを作成します。src/user.controller.tsというファイルを新規作成します。

import { Controller, Get, Post, Body, Param } from '@nestjs/common';

@Controller('users')
export class UserController {
private users = [];

@Post()
create(@Body() user: { name: string; age: number }) {
this.users.push(user);
return user;
}

@Get()
findAll() {
return this.users;
}

@Get(':id')
findOne(@Param('id') id: string) {
return this.users[id];
}
}

このコードでは、以下のエンドポイントを作成しています。

  • POST /users: 新しいユーザーを作成するエンドポイント。
  • GET /users: すべてのユーザーを取得するエンドポイント。
  • GET /users/:id: 特定のIDのユーザーを取得するエンドポイント。

2.2 サービスの作成

次に、ビジネスロジックを分離するためのサービスを作成します。ファイル名はsrc/user.service.tsとします。

import { Injectable } from '@nestjs/common';

@Injectable()
export class UserService {
private users = [];

create(user: { name: string; age: number }) {
this.users.push(user);
return user;
}

findAll() {
return this.users;
}

findOne(id: number) {
return this.users[id];
}
}

このサービスは、ユーザーの作成、取得を担当します。

2.3 モジュールへの登録

最後に、コントローラーとサービスをアプリケーションのメインモジュールに登録します。src/app.module.tsを編集します。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserController } from './user.controller';
import { UserService } from './user.service';

@Module({
imports: [],
controllers: [AppController, UserController],
providers: [AppService, UserService],
})
export class AppModule {}

3. アプリケーションの再起動

アプリケーションを再起動します。ターミナルで以下のコマンドを実行してください。

npm run start

4. APIのテスト

4.1 Postmanを使ったテスト

APIが正常に動作しているかを確認するために、Postmanを使ってテストします。

  1. ユーザーの作成: POST /usersエンドポイントに対して以下のJSONデータを送信します。jsonコードをコピーする{ "name": "John Doe", "age": 30 }
  2. すべてのユーザーを取得: GET /usersエンドポイントにアクセスすると、作成したユーザーのリストが取得できます。
  3. 特定のユーザーを取得: GET /users/0エンドポイントにアクセスすると、IDが0のユーザーが取得できます。

5. ルーティングの詳細

NestJSでは、ルーティングの設定に多くのオプションがあります。以下にいくつかの重要なデコレーターとその使用例を示します。

5.1 デコレーターの種類

  • @Get(): GETリクエストを処理するメソッド。
  • @Post(): POSTリクエストを処理するメソッド。
  • @Put(): PUTリクエストを処理するメソッド。
  • @Delete(): DELETEリクエストを処理するメソッド。
  • @Patch(): PATCHリクエストを処理するメソッド。
  • @Param(): URLパラメータを取得するデコレーター。
  • @Body(): リクエストボディを取得するデコレーター。
  • @Query(): クエリパラメータを取得するデコレーター。

5.2 ルートパラメータの取得

ルートパラメータは、エンドポイントの一部として指定される値です。以下は、IDをパラメータとして受け取る方法の例です。

@Get(':id')
findOne(@Param('id') id: string) {
return this.users[id];
}

5.3 クエリパラメータの取得

クエリパラメータは、URLの末尾に?key=valueという形式で追加される値です。以下は、クエリパラメータを取得する方法の例です。

@Get()
findAll(@Query('page') page: number) {
// ページネーション処理を行うことができる
return this.users.slice(page * 10, (page + 1) * 10);
}

6. ミドルウェアの利用

ミドルウェアは、リクエストがルーティングハンドラーに到達する前に実行される関数です。これにより、リクエストの処理を拡張したり、カスタムロジックを追加したりすることができます。

6.1 ミドルウェアの作成

ミドルウェアを作成するために、src/logger.middleware.tsというファイルを作成します。

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`Request... ${req.method} ${req.originalUrl}`);
next();
}
}

このミドルウェアは、リクエストメソッドとURLをログに出力します。

6.2 ミドルウェアの登録

作成したミドルウェアをアプリケーションに登録します。src/app.module.tsを以下のように変更します。

import { Module, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { LoggerMiddleware } from './logger.middleware';

@Module({
imports: [],
controllers: [AppController, UserController],
providers: [AppService, UserService],
})
export class AppModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes('*');
}
}

これにより、すべてのリクエストに対してLoggerMiddlewareが適用されます。

7. まとめ

この第3章では、NestJSのルーティングとミドルウェアについて詳しく解説しました。基本的なルーティングの設定、パラメータやクエリの取得方法、ミドルウェアの作成と登録方法を学びました。

【NestJS入門シリーズ】第4章: NestJSでのデータベース接続とORMの使用

1. ORMとは

ORM(Object-Relational Mapping)は、オブジェクト指向プログラミングとリレーショナルデータベースの間のデータ変換を行う技術です。NestJSでは、ORMライブラリの一つであるTypeORMを使用して、データベースとのやり取りを簡単に行うことができます。

2. TypeORMのインストール

まず、TypeORMとその依存関係をプロジェクトにインストールします。以下のコマンドをターミナルで実行してください。

npm install @nestjs/typeorm typeorm mysql2

ここでは、MySQLを例にしていますが、他のデータベース(PostgreSQL、SQLiteなど)を使用する場合は、それに応じたドライバをインストールしてください。

3. データベース接続の設定

次に、TypeORMを使用してデータベースに接続するための設定を行います。src/app.module.tsを以下のように編集します。

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { User } from './user.entity';

@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'password',
database: 'test',
entities: [User],
synchronize: true,
}),
TypeOrmModule.forFeature([User]),
],
controllers: [AppController, UserController],
providers: [AppService, UserService],
})
export class AppModule {}

この設定では、MySQLデータベースに接続し、Userエンティティを使用するように指定しています。また、synchronize: trueを設定することで、エンティティの変更が自動的にデータベースに反映されるようになります。

4. エンティティの作成

次に、データベースのテーブルに対応するエンティティを作成します。src/user.entity.tsというファイルを新規作成します。

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;

@Column()
name: string;

@Column()
age: number;
}

このエンティティでは、Userテーブルの構造を定義しています。@Entity()デコレーターは、このクラスがデータベースのテーブルに対応することを示します。

5. サービスの更新

次に、ユーザー管理のためのサービスを更新します。src/user.service.tsを以下のように編集します。

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';

@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private userRepository: Repository<User>,
) {}

create(user: { name: string; age: number }) {
const newUser = this.userRepository.create(user);
return this.userRepository.save(newUser);
}

findAll() {
return this.userRepository.find();
}

findOne(id: number) {
return this.userRepository.findOneBy({ id });
}
}

ここでは、TypeORMのリポジトリを使用して、ユーザーの作成、取得を行っています。@InjectRepository(User)デコレーターを使用して、Userエンティティに対応するリポジトリを注入しています。

6. コントローラーの更新

コントローラーも、サービスの変更に合わせて更新します。src/user.controller.tsを以下のように編集します。

import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}

@Post()
create(@Body() user: { name: string; age: number }) {
return this.userService.create(user);
}

@Get()
findAll() {
return this.userService.findAll();
}

@Get(':id')
findOne(@Param('id') id: string) {
return this.userService.findOne(+id);
}
}

7. データベースのテスト

7.1 データベースのセットアップ

MySQLのデータベースを事前に作成する必要があります。以下のSQLを実行して、testデータベースを作成してください。

CREATE DATABASE test;

7.2 アプリケーションの起動

アプリケーションを再起動します。ターミナルで以下のコマンドを実行してください。

bashコードをコピーするnpm run start

7.3 Postmanでのテスト

Postmanを使用して、データベース操作が正しく機能するかを確認します。

  1. ユーザーの作成: POST /usersエンドポイントに対して以下のJSONデータを送信します。jsonコードをコピーする{ "name": "John Doe", "age": 30 }
  2. すべてのユーザーを取得: GET /usersエンドポイントにアクセスすると、作成したユーザーのリストが取得できます。
  3. 特定のユーザーを取得: GET /users/1エンドポイントにアクセスすると、IDが1のユーザーが取得できます。

8. データベース操作の詳細

8.1 CRUD操作の実装

TypeORMを使用すると、簡単にCRUD(Create, Read, Update, Delete)操作を実装できます。

8.1.1 ユーザーの更新

ユーザーを更新するためのメソッドをUserServiceに追加します。

update(id: number, user: { name?: string; age?: number }) {
return this.userRepository.update(id, user);
}

これをコントローラーに追加します。

@Patch(':id')
update(@Param('id') id: string, @Body() user: { name?: string; age?: number }) {
return this.userService.update(+id, user);
}
8.1.2 ユーザーの削除

ユーザーを削除するためのメソッドも追加します。

remove(id: number) {
return this.userRepository.delete(id);
}

コントローラーに以下を追加します。

@Delete(':id')
remove(@Param('id') id: string) {
return this.userService.remove(+id);
}

9. エラーハンドリング

エラーハンドリングは、APIを構築する上で非常に重要です。NestJSでは、HTTP例外を使用して、簡単にエラーハンドリングを実装できます。次のようにエラーハンドリングを追加できます。

import { NotFoundException } from '@nestjs/common';

findOne(id: number) {
const user = this.userRepository.findOneBy({ id });
if (!user) {
throw new NotFoundException(`User with id ${id} not found`);
}
return user;
}

このようにして、ユーザーが見つからない場合に404エラーを返すように設定できます。

10. まとめ

この章では、NestJSでのデータベース接続とORMの使用方法について詳しく解説しました。TypeORMを使用してデータベースのCRUD操作を実装し、エラーハンドリングについても学びました。