はじめに
この連載では、NestJSを使ってシンプルなブログアプリを開発しながら、Webアプリケーション開発の基礎から運用までを段階的に学んでいきます。
最終的には、投稿された記事をReactで表示できるシンプルなUIを備えたブログアプリを完成させ、Dockerによるローカル開発環境や、NeonなどのマネージドDBを用いた本番環境へのデプロイまで扱います。
NestJSは、TypeScriptベースで構築されたNode.jsのフレームワークで、Angularのようなモジュール構造を持ち、拡張性や保守性に優れた設計が可能です。
この特性を活かしながら、実際に動くアプリケーションを一歩ずつ作り上げていきましょう。
この連載で作るもの
- NestJSを用いたブログ投稿API
- Prismaを使った型安全なDB操作
.env
を使い分けた環境ごとの設定管理- ログ・エラーハンドリング・テストといった運用を意識した構成
- 最後にReactでブログ記事を表示し、Docker構成を用いて本番環境へデプロイ
この連載の全体像と今回の位置づけ
連載構成(予定)
- NestJSで始めるWebアプリ開発 ─ ブログサイトを作りながら学ぶプロジェクト構成と設定管理 ←
今回の記事
- NestJSで記事投稿APIを作ろう ─ Prisma導入とCRUD実装の基本
- アプリの信頼性を高める ─ ロギング・例外処理・テスト戦略
- PrismaとDB設計を深掘る ─ モデル・リレーション・運用設計
- ReactでUIを構築して本番へデプロイ ─ Dockerと環境構築
この記事(第1回)では、NestJSプロジェクトのセットアップと、今後の開発を支える「設定管理の基盤作り」をテーマに進めていきます。
シンプルな「Hello World」だけでなく、今後の構成を見据えた.env管理やディレクトリ設計まで丁寧に扱います。
対象読者と学べること
この連載は、次のような方を想定しています
- NestJSに興味があり、実用的なアプリを通して学びたい方
- PrismaやDockerなど、モダンな開発ツールを一緒に使いたい方
- Webアプリを「とりあえず動かす」ではなく、設計や運用まで含めて学びたい方
- Reactやフロントは後回しで、まずAPIやバックエンドの基盤をしっかり作りたい方
NestJSの基本から始めて、実際に使える構成で動くアプリケーションを完成させることを目指します。
プロジェクトの全体像と使用技術
この連載で構築するアプリケーションは、NestJSを中心に、データベースやフロントエンド、そして本番運用まで見据えた構成を取り入れたブログシステムです。
「シンプルな記事投稿・表示」を題材にしながらも、現場でも使える設計・運用ノウハウが自然に身につく構成を目指しています。
NestJSとは?
NestJSは、TypeScriptベースで構築されたNode.js向けのWebアプリケーションフレームワークです。
Angularにインスパイアされたモジュール構造とDI(依存性注入)コンテナを備え、シンプルなAPIからスケーラブルなマイクロサービスまで対応できます。
NestJSの主なメリットとしては以下が挙げられます。
- アーキテクチャが明快で拡張しやすい
- TypeScriptが前提なので、型安全な開発ができる
- PrismaやGraphQL、Swaggerなどモダンな周辺技術との親和性が高い
- ロギング、例外処理、設定管理、テストなどが最初から整理しやすい構成
使用技術スタック一覧
項目 | 技術 | 用途 |
---|---|---|
フレームワーク | NestJS | API設計・バックエンドの基盤 |
ORM | Prisma | DBスキーマ管理と型安全な操作 |
データベース | PostgreSQL(Docker) | ローカル開発用DB |
DBホスティング | Neon / PlanetScale | 本番環境用マネージドDB |
設定管理 | @nestjs/config | .env を通じた環境ごとの設定管理 |
フロント | React(+ Vite) | ブログ記事を表示するUI部分 |
テスト | Jest + Supertest | 単体テスト・E2Eテスト |
デプロイ | Docker / Render | 開発・本番環境の運用と公開 |
開発から本番までの構成イメージ
NestJSアプリはローカルのホスト環境で直接起動し、Dockerコンテナ化されたPostgreSQLと接続して開発を行います。
最終的には、Reactで構築したブログUIをNestJS経由で配信し、DockerコンテナとしてRenderなどにデプロイします。DBも外部サービス(Neon)を使い拡張性を考慮した構成にします。
ローカル環境
本番環境
NestJSのプロジェクトを作成しよう
ここから、実際にNestJSのプロジェクトを立ち上げていきます。
NestJSにはNest CLIという公式ツールが用意されており、数コマンドで初期構成が整ったプロジェクトを作ることができます。
このCLIを使えば、ディレクトリ構成やTypeScriptの設定なども自動でセットアップしてくれるため、スムーズに始められるのが魅力です。
Nest CLIのインストール
まずは、Nest CLIをグローバルにインストールします。
※すでにインストール済みの方は、nest --versionでバージョン確認してスキップしてOKです。
npm install -g @nestjs/cli
-g
は「グローバルインストール」の意味です。これにより、どのプロジェクトからでも nest コマンドが使えるようになります。
プロジェクトを作成する
次に、CLIを使ってプロジェクトを新規作成します。
今回は nestjs-blog
という名前でプロジェクトを作ってみましょう。
nest new nestjs-blog
すると、次のような対話形式の質問が表示されます。
Which package manager would you ❤️ to use?
❯ npm
yarn
pnpm
- いつも使っているもの(例:
npm
)を矢印キーで選んでEnterを押します。 - すると、自動的に必要な依存パッケージがインストールされます。
プロジェクトの中に入ってみる
作成されたディレクトリに移動します。
cd nestjs-blog
中には、すでにNestJSの基本構成が整っています。
nestjs-blog/
├── src/
│ ├── app.controller.ts ← ルーティング(URLの処理)
│ ├── app.module.ts ← アプリ全体の構成を定義
│ ├── app.service.ts ← ビジネスロジックを書く場所
│ └── main.ts ← エントリーポイント(アプリの起動処理)
├── test/ ← テストコード
├── package.json ← 依存パッケージの一覧
└── tsconfig.json ← TypeScriptの設定
アプリを起動してみる
次に、NestJSアプリを起動して動作確認をしてみましょう。
開発用のホットリロード付きで立ち上げます。
npm run start:dev
成功すれば、次のようなメッセージが表示されるはずです。
この状態で、ブラウザで http://localhost:3000 にアクセスしてみてください。
「Hello World!」という文字列が表示されていれば、無事にNestJSアプリが起動しています!🎉
ここまでのまとめ
- Nest CLIを使えば、複雑な設定不要でNestJSアプリがすぐ立ち上がる
- TypeScriptやディレクトリ構成もすでに整っている
- ブラウザで「Hello World!」が出れば、準備完了!
次のセクションでは、作ったプロジェクトを今後の開発に耐えられるような設計に整えていくために、環境変数や設定管理について掘り下げていきます。
ディレクトリ構成の基本とモジュール設計
NestJSのプロジェクトは、明確な責務分離と拡張性を意識したディレクトリ構成が特徴です。
はじめて見ると「ファイルが多いな」と感じるかもしれませんが、それぞれに意味があり、理解して使いこなせば非常にスッキリとした開発体験になります。
この章では、最初に作成された構成を紐解きながら、NestJSの設計思想に触れていきましょう。
NestJSの標準的な構成を理解する
Nest CLIでプロジェクトを作成すると、src/
ディレクトリ以下は次のような構成になっています。
src/
├── app.controller.ts // ルーティングの定義
├── app.module.ts // アプリ全体の構成(モジュールの登録)
├── app.service.ts // ビジネスロジック(処理の本体)
└── main.ts // エントリーポイント(アプリの起動)
これらの役割は以下の通りです。
ファイル | 役割 |
---|---|
main.ts |
アプリケーションを起動する(NestFactory.create()など) |
app.module.ts |
アプリのモジュールをまとめる中心。各機能を登録するハブ |
app.controller.ts |
HTTPリクエスト(ルーティング)を受け取る窓口 |
app.service.ts |
実際の処理・ビジネスロジックを担う場所 |
AppModuleとは何か?
NestJSでは、すべての機能は「モジュール」という単位で構成されます。
AppModule はその中でも「ルートモジュール(= アプリ全体の入口)」として位置づけられており、以下のような役割を果たします。
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
imports
: 他のモジュールをここに読み込む(例:DatabaseModuleやPostsModuleなど)controllers
: このモジュールが持つコントローラー(ルーティング担当)providers
: サービスやユーティリティなど、DI(依存性注入)されるクラスたち
すべてのモジュールは最終的にAppModuleに登録されることでNestJSに認識されます。
Controller / Service の責務
NestJSは、ControllerとServiceを明確に分けることで、責任の分離(Separation of Concerns)を徹底しています。
役割 | 担当 | 実装ファイル例 |
---|---|---|
Controller | ルーティングと入力の受付 | app.controller.ts |
Service | ビジネスロジック・処理の実行 | app.service.ts |
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
Controllerは「ルーティングやパラメータの処理」までに留め、処理の本体は必ずServiceに委ねる。これにより、以下のようなメリットが得られます。
- 責任が明確になり、テストや保守がしやすい
- ロジックをControllerに書かないので、コードが読みやすくなる
- Serviceを再利用できる(複数のControllerやイベント処理でも)
モジュール単位の構成が基本
NestJSでは、機能ごとに「○○Module」単位で分けるのが推奨されます。
src/
├── posts/
│ ├── posts.module.ts
│ ├── posts.controller.ts
│ └── posts.service.ts
├── users/
│ ├── users.module.ts
│ └── ...
このように整理することで、規模が大きくなっても見通しの良いコードベースが維持できます。
ここまでのまとめ
- NestJSは「モジュール」を中心に構成されるアーキテクチャ
- AppModule がルートとなり、機能単位のモジュールをまとめて管理する
- ControllerとServiceを分けて責任を明確にすることで、テストや拡張が容易に
環境変数の管理と設定ファイルの分離
現代のWebアプリケーションでは、「コードに環境依存の値(DBのURLやAPIキーなど)を埋め込まない」ことが基本です。
NestJSでも .env
ファイルによってこれを実現できますが、より高度に扱うためには @nestjs/config
パッケージの導入が推奨されています。
このセクションでは、開発・本番・テスト環境を意識した環境変数の管理方法と、その活用パターンについて解説します。
@nestjs/config
パッケージのインストール
npm install @nestjs/config
これにより、.env
ファイルを自動的に読み込み、アプリ全体で共通して使える ConfigService
が使えるようになります。
.env
ファイルを作成する
まず、プロジェクトルートに .env
ファイルを作成し、次のような環境変数を定義してみます。
# .env(開発環境用)
PORT=3000
DATABASE_URL=postgresql://bloguser:blogpass@localhost:5432/blogdb
.env.production
や.env.test
のように、環境ごとにファイルを分けておくと後で便利です。
AppModule で設定モジュールを読み込む
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
+ import { ConfigModule } from '@nestjs/config'
@Module({
- imports[],
+ imports: [
+ ConfigModule.forRoot({
+ isGlobal: true,
+ envFilePath: ['.env'],
+ }),
+ ],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
isGlobal: true
を設定することで、各モジュールで毎回 ConfigModule をインポートしなくても ConfigService を使えるようになります。
ConfigService を使って値を取得する
環境変数が正しく取得できているか確認してみたいと思います。(動作確認後に書いた部分は削除します)
+ import { ConfigService } from '@nestjs/config'
@Injectable()
export class AppService {
- getHello(): string {
- return 'Hello World!';
- }
+ constructor(private configService: ConfigService) {}
+ getPort(): string {
+ return this.configService.get<string>('PORT') || '3001';
+ }
}
configService.get
を使うことで読み込んだ環境変数の値を使用できます。
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
- return this.appService.getHello();
+ return this.appService.getPort();
}
}
これで http://localhost:3000/ にアクセスすると、PORT の値(3000)が画面に出てきて確認できます。
環境ごとに .env ファイルを切り替える
本番・開発・テストなど、実行環境によって設定を切り替えたい場面は必ず出てきます。
NestJSでは、NODE_ENV 環境変数の値に応じて .env
ファイルを出し分けることで、これを柔軟に実現できます。
ConfigModule.forRoot({
isGlobal: true,
envFilePath: [
`.env.${process.env.NODE_ENV}`,
'.env',
],
}),
これにより、実行環境で NODE_ENV を設定すれば自動的に適切な.envが読み込まれます。
# 開発環境
NODE_ENV=development npm run start:dev
# 本番環境(ビルド後)
NODE_ENV=production node dist/main.js
process.env.NODE_ENV
はNode.js標準の環境変数です。CI/CDやDocker上でも制御できます。
.env
ファイルは Git に含めないようにする(NestJSの既定を活かす)
NestJSのプロジェクトを Nest CLI で生成すると、.gitignore にはすでに次のような .env 関連の設定が追加されています。
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
これによって、以下のような機密性の高い設定ファイルはGitにコミットされないようになっています。
ファイル名 | 役割の例 |
---|---|
.env | デフォルトの開発用設定 |
.env.production.local | 本番サーバー固有の秘密設定(DBのURLなど) |
.env.local | 開発者ごとのローカル個別設定(チーム内で共有しない) |
.env.example
を追加して共有の指針を示す
実際に運用するうえでは、Gitに含めることを前提にした「ひな形ファイル」を用意しておくのが推奨されます。
# .env.example
PORT=3000
DATABASE_URL=
これにより、他の開発者がプロジェクトをクローンしたときも「どんな環境変数が必要か」が明確になります。
フロントエンドを含めたモノレポ構成に移行
既存のNestJSバックエンドプロジェクトに対し、将来的にフロントエンドを追加できる構成にリファクタリングする方法を紹介します。ここでは モノレポ構成として frontend/
・backend/
を並べるシンプルな形に整理します。
この構成にしておくことで、
- フロント・バックの役割が明確になる
- DockerやCI/CDの設定が整理しやすくなる
- プロジェクトの拡張性が高まる
などのメリットがあります。
新しいディレクトリ構成イメージ
your-project-root/
├── backend/ # NestJS + Prisma
│ ├── src/
│ ├── prisma/
│ ├── .env
│ └── ...
├── frontend/ # Next.js や React(後ほど追加予定)
│ └── ...
├── docker/ # 共通のdocker構成(必要に応じて)
├── docker-compose.yml
└── README.md
backend/
にまとめる)
移行手順(バックエンドを backend/
ディレクトリを作成
mkdir backend
NestJSプロジェクトの中身を移動
rsync -av --progress ./ ./backend \
--exclude .git --exclude .vscode --exclude backend
移動ができたら、いらなくなったファイルの削除
find . -maxdepth 1 ! -name '.' ! -name '..' ! -name '.git' ! -name '.vscode' ! -name 'backend' -exec rm -rf {} +
最後に確認
ls -a
最終的にトップディレクトリがこうなれば完了。
.
..
.git
.vscode
backend
動作確認
cd backend
npm run start:dev
この状態で、ブラウザで http://localhost:3000 にアクセスして、「Hello World!」という文字列が表示されていれば、無事にNestJSアプリのディレクトリ移動は完了です。
おわりに
設定値が正しく取得できているかを一度明示的に確認しておくことは、NestJS に限らずどんな開発でも大切なプロセスです。とくに、環境変数は「取れているつもり」で進めてしまうと、後々原因不明の不具合として表面化することがあります。
今回のように、PORTなどの値を一時的に画面に表示して確認するのは、地味ですが確実な習慣づけのひとつです。そして同時に、設定の取得ロジックを Controller に書くか Service に委ねるかという設計上の判断も、初期段階から意識しておきたい重要なポイントです。
開発初期だからこそ、小さな確認や設計判断を丁寧に行うことが、後の安心と品質につながります。先を急がず、まずは足元を固めながら進めていきましょう。
次回:NestJSの構成と設計原則に向き合う
今回取り上げた環境変数の扱いや、責務を意識した構成は、あくまでスタートラインにすぎません。
チーム開発においては「何をどこに書くべきか」という構造的な判断こそが、長期的な品質と保守性を左右します。
次回は、NestJSの標準的なディレクトリ構成とモジュール設計の考え方を整理しつつ、
- AppModuleの役割と構成の基準
- Controller / Service / Moduleの責務と設計分離
- 将来的な拡張を見据えたスケーラブルな初期設計のあり方
といった実践的なテーマに踏み込んでいきます。
プロジェクトの初期設計における判断が、どのように後の開発スピードとチーム内の理解度に影響するのか。
一つひとつの構成に理由を持たせながら、健全なアーキテクチャの土台を築いていきましょう。
弊社の技術支援サービス
無駄なコストを削減し、投資対効果を最大化する
クラウド費用の高騰、不要なSaaSの乱立、開発工数の増加――これらの課題に悩んでいませんか?本サービスでは、クラウドコストの最適化、開発効率向上、技術選定の最適化 を通じて、単なるコスト削減ではなく、ROIを最大化する最適解 をご提案します。
shinagawa-web.com
最新技術の導入・検証を支援するPoCサービス
Remix、React Server Components、TypeScript移行、クラウドサービス比較、マイクロサービス、サーバーレス、デザインシステムなど、最新技術のPoC(概念実証)を通じて、最適な技術選定と導入を支援します。貴社の開発課題に合わせた検証・実装で、ビジネスの成長を加速させます。
shinagawa-web.com
開発生産性を最大化するための技術支援
開発チームの生産性向上、コードの品質管理、インフラの最適化まで、様々な側面からサポートします。コードベースのリファクタリングから、テスト自動化、オンボーディング強化まで、プロジェクトの成功に必要なすべての支援を提供。御社の開発現場が効率的に機能するように、技術的な障害を取り除き、スムーズな開発を実現します。
shinagawa-web.com
開発品質向上支援 – 効率的で安定したプロダクトを実現
フロントエンドからバックエンド、データベースまで、開発プロセス全体を最適化し、安定したプロダクト作りをサポートします。コードレビューの仕組み、型定義の強化、E2Eテスト環境の構築など、開発の各ステップにおけるベストプラクティスを導入することで、より効率的でバグの少ない、そしてユーザー満足度の高いサービス提供を支援します。
shinagawa-web.com
Webアプリのセキュリティ強化支援
Webアプリの脆弱性対策からインフラのセキュリティ強化まで、包括的なセキュリティ支援を提供。OWASP Top 10対策、JWT認証の最適化、APIのアクセス制御、依存パッケージの監査、セキュアコーディングの標準化など、実践的なアプローチで開発現場の安全性を向上させます。
shinagawa-web.com
目次
お問い合わせ