Lesson 1

はじめに

Lesson 1 Chapter 1
Node.jsとは

この教材では、Node.jsを使用したWebアプリケーションの開発手法を学びます。

Node.jsを使えば、JavaScriptをRubyやPHP、Pythonと同じバックエンドの言語として記述できます。開発コストを下げ、エンジニアの負担を減らす上で、フロントエンドとサーバーサイドの言語を一本化できることは大きなメリットです。

教材の前半では、Node.jsの仕組みや環境構築について学びます。その後、TypeScript、Nest.jsを用いたアプリケーションの開発手法について学びます。。

最終的には、上記のソフトウェアを活用し、簡単なWebアプリケーション(Todoアプリ)を作成します。最後のLessonを終える頃には、セキュリティやロギングなども含め実践的な知識が身についているはずです。

Node.jsの概要

Node.jsは、サーバーサイドで動作するJavaSciprt実行環境のひとつです。従来はWebブラウザの中だけで動いていたJavaScriptを、独立したプログラムとして動かす目的で開発されました。

実行環境とは

人間が書いたプログラムをコンピューターが理解できる形に変換し、コンピューター上で実行してくれる環境のこと。

当初はWebアプリケーションのバックエンドを構築するために作られたNode.jsですが、今では様々な場面での活用が進んでいます。具体的には、以下の使用シーンが想定されるでしょう。

  • 軽量で堅牢なWebサーバーの構築
  • リアルタイム処理が必要なWebアプリの開発
  • ハイブリット型スマートフォンアプリの開発
  • IoT分野における組み込み制御の開発

このように多用途で用いられるのも、Node.jsが大量処理・リアルタイム処理に長けているからこそです。JavaScriptによるWeb開発の経験がある人にとっては、学習コストが大幅に抑えられる点もメリットと言えるでしょう。

Node.jsが動く仕組み

Node.jsは、JavaScriptエンジン「V8」を使って作られています。

JavaScriptエンジンとは

JavaScriptのコードを機械語にコンパイルし、実行するためのプログラムのこと。

V8は、Google社が開発したJavaScriptエンジンです。オープンソースとして公開されており、 以下の通り「Google Chrome」ほか多くのWebブラウザで使われています。

ブラウザ・ソフトウェア 搭載されているJavaScriptエンジン
Google Chrome V8
Microsoft Edge Chakra | V8
Firefox SpiderMonkey
Opera V8
Safari JavaScript Core

このV8エンジンを組み込むことで、Node.jsはJavaScriptの実行環境を提供しています。サーバーにNode.jsをインストールすることで、JavaScriptを動作させられるという仕組みです。

まとめ

今回はNode.jsの概要について学びました。

繰り返しになりますが、Node.jsはサーバーサイドにおけるJavaScript実行環境のひとつです。軽量で高負荷の処理に長けており、サーバーだけでなくスマホアプリやIoTの分野でも使われています。

Node.jsのメリット

  • Node.jsによってサーバーサイドでJavaScriptを動作させられる
  • JavaScriptひとつでフロントエンドとバックエンド両方の開発が可能になる

Node.jsを扱えるようになれば、JavaScriptを使ってWebアプリケーションの開発が可能になります。今後のLessonを通して、ぜひ実践的な知識を身につけてください。

Lesson 1 Chapter 2
Expressとは

この教材では、Node.jsのフレームワーク「Nest.js」を使った開発方法を学びます。「Nest.js」は「Express.js」をさらに使いやすくしたフレームワークのため、このチャプターではExpress.jsについて学んでおきましょう。

Node.jsの登場はそれだけで革新的なものでしたが、その人気を後押ししたのが秀逸なフレームワークの存在です。Vue.jsやReactといったフレームワークが脚光を浴びたことは、Node.js自体の発展に大きく寄与しました。

Expressは、同じNode.js製フレームワークの中でも最古参にあたります。利用者が多く、日本語の情報も溢れているため、初学者には最適のフレームワークといえるでしょう。

実際の導入に移る前に、ここではExpressの概要を述べておきます。

Expressの概要

express-website.png Express

Express.jsは、Node.js上で動作するWebアプリケーションのフレームワークです。

