大規模なアプリケーションの管理は簡単ではありません。特に綿密に計画された構造や厳密なコード編成戦略がないと、混乱を引き起こす可能性があります。メンテナンス中の問題発生は、何としても避けたいところです。ユーザー数が拡大するにつれて、コードの改善や新機能の追加を行うことで、そのような欠陥があらわになることがあります。

そんな中でNest.jsが、コードの構造や編成戦略の問題に対する解決策として注目を集めています。Nest.jsは、ソフトウェア工学とモジュラーという構造を味方につけた比較的新しい選択肢です。

Nest.jsは型チェックにTypeScriptを使用しており、テストのしやすさ、スケーラブルな構造を特徴とします。そのソフトウェアアーキテクチャを使い、疎結合で保守が容易なアプリケーションの構築をすぐに始めることができます。

今回は、Nest.jsについて、そしてNest.jsを使ってどのようなものを構築できるのかについてご説明します。また、このフレームワークの長所と短所に迫り、多くの有名企業がNest.jsを採用している理由も明らかにします。そして最後には、Nest.jsを使ったToDo APIの作成方法をご紹介します。

Nest.jsとは

Nest.jsは、Node.jsを使用して効率的でスケーラブルなエンタープライズグレードのバックエンドアプリケーションを構築することのできる、急成長を見せるNode.jsフレームワークです。Nest.jsでは、モダンJavaScriptとTypeScriptを使用して、高いテスト可能性、保守性、拡張性を備えたアプリケーションを作成可能です。

