初心者向けNestJSによるバックエンド開発講座

# はじめに

NestJS、何それおいしいの？って方が、NestJSでバックエンドを開発することを通して、理解を深めます。
TypeScriptと呼ばれるプログラミング言語を使って、簡単な実装をします。

# そもそもバックエンドとは何か

フロントエンドは、ユーザには見える画面といった機能を指すイメージです。
一方、バックエンドは、ユーザには見えない機能を指すイメージです。
例えば、データベースからデータを取得・登録・削除するといった処理は、ユーザには見えないので、バックエンドの機能となります。
一方、取得したデータを画面に表示するといった処理はフロントエンドの機能です。


# バックエンドエンジニアとは

バックエンドエンジニアとは、一体何者なんでしょうか。こちらをご覧ください。

https://roadmap.sh/backend

バックエンドエンジニアのロードマップの例です。
ネットワークから始まり、プログラミングやデータベース、セキュリティなど幅広い知見が必要となります。

こちらは海外企業の役職レベル別の年収レンジが確認できるサイトです。
世界トップレベルのバックエンドエンジニアの給与って**半端ない**っすね…

https://www.levels.fyi/comp.html?track=Software%20Engineer&search=Back-End


# NestJSとは

[NestJS公式ドキュメント](https://docs.nestjs.com/)を引用します。

> Nest (NestJS) is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with and fully supports TypeScript (yet still enables developers to code in pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).

初学者向けにわかりやすく言い換えると、
**NestJSとは、Typescriptでバックエンドのプログラムを非常に効率良く開発できるもの**
というイメージです。


# NestJSの開発環境を準備する

NestJSを利用するためには、Node.jsがPCにインストールされている必要があります。
すなはち、ターミナルで**node -v**と叩くとバージョンが表示されることが必要です。
もしNode.jsをインストールすることでPC環境を汚したくない方は、こちらのWEBサービスを活用しましょう。

https://www.katacoda.com/courses/nodejs/playground


# NestJSの新規プロジェクトを作る

[公式ドキュメント](https://docs.nestjs.com/first-steps)の通りにセットアップを進めていきます。
まず、npmとは「Node Package Manager」の略称です。
世界中で作成されたモジュール（部品化したプログラム）を誰もが再利用できるようにしたものです。

```shell:ターミナル
npm i -g @nestjs/cli
nest new test-project #project-nameは自分で命名する。
# 今回npmを選択する
```

以下、npmコマンドを叩く様子。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/9ec19156-062c-7856-6dfc-bd6a86a23a5f.png)

以下、nestコマンドを叩く様子。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/1723f42c-29f9-33fe-8a71-963491126652.png)

以下、インストールが正常に完了すると以下が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/f4ac4cfc-a455-ab22-c507-00bef8fb28ae.png)

以下、ディレクトリおよびファイルが生成されていることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/1cca7141-aff2-7e6c-a051-a9b29bef6327.png)


# まずはプログラムを動かしてみる

以下のコマンドを実行します。

```shell:ターミナル
cd test-project # ディレクトリを移動
npm run start:dev # 開発モードで実行
```

ブラウザを開き、http://localhost:3000/ にアクセスします。以下のようにHello World!と文字列が返ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/33c8faa2-5313-08eb-9d38-587d1efefac2.png)

# ソースコードを見る

プロジェクトを新規作成されるとデフォルトでサンプルの機能が実装されています。
まず、src配下のapp.service.tsを開きます。
getHello()と呼ばれるHello World!という文字列を返す関数が存在することが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/f7065ee5-a8cf-a6e9-8659-0b47774b6416.png)


次にapp.controller.tsを開きます。
こちらはクライアントがアクセスしたURLに従って、サービスクラスの関数を呼び出しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/9f107569-e53e-fca0-cfac-bcdbd2452b2b.png)