そもそも「フレームワーク」とは、アプリケーション開発に必要な機能をまとめて提供するパッケージを指します。文字通り「枠組み」として、Webアプリケーションを開発する上での基本構成を用意してくれるものです。

様々なフレームワーク

フレームワークはExpress以外にも様々あります。有名なところでは、JavaScriptのフロントエンドの開発で使われることの多いVueや、 Pythonでの開発で使われるDjango、Flaskなどがあります。 言語やフロントエンド・バックエンドなどの違いによって使用できるものが異なるので注意してください。

Expressの特徴

Expressの主な特徴として、ここでは以下の3点を紹介します。

  • 機能が最小限に絞られていて軽量である
  • 日本語の情報が豊富にあり学習しやすい
  • EJSとの連携によりフロント開発も容易

以下でそれぞれ見ていきましょう。

機能が最小限に絞られていて軽量である

Expressは、必要最小限の構成であることを理念に掲げています。したがって、他のフレームワークに見られるような機能(テンプレートエンジンやORMなど)は標準搭載されていません。

コア機能として提供されているのは、あくまでルーティングによる動的なWebページの設計です。

機能が絞られている分、Expressは軽快に動作します。サーバーの処理を高速化したい場合、Expressは十分な期待に応えてくれるはずです。

日本語の情報が豊富にあり学習しやすい

Expressには長い歴史があるため、日本語のドキュメントが豊富に見つかります。

インターネット上のコミュニティやブログでは、初学者向けの情報が分かりやすくまとまっています。Node.jsの入門書では、構築の手段としてExpressが採用されていることも少なくありません。

特にこれからNode.jsを学ぶ場合、フレームワークにExpressを選ぶことで学習コストを抑えられます。

EJSとの連携によりフロント開発も容易

すでに述べた通り、EJSには最低限の機能しかありません。

機能が絞られているからといって、Expressを使っていて不便に感じることは少ないでしょう。そもそもNode.jsには、豊富な外部パッケージが提供されているためです。

npmを介して必要なパッケージを揃えることで、開発者のスタイルに合わせたカスタマイズが可能です。

Lesson 1 Chapter 3
NestJSとは

NestJSは大きく以下の特徴を持つNode.jsのフレームワークです。

NestJSの特徴

  • expressをコアとして作られている
  • TypeScriptで作られているためTypeScriptが標準仕様となっている
  • Angularのアーキテクチャに影響を受けていると共に、DDD(domain-driven design:ドメイン駆動設計)を採用している
  • Dependency Injection(依存性の注入)デザインパターンを採用している

browser_lesson1-ch3.png NestJS公式

expressをコアとして作られている

NestJSはexpressをコアとして作られています。なのでexpressで可能なことはNestJSでも可能です。expressのノウハウを活かしつつ高品質なソフトウェア開発が可能です。たとえば以下のようにexpressからRequestオブジェクトをインポートして使用できます。

import { Controller, Get, Req } from '@nestjs/common';
// expressからimport
import { Request } from 'express';

@Controller('cats')
export class CatsController {
  @Get()
  // 使用箇所
  findAll(@Req() request: Request): string {
    return 'This action returns all cats';
  }
}

TypeScriptで作られているためTypeScriptが標準仕様となっている

NestJSのプロジェクトを立ち上げるとすべてTypeScriptの拡張子で書かれていることに気づきます。NestはTypeScriptで開発されており、使用時もTypeScriptが基準としてプロジェクトがスタートします。TypeScriptを用いることでNestの良さを活かした型安全な開発を行うことができます。

editor_lesson1-ch3.png 初期ファイル群

Angularのアーキテクチャに影響を受けていると共に、DDD(domain-driven design:ドメイン駆動設計)を採用している

