このブログは未経験からのエンジニア転職やプログラミングの勉強方法などを発信する、現役エンジニアによるエンジニアのためのトータル技術ブログです。ブログとご一緒にSNSのフォローもよろしくお願いします。

Twitterをフォローする

【NestJS】環境構築しながら基本を学ぶ

NestJS
スポンサーリンク

こんにちは、あっきー(IwswAkht)です。

フロントエンドでTypeScriptが有名になってきてる近年、ついにTypeScriptで動くバックエンドのフレームワーク「NestJS」が登場しました。

同時にNestJSでの開発プロジェクトに携わる機会があり、インプットする機会にも恵まれました。せっかくインプットしたので合わせてアウトプットもしていこうということで記事を書いていきます。

今回は環境構築をしながら、NestJSの基本的な構造などを中心に話ていきます。
NestJSをさわってみようかなと思ってる方はぜひこの記事に雰囲気を掴んでいただけたらと思います。

それでは、よろしくお願いします。

スポンサーリンク

NestJSとは

まずは、NestJSの特徴です。以下にまとめました。

  • Node.js上で動作するオープンソースのバックエンド開発フレームワーク
  • TypeScriptで作られているので基本TypeScriptで開発するもの
  • Expressをコアに作られている
  • Express + NestJS特有の機能も使うことができる
  • AngularにインスパイアされているのでAngluarに似ているところが多い

NestJSのメリット

NestJSを使うメリットを以下にまとめました。

  • TypeScriptで開発するので型つけることができる
  • Expressの機能やライブラリも使用できる
  • Nest CLIを使ってプロジェクトやファイルのテンプレートを作成できる
  • テストフレームワークが標準で用意されている
  • 拡張性が高く、RDB、NoSQL、セキュリティ、GraphQL、WebSocketなどに対応
  • Angularにインスパイアされてるので一緒に使うと学習コストが下がる
  • AngularとNestJSのmonorepo構成にすることでフロントエンド、バックエンド両開発の学習コストを下げる

NestJSのデメリット

もちろんデメリットもあります。以下にまとめました。

  • 他のフレームワークと比較してまだ情報が少ない
  • 公式ドキュメントも日本語対応していない

Nest CLIとは

Nest CLIとはNestJSのコマンドラインインターフェースです

例えばLaravelのlaravel newであったりRuby on Railsのrails newであったり。

フレームワーク特有のコマンドでプロジェクトフォルダを作成できたりするのですが、それのNestJSバージョンです。

Nest CLIでプロジェクトフォルダの作成

Nest CLIでまずは空っぽのプロジェクトフォルダを作成してみましょう。

前提として、以下の環境は既に導入済みとします。

今回はnpmでの導入方法になります。
テキストエディタはお好みのもので構いませんが、特段理由がないようでしたらVSCodeを使うことをお勧めします。

ターミナルよりNest CLIのパッケージをインストールします。

ターミナル

お好みの名前でプロジェクトフォルダを作成し移動します。

ターミナル

移動したフォルダ先でNestJSのプロジェクトフォルダを作成します。project-nameはお好みの名前を設定ください。

ターミナル

これで完了です。プロジェクトフォルダ配下に空のNestJSプロジェクトが作成されたことが確認できます。

各種ファイルの概要

それぞれのファイルがどんな役割があるのかざっと確認します。

フォルダ全体の構成は以下になります。(node_modulesは省略してます)

ターミナル

それぞれのファイルの概要を以下にまとめます。

ディレクトリ、ファイル名 概要
node_modules プロジェクトに依存しているライブラリ群
.eslintrc.js ES Lintの設定ファイル
.prettierrc コード整形を行うprettirの設定ファイル
nest-cli.json Nestの設定を上書きしたり、追加するためのファイル
package-lock.json ライブラリの依存情報が記載されたファイル
package.json ライブラリの管理ファイル
src プロダクションコードを格納するディレクトリ
app.controller.spec.ts appモジュールのコントローラのテストファイル
app.controller.ts appモジュールのコントローラファイル
app.module.ts 全モジュールの親にあたるファイル
app.service.ts appモジュールのサービスファイル
main.ts 最初に読み込まれるファイル
test テストコードを格納するディレクトリ
app.e2e-spec.ts e2eテストコードファイル
jest-e2e.json jestの設定ファイル
tsconfig.build.json TypeScriptの設定ファイル
tsconfig.json TypeScriptの設定ファイル

NestJSの基本構造

NestJSは基本、機能単位でモジュールを作成します。

1つのモジュールは原則以下の3ファイルによって構成されます。

  • Controller
  • Service
  • Repository

それぞれの役割を説明していきます。

Controllerファイルの作成

