第7章 実践パターン
更新日:2025年12月17日
1. ログ
1.1 console.logの問題点
開発中は`console.log`でデバッグすることが多いが、実務では不十分である。
Table 1. console.logの問題点
| 問題 | 説明 |
|---|---|
| 残らない | サーバー再起動で消える |
| いつか分からない | タイムスタンプがない |
| どこか分からない | ファイル名・行番号がない |
| 重要度が分からない | 警告なのかエラーなのか区別できない |
1.2 ログレベル
ログには重要度を示す「レベル」がある。
Table 2. ログレベル一覧
| レベル | 意味 | 例 |
|---|---|---|
| TRACE | 最も詳細。メソッドの出入りまで | login() メソッド開始 |
| DEBUG | 開発時の詳細情報 | ユーザーID=123でログイン試行 |
| INFO | 正常な動作の記録 | ログイン成功 |
| WARN | 警告(動作は継続) | 応答に3秒かかりました |
| ERROR | エラー(処理失敗) | ログイン失敗 |
| FATAL | 致命的(システム停止) | DB接続不可 |
1.3 出力レベルの設定
ログには2つの「レベル」の概念がある。
Table 3. 2つのレベル
| 種類 | 意味 |
|---|---|
| コードで指定 | 「このログはDEBUGレベルです」 |
| 設定で指定 | 「INFOレベル以上だけ表示しなさい」 |
Fig. 1 フィルタリングの仕組み
設定:ログレベル = INFO(INFO以上を表示) コードが出力しようとするログ: [TRACE] ... → 表示されない(INFO未満) [DEBUG] ... → 表示されない(INFO未満) [INFO] ... → 表示される ✓ [WARN] ... → 表示される ✓ [ERROR] ... → 表示される ✓ [FATAL] ... → 表示される ✓
1.4 環境による切り替え
Table 4. 環境別設定
| 環境 | 設定レベル | 表示されるログ |
|---|---|---|
| 開発環境 | DEBUG | DEBUG, INFO, WARN, ERROR, FATAL |
| テスト環境 | DEBUG | DEBUG, INFO, WARN, ERROR, FATAL |
| 本番環境 | INFO | INFO, WARN, ERROR, FATAL |
コードは変えず、設定だけで表示されるログを切り替えられる。
1.5 Node.jsでの実装
const winston = require('winston');
// 環境変数でレベルを切り替え
const level = process.env.LOG_LEVEL || 'info';
const logger = winston.createLogger({
level: level,
format: winston.format.combine(
winston.format.timestamp(),
winston.format.printf(({ timestamp, level, message }) => {
return `[${level.toUpperCase()}] ${timestamp} - ${message}`;
})
),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'app.log' })
]
});
// 使用例
logger.debug('詳細情報'); // DEBUGレベル
logger.info('ログイン成功'); // INFOレベル
logger.warn('応答が遅い'); // WARNレベル
logger.error('ログイン失敗'); // ERRORレベル
1.6 Javaのログ設定(参考)
Javaのログ設定は複雑である。歴史的経緯により複数のライブラリが存在する。
Table 5. Javaのログライブラリ
| 名前 | 種類 | 説明 |
|---|---|---|
| java.util.logging | 実装 | Java標準 |
| Log4j / Log4j2 | 実装 | 老舗。広く使われた |
| Logback | 実装 | Log4j作者の改良版 |
| SLF4J | インターフェース | 統一API。実装は別途選ぶ |
Fig. 2 SLF4Jと実装の関係
SLF4J(インターフェース)
│
│ どれか1つを選ぶ
↓
┌─────────┬─────────┬─────────┐
│ Logback │ Log4j2 │ JUL │
│ (実装) │ (実装) │ (実装) │
└─────────┴─────────┴─────────┘
コードはSLF4Jで書き、実装は設定で差し替えられる。
2. デバッグ
2.1 デバッグの方法
Table 6. デバッグ方法の比較
| 方法 | 説明 | 用途 |
|---|---|---|
| console.log | 値を出力して確認 | 簡単な確認 |
| デバッガ | 1行ずつ実行して確認 | 複雑な問題 |
| ログ分析 | 記録されたログを調べる | 本番環境の問題 |
2.2 デバッガの利点
Table 7. デバッガの機能
| 機能 | 説明 |
|---|---|
| ブレークポイント | 任意の行で停止できる |
| ステップ実行 | 1行ずつ進められる |
| 変数確認 | 全変数の値を一覧で見られる |
| コールスタック | どの関数から呼ばれたか分かる |
| 式の評価 | 停止中に任意の式を実行できる |
2.3 デバッガの操作
Table 8. VS Codeのデバッグ操作
| 操作 | キー | 説明 |
|---|---|---|
| 続行 | F5 | 次のブレークポイントまで進む |
| ステップオーバー | F10 | 次の行へ(関数の中には入らない) |
| ステップイン | F11 | 次の行へ(関数の中に入る) |
| ステップアウト | Shift+F11 | 現在の関数を抜ける |
| 停止 | Shift+F5 | デバッグ終了 |
2.4 デバッグパネル
Table 9. デバッグパネルの役割
| パネル | 役割 | 使うタイミング |
|---|---|---|
| VARIABLES | 変数の値を見る | 常に |
| CALL STACK | 呼び出し階層を見る | 「どこから来た?」 |
| BREAKPOINTS | ブレークポイント管理 | 複数設置時 |
| WATCH | 任意の式を評価 | 「この条件は?」 |
2.5 ステップイン問題の対処
F11(ステップイン)でライブラリの中に入ってしまい迷子になることがある。
Table 10. 対処方法
| 方法 | 操作 |
|---|---|
| ステップアウト連打 | Shift+F11を繰り返す |
| ブレークポイント+続行 | 戻りたい行にブレークポイント → F5 |
| コールスタック利用 | 自分のコードをクリックして戻る |
VS Codeでは`skipFiles`設定でnode_modules等をスキップできる。
// .vscode/launch.json
{
"skipFiles": [
"<node_internals>/**",
"node_modules/**"
]
}
3. モック
3.1 モックとは
モックとは「本物の代わりになる偽物」である。テスト時に外部システムへの接続を避けるために使用する。
3.2 なぜモックが必要か
本物のシステムでテストする問題点を整理する。
Table 11. 本物のシステムでテストする問題
| 問題 | 説明 |
|---|---|
| 実際に実行される | テストで発注 → 本当に届く |
| コストがかかる | 実際の請求が発生 |
| 環境依存 | メンテナンス中はテストできない |
| 再現性がない | 状態が毎回違う |
3.3 Node.jsでのモック実装
// 本物の関数
async function order(productId, quantity) {
const response = await fetch('https://api.example.com/order', {
method: 'POST',
body: JSON.stringify({ productId, quantity })
});
return response.json();
}
// モック(テスト用)
async function orderMock(productId, quantity) {
return {
success: true,
orderId: 'TEST-001',
message: '発注完了(モック)'
};
}
// 環境変数で切り替え
const orderFunction = process.env.NODE_ENV === 'test'
? orderMock
: order;
3.4 Playwrightでのモック
Playwrightにはネットワークリクエストをモックする機能がある。
// 特定のAPIをモック
await page.route('**/api/order', route => {
route.fulfill({
status: 200,
body: JSON.stringify({
success: true,
orderId: 'MOCK-001'
})
});
});
// この後のページ操作では、/api/order への通信がモックされる
await page.click('#order-button');
3.5 モックの種類
Table 12. モックの種類
| 種類 | 説明 | 用途 |
|---|---|---|
| モック | 偽の実装を用意 | 外部API、DB |
| スタブ | 固定値を返す | 単純なテスト |
| スパイ | 呼び出しを記録 | 「何回呼ばれたか」確認 |
4. 設定管理
4.1 ハードコードの問題
// 悪い例:ハードコード const dbHost = 'localhost'; const dbPort = 3306; const apiKey = 'abc123';
Table 13. ハードコードの問題
| 問題 | 説明 |
|---|---|
| 環境ごとに変えられない | 開発と本番でDBが違う |
| セキュリティ | APIキーがコードに残る |
| 変更のたびにビルド | 設定変更でデプロイが必要 |
4.2 環境変数
// 環境変数から読み込む const dbHost = process.env.DB_HOST; const dbPort = process.env.DB_PORT; const apiKey = process.env.API_KEY;
# 開発環境 DB_HOST=localhost DB_PORT=3306 node app.js # 本番環境 DB_HOST=prod-db.example.com DB_PORT=3306 node app.js
4.3 .envファイル
環境変数をファイルにまとめる方法である。
# .env DB_HOST=localhost DB_PORT=3306 API_KEY=abc123
// dotenvパッケージを使用
require('dotenv').config();
const dbHost = process.env.DB_HOST;
重要:.envはGitに含めない(.gitignoreに追加)。代わりに.env.exampleを用意する。
# .env.example(Gitに含める) DB_HOST= DB_PORT= API_KEY=
4.4 設定管理の使い分け
Table 14. 設定方法の使い分け
| 方法 | 用途 |
|---|---|
| 環境変数 | 秘密情報(APIキー、パスワード) |
| .envファイル | ローカル開発用の環境変数管理 |
| config.json | 秘密でない設定(ポート番号、URL等) |
5. まとめ
Table 15. 第7章のまとめ
| 概念 | 内容 |
|---|---|
| ログレベル | TRACE/DEBUG/INFO/WARN/ERROR/FATAL |
| ログ設定 | 環境ごとに出力レベルを切り替え |
| デバッガ | ブレークポイント、ステップ実行、変数確認 |
| デバッグ操作 | F5続行、F10オーバー、F11イン、Shift+F11アウト |
| モック | 本物の代わりになる偽物 |
| 設定の外部化 | 環境変数、.env、config.json |
本コンテンツは2025年12月時点の情報に基づいて作成されています。Node.jsおよび関連ツールは活発に開発が進められており、APIや機能が変更される可能性があります。最新情報は公式ドキュメントをご確認ください。