ReactやVueと並ぶフロントエンドフレームワーク「Angular」のアーキテクチャに影響を受けると共にDDDを採用しています。Angularからの影響として「デコレーターを使った開発」や「疎結合なモジュール間を意識したディレクトリ構成やファイルの命名規則」等があります。また「featuresモジュール」と呼ばれる機能単位ごとで設計を行うことからDDD(ドメイン駆動設計)を採用していると言えます。ドメインを簡単に説明するとアプリケーションの機能における部分領域のことで「ユーザー」や「TODO」や「商品」等を意味します。実際の機能に基づいてアプリケーションの設計を行っていくことをDDD(ドメイン駆動設計)と呼びます。NestJSは「バックエンドJavaScriptでアーキテクチャの問題をクリティカルに解決する技術がない」という課題から生まれました。AngularアーキテクチャやDDDを採用することで、課題を解決し可読性・保守性に優れたWEB開発を行うことが可能になりました。

疎結合

「疎結合」という言葉に聞き馴染みない人がいるかもしれません。疎結合を簡単に説明すると「互いに独立しており依存していないこと」です。反対の言葉に「密結合」があります。意味は疎結合の反対です。あるモジュールに変更を加えたら他のモジュールにも変更を加える必要がある状態は「密結合な状態」です。この状態は開発者の関心ごとが増えバグを生みやすくするため良い状態とはされていません。ソフトウェア開発ではなるべく疎結合な状態を目指すべきです。

DDDについて注意

DDDを詳細に説明しようとすると1Chapterだけではとても足りない量になってしまうため今回はとてもざっくり解説しています。DDDをしっかり理解したい方は書籍や他記事等で補うようお願いいたします。

Dependency Injection(依存性の注入)デザインパターンを採用している

NestJSは通称「DI」と呼ばれるデザインパターンを採用しています。デザインパターンとは開発をする上で従うべき設計指標です。Dependency Injectionについては「Lesson4 chapter10 Injectableの意味(依存性の注入/他クラスに関数を提供できる)」に解説のページがあるため詳しくは割愛しますが、簡単に説明すると「疎結合なモジュール間同士で開発を行うために設計されたデザインパターン」のことです。DIはNestJSだけでなく他の言語でもよく用いられます。そしてNestJSはDIを基盤に置いてますが私たちがそれを意識する必要もなく使えてしまいます。私たちはフレームワークの御作法に則るだけです。DIを意識する必要はありません。お作法に則ることでNestJSが勝手にDIを実現してくれます。それもNestJSの良さと言えるでしょう。

まとめ

ここまでNestJSの主な特徴を挙げました。他にもテスティングライブラリが標準で搭載されていたり、CLIでの開発が便利だったりさまざまな特徴を持っています。これからしっかりとNestJSを学んでいきましょう。

Lesson 1 Chapter 4
MVCモデルとは

MVCモデルとはプログラムをアプリケーション上の役割に分割して開発する考え方の1つです。MVCはディクレトリの組み方やファイルの命名などの指標となります。MVCは「Model、View、Controller」の頭文字からきています。ビジネスロジックを扱う「Model」と画面表示を担う「View」とリクエストレスポンスに応じてそれらに命令を下す司令塔の「Controller」が役割として存在します。

mvc_lesson1-ch4.png MVCモデル

Model

mvc_lesson1-ch4-2.png Modelについて

Modelではビジネスロジックを記述します。また、DBへのアクセスを行いデータ参照や作成なども担います。Controllerから渡されたクライアント(画像だとPC)からのパラメーターを受け取り適切に処理します。Controllerにはビジネスロジックに通したデータを渡します。NestJSでは「Service」や「Repository」がModelに該当します。

ビジネスロジックとは

ビジネスロジックとはアプリケーションの要件に合わせた独自ロジックのことをそう呼びます。たとえば別々の2つのアプリケーションに「決済」という抽象機能があるとします。この抽象機能の具体的実装はアプリケーションの要件によって異なるかもしれません。割引額が違ったり、アプリケーション内で使用している決済サービスが違ったり、一定額を寄付に回したりなどさまざまです。そしてそれらが複雑に絡み合います。そのようにアプリケーションそれぞれの要件に合わせた独自ロジックをビジネスロジックと呼びます。

View

mvc_lesson1-ch4-4.png Viewについて

ViewはHTMLを生成して画面表示を行う責務を担います。ModelからのデータがController経由で渡されるためそのデータをHTMLに嵌め込み動的にHTMLを生成します。NestJSでは「views」というディレクトリを切ってその中でView領域のファイルを記述します。