Controllerの役割はクライアントからのリクエストを受け付け、クライアントにレスポンスを返すことです。

要はルーティングの役割を担うファイルです。

ルーティングをするファイルになりますので、ロジックにあたる処理は書かないでそれらのプログラムはServiceに実装するのが一般的です。

なのでControllerには原則、ルーティングとServiceを呼び出す記述以外は書くことはないです。

Controllerの記述例は以下になります。

usersController

基本は@Controller()デコレータを付与しController全体のルーティングを行います。

先の例だとUsersController/usersのパスにアクセスされた時に起動するControllerという意味になります。

Controllerでのルーティングをしたらクラス内の各メソッドに対してHTTPメソッドを定義します。

先の例だとindex()メソッドに@Get()デコレータを付与することでHTTPリクエストGETで/usersのパスにアクセスした時はindex()を実行するという意味合いになります。

また、Nest CLIでControllerの雛形ファイルを作成することができます。コマンドは以下です。

ターミナル

上記コマンドの実行結果としてusers.controller.tsusers.controller.spec.tsのファイルが作成されます。

テストファイルを作成しない場合は--no-specオプションを末尾に付与してあげてください。

Serviceファイルの作成

Serviceはビジネスロジックを定義するファイルです。

先ほどControllerはルーティング以外の記述は書かないと言いましたので、細かい処理はこのServiceに書いていくイメージですね。

Serviceの書き方などを見る前に、まずServiceを使う上で理解しておきたい大事な概念がありますのでそちらを先に説明します。

それがDI(Dependency Injection)です。

直訳すると依存性の注入です。よくわからないですよね。

もう少しプログラムの言葉で表現すると依存関係のあるオブジェクトを外部から渡すことをDIと言います。

まだ、わかりづらいですよね。例を出しつつもう少し詳しくいきます。

まず、依存関係のあるオブジェクトとはなんでしょうか。

例えば、UsersControllerのビジネスロジックを書いているUsersServiceが存在するとします。

このUsersControllerUsersServiceが存在しないと正しく動作クラスです。

このようなある特定のプログラムがないと対象のプログラムを動かすことができないような状況を依存関係があるオブジェクトと言います。

次に外部から渡すとはどういうことでしょうか。

外部から渡さない例を見てみます。
UsersServiceはクラスなのでどこかでインスタンス化しなければいけません。

インスタンス化を以下のようにController内でインスタンス化したとします。

Controller

クラス内で別のクラスをインスタンス化する。このような書き方を外部から渡さないと言います。

これでもプログラム的には全然問題はないです。
ただ、例えばDBの向き先であったり、ログの出力先の定義などをテスト環境と本番環境で別々にするという環境によって違う実装が必要になるケースが存在したとします。

この場合、テスト環境用のServiceクラスで実装し、本番環境にアップする時に本番用のServiceクラスの実装に書き換える必要がでたりしてプログラム間の依存度を高めてしまいます。

このような事象を回避するためにServiceは外部でインスタン化し、Controllerに渡すように設計された考え方がDIと言います。

DIすることで依存元のプログラムを書き換えることなく依存先のプログラムを切り替えられるようになり依存性を低くすることができるというメリットがあります。

DIの概要はこの辺にして実際にNestJSでDIする流れを確認します。

まずServiceの書き方の例は以下です。

Service

クラスに@injectable()デコレータを付与します。
これでDI可能なクラスになります。

このクラスをモジュールに登録します。

モジュールの例は以下です。

Module

DIするにはprovidersにServiceクラスを登録します。この記述だけでNestJSが自動でDIしてくれるようになります。

あとは使いたいクラスのコンストラクタで受け取るようにしてあげれば完了です。

Controller

また、Nest CLIでServiceの雛形ファイルを作成することができます。コマンドは以下です。

ターミナル

上記コマンドの実行結果としてusers.service.tsusers.service.spec.tsのファイルが作成されます。

テストファイルを作成しない場合は--no-specオプションを末尾に付与してあげてください。

Repositoryの作成

Repositoryはデータベースへの参照や作成、更新、削除などのいわゆるCRUD処理を記述するためのファイルになります。

データベース処理なので別途接続設定が必要になります。
今回、データベースについては詳しくふれないので簡単に概要だけ確認します。

まず、Repositoryの記述例は以下です。

Repository

Repositoryには@EntityRepository()デコレータを付与します。

引数に渡してるUserは簡単に言えばデータベースのテーブル内容を定義したファイルです。

デコレータにテーブルの情報を渡してデータベース処理を記述するクラスがRepositoryということだけを今回は理解しておいてもらえばオッケーです。

Module化する