このようにNestJSでは、**サービス**や**コントローラー**など、プログラムの責務を明確に分離することになります。
**責務を分離するため、プログラムを変更した際の影響範囲を極小化**することができます。
またNestJSでは、DI（Dependency Injection）と呼ばれるデザインパターンが使われます。
ここでは説明を割愛しますが、このDIによって、プログラムを疎結合にして依存性をなくすことができるため、テスト駆動開発が可能になるなどのメリットを享受できます。


# NestJSを理解する

こちらは公式ドキュメントから抜粋したNestJSを構成する要素です。

- Controller
- Provider
- Module
- Middleware
- Exceptiopn filters
- Pipes
- Guard
- Interceptors
- Custom decorator

今回利用する以下３つの要素について簡単に説明しておきます。

- Controller：クライアントからのリクエストを受けて、レスポンスを行う。
- Provider：ビジネスロジックなどを提供する。
- Module：部品化することで、再利用できるようにする。

詳しくは公式ドキュメントを一読ください。

# 新しくバックエンドの機能をつくる

新たなバックエンドの機能を追加します。
今回は、ユーザ情報を登録・取得する機能を作ってみます。
**nest g**は**nest genarate**のショートカットコマンドです。
以下のコマンドを叩くことで機能のベースをつくります。

```sh:ターミナル
cd test-project
nest g module users
nest g controller users --no-spec
nest g service users --no-spec

```

新しくディレクトリおよびファイルが生成されたのを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/c88baed2-b6f4-4853-a076-c0ec03e205de.png)

# Modelを実装する

*※本来はData Transfer Object （DTO）と呼ばれるデザインパターンで実装するのが一般的ですが、今回は初心者向けのため割愛します。*

ユーザ情報のデータモデルをつくります。
と、その前にClass validatorと呼ばれるバリデータ用ライブラリを導入します。
導入方法は[公式ドキュメント](https://docs.nestjs.com/pipes)に従います。
バリデータとは、簡単に言うと「文字列であること」や「何文字以上であること」など、データ属性を保証するために使うものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/7e51d96f-6d6a-09c5-2040-7afdedde7753.png)


```sh:ターミナル
# バリデータ用ライブラリを導入する
npm i --save class-validator class-transformer

# ユーザ情報のデータモデル（空のファイル）を作成する
touch src/users/user.ts

```

```typescript:src/users/users.ts
import { IsString, MinLength, MaxLength } from 'class-validator';
export class User {
    @IsString()
    @MinLength(1)
    @MaxLength(20)
    readonly name: string;

    @IsString()
    @MinLength(6)
    @MaxLength(20)
    readonly password: string;
}

```

# Serviceを実装する

```typescript:src/users/users.service.ts
import { Injectable } from '@nestjs/common';
import { User } from './user';

@Injectable()
export class UsersService {

    users: User[] = [];

    create(user: User) {
        this.users.push(user)
    }

    findAll() {
        return this.users
    }
}

```

# Controllerを実装する

```typescript:src/users/users.controller.ts

import { Body, Controller, Get, Post, ValidationPipe } from '@nestjs/common';
import { User } from './user';
import { UsersService } from './users.service';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  findAll() {
    return this.usersService.findAll();
  }
  @Post()
  create(@Body(ValidationPipe) user: User) {
    return this.usersService.create(user);
  }

}

```

# 実装したものを動かしてみる


```sh:ターミナル
npm run start:dev
```


```sh:ターミナル

# 空のユーザー情報がレスポンスされる
curl http://localhost:3000/users

# ユーザ情報をPOST
curl -X POST -H "Content-Type: application/json" -d '{"name":"John","password":"1234567"}' http://localhost:3000/users 

# 先程のPOSTしたユーザ情報がレスポンス
curl http://localhost:3000/users 
```

ユーザ情報がレスポンスされる様子
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/2caeaa40-76d6-c5e8-88c6-fe4d9f6f5973.png)


# おわりに

実際の開発では、フロントエンドやデータベースなどの機能との連携が必要になってきます。
今回は、NestJSで簡単なバックエンドの機能をつくることで、NestJSの理解を深めることを目的に執筆しました。

以上です。