点線の矢印について

Viewの矢印を点線にしているのは実際にはControllerからクライアントへ返されるからです。クライアントからのリクエストに応じてControllerがデータとともにView領域のファイルをレスポンスします。

Controller

mvc_lesson1-ch4-3.png Controllerについて

ControllerはMVCモデルにおける中核を担います。いわば司令塔です。1番大事な業務として「ルーティング」があります。ルーティングはリクエストとレスポンスを処理することです。リクエストに応じてModelへ適切な命令を下し、Modelから返却されたデータをViewに渡しクライアントへ返却します。クライアントからのリクエストは必ずここを通ります。Controllerがどこに処理を移すべきか判断を下す必要があるからです。NestJSでは「Controller」がその役目を担います。

ファットコントローラーに気を付ける

ファットコントローラーとは余計な処理を書きすぎて肥大化したコントローラーのことです。余計な処理とは本来コントローラーに書くべきではない処理のことで、Modelで書くべきロジックをコントローラーに書いてしまうパターンが挙げられます。コントローラーは極力シンプルに保つほうが良いとされているためコントローラーがファットになってきた時はロジックを書く場所を疑うようにしましょう。

3層アーキテクチャ

MVCモデルに合わせて3層アーキテクチャというものを解説します。3層アーキテクチャとは設計を行うときアプリケーションの構造を3つの層に分割する考え方です。元はアプリケーションを構築する上で必要な物理サーバーなどのアーキテクチャとして定義づけられています。今回、この考え方をWebアプリケーションのバックエンドアーキテクチャに置き換えた話をします。MVCとかなり似ていますが、MVCよりもバックエンドの実装に寄り添ったアプリケーションの層の分け方となっています。また、MVCを補完する目的で3層アーキテクチャを用います。

3層アーキテクチャは「プレゼンテーション層、ビジネス層、データアクセス層」に分類されます。MVCとの関係を見るとMVCはプレゼンテーション層に寄った設計であることがわかります。なぜならMVCにはデータアクセス層が明確に定義づけられていないからです。それぞれ詳細に解説しつつMVCとの関係を見ていきます。

役割
プレゼンテーション層 クライアントとのやり取りを行う。クライアントの要求をビジネス層に伝える。MVCでは ViewとControllerが該当。
ビジネス層 ビジネスロジックを記述する。データアクセス層とデータのやり取りを行う。MVCではModelが該当。
データアクセス層 データベースと直接やり取りを行う。MVCではModelが担うことがある。

arch_lesson1_ch4-1.png 3層アーキテクチャ

プレゼンテーション層

プレゼンテーション層はクライアントとのやり取りを担います。主な役割にルーティングがあります。また、画面表示のための情報を返します。プレゼンテーション層はクライアントからの情報をビジネス層に伝えます。そしてビジネス層が処理した情報をクライアントに返します。MVCではControllerとViewが、 NestJSではControllerがその役割を担います。

ビジネス層

ビジネス層はアプリケーションのコアなビジネスロジックを記述します。たとえばジャンケンゲームを作るとして、ジャンケンの勝敗を決めるための「ルール」のロジックを記述するのはこの層です。MVCではModelが、NestJSではServiceがその役割を担います。またデータアクセス層と連携してデータのやり取りを行います。

データアクセス層

データアクセス層はDBへアクセスしデータの操作を直接行います。ジャンケンゲームを作るとしてジャンケンの結果をDBに保存するのはデータアクセス層の役割になります。MVCで明確な定義づけはないもののModelで担うことが多いです。NestJSではRepositoryが担当します。

それぞれの変更は影響を及ぼさない

3層のどれかを変更したとして、他の層に影響が出るべきではありません。データアクセス層のDBがMySQLからPostgresqlへ変更されたからといってビジネス層からデータアクセス層への接続のしかたを極力変えるべきではありません。ビジネス層はDBが何であるかは知る必要がないからです。データアクセス層の関心をビジネス層まで持ち込むべきではありません。このように3層アーキテクチャやMVCを用いてアプリケーションを構築していくときそれぞれの層の役割を明確にし「疎結合」にアプリケーションを組んでいくのが壊れにくいアプリケーション開発につながります。