ここまでの流れで確認してきたControllerServiceRepositoryを1つのモジュールとしてまとめます。

これで1つの機能を備えたモジュールの完成です。

記述例としては以下になります。※Repositoryの記述は除外してます。

Module

その他の設定のプロパティ含め以下が概要になります。

  • providers:Serviceなど@injectableデコレータがついたクラスを指定e
  • controllers:@controllerデコレータがついたクラスを記述
  • imports:Repositoryなどモジュール内部で使いたい外部モジュールを記述
  • exports:外部モジュールとしてエクポートしたいものを記述

また、Nest CLIでModuleの雛形ファイルを作成することができます。コマンドは以下です。

ターミナル

上記コマンドの実行結果としてusers.module.tsのファイルが作成されます。

今回はController→Service→Repository→Moduleの順番で説明しましたが、実際に実装をする時はこの流れとは逆で最初にModuleを作成すると思います。
最初にModuleを作成した場合、後続のServiceやControllerをNest CLIで作成した場合、自動でModuleの方が更新されます。

appモジュールに登録

1つの機能を持ったモジュールが作成されたら最後にappモジュールにそのモジュールを登録します。作ったモジュールは最終的にこのappモジュールに登録する必要があります。

以下、記述例です。

app.module.ts

Nest CLIコマンドでモジュールを作成した場合はコマンド実行された段階で対象のモジュールはこのappモジュールに登録されているので気にしなくて良いのですが、もし手動でモジュールファイルを作成した時などはappモジュールに登録する必要があるということを忘れないでください。

全体構造を確認

appモジュールに各機能ごとにモジュールが登録されたら最後はmain.tsで読み込まれます。

これによりアプリケーション全体にモジュールの機能が適応されます。

main.tsの内容を確認してみます。

main.ts

appモジュールがインポートされてポート3000でリスンされていることが確認できますね。

こんな感じでmain.tsをプログラムのスタート地点として→appモジュール→各機能モジュール→機能モジュールの実装

という設計で開発していくのがNestJSの基本構造になります。

図解すると以下のようなイメージです。

ここまでの内容を踏まえて最後にHello world して終了しましょう。

Hello Worldしてみる

以下のコマンドを順番に実行して必要なファイルを作成します。

ターミナル

./src/helloフォルダは以下にhello.modules.tshello.controller.tshello.service.tsが作成されたことを確認します。

確認できましたら各ファイルに以下の編集を加えます。

hello.controller.ts

hello.controller.ts

修正したらnpm startでローカルサーバを起動し、http://localhost:3000/helloにアクセスしてHello World!が出力されればOKです。

さいごに

さいごまで読んでいただきありがとうございます。

NestJSの全体像が少しは見えましたでしょうか。

NestJSが今後バックエンドでベターなフレームワークとして浸透するのかなどはわかりませんが、個人的に使ってみた所感としてはシンプルな設計でさくっとAPIサーバ立てるならNestJSが最適だなという感じでした。

まだまだ日本語情報が少なくこれからふれる人は苦労する場面も多いだろうなと思うので引き続きNestJSの記事は多めに書いてみなさんの役に立ったらいいなと思ってますので引き続きよろしくお願いします。

この記事を気に入っていただけましたらTwitterでもプログラミングに関してのツイートをリアルタイムでしていますので
ご一緒にフォローもお願いします。

IT転職ならレバテック!

僕は未経験からSESの企業にエンジニアとして転職し、その後はフリーラン、現在は受託開発企業に転職しました。

エンジニアとしていろいろな働き方を経験し、いろいろな転職サイトや転職エージェントの方にお話を伺いました。

その経験の中でだいじだと感じたことは、ITに特化した転職エージェントのサービスを利用することです。

幅広い業界に対応した転職エージェントはIT転職に特化したエージェントと比べると紹介先の数が少ないです。

そのため希望してない紹介先に転職し、思ってたのと違うとなることもあります。

そうならないためにエンジニアを目指すなら必ずIT特化の転職サービスを登録し、たくさんの選択肢の中から自分が行きたいと思う企業を探してください

僕はフリーランスでの案件探し、受託開発企業の転職の時もレバテックのかたに紹介していただきました。

とても満足できましたので皆さんもぜひ利用してみてください!

\無料のIT系転職サービス/

/優良案件がたくさん\

スポンサーリンク
あっきー

元キャバクラ店長から未経験でエンジニアに転職した異端児。

自分の経験を元に、エンジニア転職や未経験からでも挫折しないプログラミングの勉強方法の発信をしてます。

あっきーをフォローする
NestJSNode.js
\良い記事だったらシェアしてね!/
スポンサーリンク
駆け出しエンジニアのつぶやき