Nest.jsのロゴ
Nest.jsの公式ロゴ(画像出典:Behance

Nest.jsはGitHubで4万6,600のスターと5,400のフォークを記録し、毎週のダウンロード数は70万に達しています。

Nest.jsは、スケーラブルで保守のしやすいエンタープライズレベルのアプリケーションを構築するのに優れた選択肢です。

次のセクションでは、Nest.jsがどのような用途で使われているのか、また、このフレームワークを本番環境で使用するさまざまな企業について見ていきます。

Nest.jsは何に使われているのか

Nest.jsはサーバーサイドのNode.jsフレームワークで、テストと保守のしやすいバックエンドアプリケーションを構築するのに向いています。Node.jsではあらゆるタイプのアプリケーションを開発可能です。

TypeScriptを活用しているため、Nest.jsはTypeScriptの型チェック性能をフル活用したいチームの間で特に人気があります。さらに、Nest.jsは学習も比較的簡単で、パワフルなCLIを使いこなすことで生産性と開発のしやすさがさらに向上します。CLIを使用して、サーバーサイドのプロジェクトを簡単に開始し、完成まで導くことができます。

さらに、Nest.jsのドキュメントは豊富に用意されており、開発者のコミュニティも活発で、問題解決に使える情報が簡単に見つかります。

これらの理由から、多くの企業がフレームワークをNest.jsに切り替えています。Nest.jsを使用している有名企業が以下の通りです。

ロシュ/Roche

Rocheは、医薬品と診断薬という2つの部門で事業を展開する多国籍ヘルスケア企業です。このアメリカのバイオテクノロジー企業は、患者に信頼できるサービスを提供するために、メインウェブサイトでNest.jsフレームワークを採用しています。

Rocheの公式ホームページ
Rocheの公式ホームページ

アディダス/Adidas

アディダスはヨーロッパ最大、世界第2位のスポーツウェアメーカーです。シューズ、ウェア、アクセサリといった製品のデザインと製造で圧倒的な存在感を誇ります。世界的な知名度と人気は言うまでもなく、大規模で効率的なアプリケーション構築に、スケーラビリティの高いNest.jsフレームワークが使用されているのには納得です。

アディダスの公式ホームページ
アディダスの公式ホームページ

デカトロン/Decathlon

Decathlonは、57カ国に1,500以上の店舗を持つスポーツ用品小売業者です。同社はアプリケーションのバックエンドとしてNest.jsを選択し、レガシーコードベースの拡張と保守を実現しています。

デカトロンの公式ホームページ
デカトロンの公式ホームページ

Nest.jsで構築されたその他の企業、プロジェクト、ツールの一覧はGitHubで確認できます。

次に、今後のプロジェクトにNest.jsをおすすめする理由、このフレームワークの特徴などについて見ていきましょう。

Nest.jsが選ばれている理由

フレームワークの選択は、開発するアプリケーションの種類に依存します。

プロジェクトを開始する、または次のレベルに引き上げるためにNode.jsフレームワークを活用することができます。これの強みをご紹介します。

  • Nest.jsは、特にAngularを経験してきた開発者にとって、学びやすく習得しやすい傾向にあります。新しい開発の原則や構造に簡単に適応できるため、素早く効率的な開発プロセスが可能になります。
  • このフレームワークは、エンタープライズアプリケーションに対応した優れたアーキテクチャ構造を誇ります。
  • Nest.jsでRESTful API、GraphQLアプリケーション、MVCアプリケーション、WebSocket、CLI、Cronジョブなどのバックエンドサービスを簡単に構築することができます。標準的なアーキテクチャの構成要素が、Nest.jsフレームワークにすでに組み込まれています。
  • Nest.jsは、TypeScriptのような最新の技術、堅牢なアーキテクチャパターン、優れたドキュメント、簡単に使える単体テストを採用し、スケーラブルで保守の捗るエンタープライズ対応アプリケーションを構築するのに有用です。
  • Nest.jsは、大規模なモノリシックおよびマイクロサービスアプリケーションを構築するために開発されたもので、アーキテクチャはすでに処理されており、ビジネスロジックを構築するだけでOKです。
  • Nest.jsは、TypeORM、Mongoose、GraphQLのようなコンセプトから、ロギング、バリデーション、キャッシュ、WebSocket、その他多くの機能まで、大規模なコミュニティベースのサポートモジュールをサポートしています。

次に、Nest.jsの長所と短所を探ります。良い点と悪い点の両方を理解することで、このフレームワークを採用する決断を固める助けとなるはずです。

Nest.jsの長所と短所

Nest.jsがNode.jsエコシステムで人気のフレームワークである理由をよりよく理解するために、Nest.jsの長所と短所を見ていきましょう。

長所

Nest.jsを使用する利点には以下のようなものがあります。

  • パワフルでユーザーフレンドリー:このフレームワークは開発者にとって使いやすく、複雑な機能であっても簡単に扱うことができます。Nest.jsを採用することでチームでの開発をすぐに始められ、セキュリティなどの要素は組み込みの性能をそのまま活用することで、ビジネスロジックを書くことに集中できます。
  • Angularスタイルの構文(バックエンド)Angularは、アーキテクチャと構造化に集中した、人気のフロントエンドフレームワークです。Nest.jsは言うなれば「バックエンドのAngular」として機能し、Angularのスタイルと構文を使用してエンタープライズプロジェクトの構造化を支援します。
  • TypeScript:Nest.jsは標準でTypeScriptをサポートし、コンパイルエラーや警告を提供することで、パフォーマンスや保守性の高いアプリケーションを素早く書くことに貢献します。VSCodeとの親和性が高く、アクセス性の高い開発環境が確保できます。
  • 徹底したドキュメント:Nest.jsはあらゆるフレームワークと比較しても高いレベルのドキュメントを誇り、学習や理解を深めるのに有用です。ドキュメントにざっと目を通すだけで問題の解決策を知ることができ、デバッグの時間を削減できます。
  • 優れたアーキテクチャと素早い開発:Nest.jsは、最初のMVP(※注釈:機能を最低限にした試作品)を作成する場合でも、実際のアプリケーションを作成する場合でも、アプリケーションを構築する際の手間の削減に貢献します。Nest.jsを採用することで、すぐに作業を開始できる強固な構造とアーキテクチャが手に入り、開発プロセスの向上が期待できます。

短所

どんな優れたツールにも課題があるもので、Nest.jsも例外ではありません。それでは、Nest.jsの短所も見てみましょう。

  • 初心者には難しい:Nest.jsは、Angularの基礎知識を持っていない駆け出しの開発者が学びマスターするには少し難しいかもしれません。さらに、すべてのJavaScript開発者がTypeScriptを使っているわけではないので、これがネックになる可能性もあります。他の技術と同じように、習得するには実際に使ってみる必要があります。
  • デバッグが大変:TypeScriptにはたくさんのメリットがありますが、特にTypeScriptを使い始めた開発者にとっては、デバッグの苦労が多くなる点は否定できません。

Nest.jsの長所と短所、そしてそれらがフレームワークとして選択する際の意思決定にどのような影響を与えるかをご紹介しました。

次に、Nest.jsを使ってRESTfulなAPIを構築する例を使って、これまでに学んだ内容を固めていきましょう。ToDoリスト開発方法を扱います。

最初のNest.js RESTful APIを構築する

Nest.jsの性能とシンプルさを実証するために、RESTful APIを構築してみましょう。Nest.jsについて学んだ基礎を実践で活用していきます。

まずはフレームワークをセットアップし、必要なツールをインストールするところから始めましょう。

1. Nest.jsのセットアップ

まずNest CLIをインストールして、以下のコマンドで新しいプロジェクトを作成します。

npm i -g @nestjs/cli

その後、以下のコマンドを使って新しいプロジェクトを作成します。

nest new nest-todo-api
cd nest-todo-api
npm run start:dev

これでNest CLIがインストールされ、プロジェクトの作成ができたところで、APIを構築していきましょう。

お好みのコードエディタでプロジェクトを開いてください。localhost:3000 にアクセスすると、プロジェクトが問題なく動作していることを示すウェルカムメッセージが表示されるはずです。

次に、MongoDBデータベースをセットアップします。これは、プロジェクト全体のToDoデータを接続して管理するためのものです。

以下のコマンドでAPIを作成するのに必要なファイルをすべて生成しておきましょう。

nest generate module todos
nest generate controller todos
nest generate service todos

2. MongoDBのセットアップ

次に、MongoDBをインストールして、先ほど作成したプロジェクトで動作するように設定します。

ローカルマシンに MongoDB をインストールしたら、次のコマンドを実行して、今回のプロジェクトにMongooseライブラリをインストールします。

npm install --save @nestjs/mongoose mongoose

次に、プロジェクトとMongoDBとの通信を確立するために、ファイルを生成してMongooseをインポートします。

他の必要なファイルを生成する前に、アプリケーションモジュールファイルにMongooseをインポートしましょう。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
import { TodosModule } from './todos/todos.module';

@Module({
  imports: [MongooseModule.forRoot('mongodb://localhost/todos), TodosModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

3. スキーマのビルド

次に、データベースのスキーマを作ります。このスキーマは、データベース内でデータをどのように表現するかを指定するためのものです。

todos.schema.tsファイルで定義することができます。

import * as mongoose from 'mongoose';
export const ItemSchema = new mongoose.Schema({
  title: String,
  is_completed: Boolean,
  description: String,
});

4. インターフェースの定義

次に、型チェックのためのインターフェースを用意します。

interfaces/todo.interface.tsファイルで定義しましょう。

import { Document } from 'mongoose';
export interface Item extends Document {
  id?: string;
  title: string;
  description?: string;
  is_completed: boolean;
}

5. DTOの作成

最後に、DTO(Data Transfer Object:データ転送オブジェクト)を作りましょう。このオブジェクトは、ネットワーク上でオブジェクトからオブジェクトへデータをどのように送ったり渡したりするかを定義します。

スキーマと同じプロパティを持つ基本的なクラスになります。

// ./dto/create-todo.ts
export class CreateItemDto {
  readonly title: string;
  readonly description: string;
  readonly is_completed: boolean;
}

6. モデル/サービスのセットアップ

サービスファイルはMongoDBデータベースとのやり取りを行います。先ほど作成したtodosスキーマからレコードを作成、取得、更新、削除するために使います。

サービスファイルを開き、次のコードを追加してください。

import { Injectable } from '@nestjs/common';
import { Todo } from './interfaces/todo.interface';
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { CreateTodoDto } from './dto/create-todo.dto';

@Injectable()

export class ItemsService {
  constructor(@InjectModel('Todo') private readonly todoModel: Model) {}
  async findAll(): Promise<Todo[]> {
    return await this.todoModel.find();
  }
  async findOne(id: string): Promise {
    return await this.todoModel.findOne({ _id: id });
  }
  async create(item: CreateItemDto): Promise {
    const newTodo = new this.todoModel(item);
    return await newTodo.save();
  }
  async delete(id: string): Promise {
    return await this.todoModel.findByIdAndRemove(id);
  }
  async update(id: string, todo: CreateTodoDto): Promise {
    return await this.todoModel.findByIdAndUpdate(id, todo, { new: true });
  }
}

上のコードは、Mongooseモデルを使ってMongoDBデータベースへのアクセスを確保する、APIのCRUD(作成、読み込み、更新、削除)アプリケーションを表しています。

次に、すべてのロジックを処理し、上記で作成したサービスと通信するコントローラファイルを作成します。

7. コントローラの設定

コントローラは受信するリクエストを処理し、レスポンスをクライアントに返します。

Todoコントローラを定義しましょう。次のコードを貼り付けてください。

import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
} from '@nestjs/common';
import { CreateTodoDto } from './dto/create-todo.dto';
import { TodosService } from './todos.service';
import { Todo } from './interfaces/todo.interface';

@Controller('items')

export class ItemsController {
  constructor(private readonly todosService: TodosService) {}

  @Get()
  findAll(): Promise<Todo[]> {
    return this.todosService.findAll();
  }
  
  @Get(':id')
  findOne(@Param('id') id): Promise {
    return this.todosService.findOne(id);
  }
  
  @Post()
  create(@Body() createTodoDto: CreateTodoDto): Promise {
    return this.todosService.create(createTodoDto);
  }
  
  @Delete(':id')
  delete(@Param('id') id): Promise {
    return this.todosService.delete(id);
  }
  
  @Put(':id')
  update(@Body() updateTodoDto: CreateTodoDto, @Param('id') id): Promise {
    return this.todosService.update(id, updateTodoDto);
  }
}

例えば、RESTful APIのPut、Delete、Post、Getの各ルート(@Put(),@Delete(),@Post(),@Get())にそれぞれ対応するアノテーションを提供することで、フレームワークのルーティングシステムを処理します。

8. PostmanでAPIをテストする

最後に、作成したばかりのAPIをPostmanでテストしてみましょう。本番サーバーにデプロイする前に、開発用サーバーを起動してすべてが問題なく機能していることを確認する必要があります。

npm run start:dev

Postmanをダウンロードして実行すれば、RESTful APIをテストできます。

Nest.jsのToDoリストを実行した結果
Nest.jsのToDoリストの実行結果

まとめ

Nest.jsは強力なNode.jsフレームワークであり、TypeScriptをサポートする選択肢として現在非常に高い人気を誇ります。

Nest.jsは標準的な開発アーキテクチャと業界のベストプラクティスの採用を後押しします。これにより、開発者は繰り返しの発生するエンジニアリングプロセスを整理し、ビジネスロジックの開発に集中することができます。

このような利点により、AdidasやRocheなどの世界的企業がこのフレームワークを活用するに至っています。

今回は、Nest.jsの基礎と、それへの乗り換えが検討に値する理由をご説明しました。さらに、フレームワークの魅力を肌で感じるために、シンプルなToDoシステムをRESTfulで構築しました。

Nest.jsを今後のプロジェクトに導入するかどうか是非ご検討ください。