3層アーキテクチャまとめ

それぞれの解説でNestJSではどのファイルがどの層に当てはまるか簡単に触れました。改めてそれを図に表します。これを見てわかる通りNestJSは大きく分けて3ファイルでアプリケーションを構築します。その3ファイルをmoduleで統括します。そこへ要件に合わせたさまざまなファイルが組み合わさることになります。

Entity

詳しくは後章で解説しますがデータアクセス層とDBの間にEntityというものを設けました。EntityはDBのテーブル情報を持ったNestJSのクラスです。このクラス情報を参考にしつつRepositoryがDB操作を行います。

arch_lesson1_ch4-3.png 3層アーキテクチャ

Lesson 1 Chapter 5
本講における実装方針

Lessonを通してTODOアプリケーションを実装しながらNestJSを効率よく学んでいきます。下記がこれから作成するTODOアプリのアーキテクチャ図です。

browser_lesson1_ch5.png TODOアプリアーキテクチャ図

Client API ORM DB
Thunder Client NestJS TypeORM MySQL

使用技術

使用技術を解説します。

Thunder Client(Client)

VSCodeの拡張機能「Thunder Client」を使ってAPIにリクエストを飛ばします。今回MVCモデルを意識しながらの実装になりますが「View」に関しては実装しません。代わりに「Thunder Client」がリクエストを飛ばす役割を担ってくれます。昨今のアプリケーション開発ではReactやVueといったSPA構築のためのフロントエンドフレームワークで画面表示を行うため、「View」のようにHTMLを返すというよりはJSONとしてデータをクライアントに返すのが一般的になってきています。

SPA

SPAは「シングルページアプリケーション」の略です。「シングル」の主語はHTMLです。1枚のHTMLでバックエンドからデータだけをもらいJavaScriptで画面表示を切り替えることで、素早いページ遷移を行うことができてユーザー体験が向上します。SPAを構築することを「CSR(クライアントサイドレンダリング)」といい、クライアントのJavaScriptを用いてHTMLを作り上げていくことからそう呼ばれています。

NestJS(API)

本講座のメインであるNestJSを使ってAPIを作成します。TypeScriptで書いていきます。

TypeORM(ORM)

ORMにTypeORMを使用します。ORMは「オブジェクトリレーショナルマッパー(マッピング)」の略です。DBのデータ構造とオブジェクト指向のデータ構造をマッピングし、オブジェクト指向言語のメソッドを使ってDB操作を可能にしてくれる仕組みを提供してくれる技術のことです。そのためORMを使用するときはDBへのクエリ文を書くことはほとんどありません。すべてメソッドによってDB操作を行います。たとえば以下のような記述で「全件取得」ができてしまいます。

ORM例
async findAll(): Promise<User[]> {
  // findメソッドで全件取得
  return await this.usersRepository.find();
}

ORMは言語に限らずさまざまなものが存在します。JavaScriptだけでも複数存在します。その中でも今回はTypeORMというORMを使用します。TypeORMはTypeScriptで開発されており型安全であること、NestJS公式サイトにも例が載っており広く使われていることから採用しています。

TypeORMについて注意事項

最近TypeORMが0.3系にバージョンアップしたことから破壊的変更がいくつか加わりました。そのためネットの記事の内容ではうまくいかないことが多々あります。本講座でもバージョン違いでうまくいかないことがあるかもしれません。本講座では「0.3系」を使用するのでネットの記事を参照する際はバージョンにご注意ください。

MySQL(DB)

RDBと呼ばれるDBの代表格で、テーブル間でリレーション(関連)を持たせ開発を行います。Expressの講座を受講した方は触れているかと思います。詳細は割愛します。

NestJSの基礎概念の習得

環境構築を終えた後、NestJSの基礎概念習得を目的としたChapterが続きます。「module」や「entity」といったNestJSで扱うメイントピックを1つずつコードを交えながら紹介します。

DBとの連携

MySQLと接続を行なって本格的にアプリケーション開発を行います。TypeORMもここから本格的に使用します。ExpressのLessonではクエリを書いていたので違和感を覚えるかもしれませんがORMに慣れていきましょう。ここでは基本的なCRUD操作をメインに学習します。TODOアプリケーションの土台はこのLessonである程度できあがります。

NestJSを深く知る

このLessonを通して「DBとの連携」までに作ったTODOアプリケーションを補強します。具体的には以下のような実装を行います。アプリケーション開発を行う上でどれも必須の知識となるためしっかりと身につけましょう。これで実装方針として以上になります。次のChapterから環境構築を行なっていきましょう。

実装一覧

  • ミドルウェア
  • 認可
  • バリデーション
  • エラー処理
  • テスト

TODOアプリの実装方針

TODOアプリの実装方針を説明する上で注意事項

実装方針を説明する上で今Chapter以降解説する用語を多々用います。解説の目的は相関図を頭に入れていただくことなので知らない用語については深く考えず今後のChapterで1つずつ理解してください。

講座を通して作成していくTODOアプリケーションの実装方針を解説します。前回ChapterでMVCと3層アーキテクチャを解説しました。それらの概念をNestJSのディレクトリやファイル構成に当てはめて考えていきます。

MVCと3層アーキテクチャの関係性

前回Chapterから3層アーキテクチャはMVCを内包したアーキテクチャといえます。そのためNestJSの設計については3層アーキテクチャを中心に話を進めていきます。

3層アーキテクチャとアーキテクチャ図

3層アーキテクチャと今回実装するアーキテクチャ図の関係図です。赤の枠線の範囲はNestJSが担当する領域です。EntityはDBのテーブル情報をクラスで保持します。またDBの通信はTypeORMが担い、その際にEntityの型情報を参照します。クライアントをThunder Clientで代用します。DBはMySQLが担当します。

arch_lesson1_ch5-1.png 3層アーキテクチャとアーキテクチャ図

NestJSと3層アーキテクチャ

今回作成するファイルと3層アーキテクチャの関係図です。Todoアプリを作成するのでtodo.module.tsがtodoに関する領域を統括します。todo.module.tsはプレゼンテーション層でありクライアントの窓口になるtodo.controller.tsとビジネス層でありTodoアプリのビジネスロジックを担当するtodo.service.tsをTodoモジュール内の層として管理します。

また、パッケージからTypeORMモジュールとデータアクセス層のtodo.repository.tstodo.service.tsDIします。DIは日本語で「依存性の注入」と訳されます。詳細については下記「DIについて」をご覧ください。目的は「疎結合なモジュール関係」を実現することです。TypeORMモジュールをDIするのはRepositoryからDBへ接続するためです。

また、データ型を使用するためにEntityを各層から参照します。こちらは型情報のみの参照となります。

arch_lesson1_ch5-2.png NestJSと3層アーキテクチャ

DIについて

今後「モジュールを他モジュールへと適用すること」を「DI」と呼称します。DIはDependency Injectionの略です。DIは日本語で「依存性の注入」と呼ばれます。DIは疎結合なモジュールを開発するためのデザインパターンでクラス設計の際にとくに用いられます。DIについて詳しくは本講の最後「Lesson4 Chapter10 Injectableの意味(依存性の注入/他クラスに関数を提供できる)」にて解説していますので気になる方は先にそちらをお読みください。

ディレクトリ構成について

今回作成するTODOアプリのディレクトリ構成は下記になります。現段階では最低限必要なディレクトリのみ明記しており、今後「DBとの連携」や「NestJSを深く知る」で必要に応じて増やします。ポイントとしては「module」や「service」や「controller」などファイルの役割ごとにディレクトリが分かれている点です。「service」や「controller」を「module」で統括しつつ進めていきます。todoモジュールはどのように格納するかを例として挙げています。

ディレクトリ構成
src
  controllers
  entities
  modules
    todo
      todo.module.ts
  repositories
  services

まとめ

以上がこれから作るTodoアプリケーションの大まかな関係図になります。関係図に登場していないファイルも登場しますが今後必要に応じて解説します。この構成は最低限崩れることがないので常に頭の片隅に置きながら実装を進めてください。それでは解説を交えながらTodoアプリの作成を頑張っていきましょう。