VSCode デバッグ機能で開発効率を最大化する

Visual Studio Code(VSCode)には、強力なデバッグ機能が標準搭載されています。console.logによるprintデバッグから脱却し、VSCode デバッグ機能を活用することで、バグの原因特定が格段に速くなります。

本記事では、VSCode デバッグの基本から、launch.jsonの設定方法、条件付きブレークポイント、ログポイント、変数ウォッチ、コールスタックの確認まで、実践的なデバッグ手法を網羅します。JavaScript、TypeScript、Pythonを例に、すぐに現場で活用できるデバッグテクニックを習得しましょう。

この記事で得られること

  • VSCode デバッグ機能の全体像と各コンポーネントの理解
  • launch.jsonによる言語別のデバッグ設定方法
  • 条件付きブレークポイントとログポイントの実践的な活用法
  • 変数ウォッチ、コールスタック、デバッグコンソールの使いこなし方

前提条件と実行環境

VSCode デバッグを始めるための環境を確認します。

項目 要件
VSCode バージョン1.85以上を推奨
Node.js 18.x以上(JavaScript/TypeScriptデバッグ用)
Python 3.10以上(Pythonデバッグ用)
拡張機能 Python Debugger(Python用)、その他言語別の拡張

必要な拡張機能

VSCode デバッグを始める前に、言語に応じた拡張機能をインストールしてください。

言語 必要な拡張機能 備考
JavaScript/TypeScript 不要(組み込み) Node.jsランタイムが必要
Python Python Debugger 自動インストール
Java Debugger for Java Extension Packに含まれる
C/C++ C/C++ Extension Microsoft公式

VSCode デバッグ機能のUIコンポーネント

VSCode デバッグのUIは、複数のコンポーネントで構成されています。それぞれの役割を理解することで、効率的なデバッグが可能になります。

デバッグサイドバー

デバッグサイドバーは、Ctrl+Shift+D(Mac: Cmd+Shift+D)で開きます。以下のセクションで構成されています。

セクション 役割
VARIABLES 現在のスコープ内の変数を表示
WATCH 監視対象として登録した式の値を表示
CALL STACK 関数の呼び出し履歴を表示
BREAKPOINTS 設定済みブレークポイントの一覧と管理
LOADED SCRIPTS 読み込まれたスクリプトファイルの一覧

デバッグツールバー

デバッグセッション中、エディタ上部に表示されるツールバーです。

graph LR
    A[続行 F5] --> B[ステップオーバー F10]
    B --> C[ステップイン F11]
    C --> D[ステップアウト Shift+F11]
    D --> E[再起動 Ctrl+Shift+F5]
    E --> F[停止 Shift+F5]
ボタン ショートカット 動作
続行/一時停止 F5 次のブレークポイントまで実行を継続
ステップオーバー F10 現在の行を実行し、次の行へ移動
ステップイン F11 関数内部に入って1行ずつ実行
ステップアウト Shift+F11 現在の関数を抜けて呼び出し元に戻る
再起動 Ctrl+Shift+F5 デバッグセッションを再起動
停止 Shift+F5 デバッグセッションを終了

デバッグコンソール

Ctrl+Shift+Yで開くデバッグコンソールは、REPL(Read-Eval-Print Loop)として機能します。デバッグ中に式を評価したり、変数の値を確認したりできます。

launch.jsonの基本構造と設定方法

launch.jsonは、VSCode デバッグの設定ファイルです。プロジェクトの.vscodeフォルダ内に配置し、デバッグ構成を定義します。

launch.jsonの作成方法

  1. デバッグサイドバーを開く(Ctrl+Shift+D
  2. 「create a launch.json file」リンクをクリック
  3. デバッガーの種類を選択

または、コマンドパレット(Ctrl+Shift+P)から「Debug: Open launch.json」を実行します。

基本的なlaunch.json構造

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "デバッグ構成の名前",
      "type": "デバッガーの種類",
      "request": "launch または attach",
      "program": "実行するファイルのパス",
      "args": ["コマンドライン引数"],
      "cwd": "${workspaceFolder}",
      "env": {
        "環境変数名": "値"
      }
    }
  ]
}

主要な設定プロパティ

プロパティ 説明
name デバッグ構成の表示名 "Launch Program"
type デバッガーの種類 "node", "debugpy", "chrome"
request 起動方法 "launch"(新規起動), "attach"(接続)
program 実行ファイルのパス "${workspaceFolder}/app.js"
args コマンドライン引数 ["--port", "3000"]
cwd 作業ディレクトリ "${workspaceFolder}"
env 環境変数 {"NODE_ENV": "development"}
envFile 環境変数ファイルのパス "${workspaceFolder}/.env"
console コンソールの種類 "integratedTerminal"

変数置換

launch.jsonでは、以下の変数が使用できます。

変数 展開される値
${workspaceFolder} ワークスペースのルートパス
${file} 現在開いているファイルのパス
${fileBasename} 現在開いているファイルの名前
${fileDirname} 現在開いているファイルのディレクトリ
${fileBasenameNoExtension} 拡張子なしのファイル名
${env:変数名} 環境変数の値

JavaScript/Node.jsのVSCode デバッグ設定

Node.jsのデバッグは、VSCode に組み込まれており、追加の拡張機能は不要です。

基本的なlaunch.json設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Node.js: Launch Program",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/src/index.js",
      "skipFiles": ["<node_internals>/**"],
      "console": "integratedTerminal"
    }
  ]
}

Auto Attach機能

VSCode には、統合ターミナルで実行されるNode.jsプロセスに自動的にデバッガーをアタッチする機能があります。

設定方法:

  1. コマンドパレットで「Toggle Auto Attach」を実行
  2. モードを選択:
    • smart: node_modules外のスクリプト実行時に自動アタッチ
    • always: すべてのNode.jsプロセスにアタッチ
    • onlyWithFlag: --inspectフラグ付きのプロセスのみ
1
2
3
4
5
6
7
// settings.jsonでの設定例
{
  "debug.javascript.autoAttachFilter": "smart",
  "debug.javascript.terminalOptions": {
    "skipFiles": ["<node_internals>/**"]
  }
}

JavaScript Debug Terminal

専用のデバッグターミナルを使用する方法もあります。

  1. コマンドパレットで「Debug: Create JavaScript Debug Terminal」を実行
  2. 開いたターミナルでnode app.jsを実行
  3. 自動的にデバッガーがアタッチされる

npmスクリプトのデバッグ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "npm: start",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "start"],
      "cwd": "${workspaceFolder}",
      "console": "integratedTerminal"
    }
  ]
}

nodemonとの連携

ファイル変更時に自動再起動するnodemonと連携する設定です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "nodemon: Launch",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "nodemon",
      "program": "${workspaceFolder}/src/index.js",
      "console": "integratedTerminal",
      "restart": true,
      "internalConsoleOptions": "neverOpen"
    }
  ]
}

TypeScriptのVSCode デバッグ設定

TypeScriptのデバッグには、ソースマップが重要な役割を果たします。

tsconfig.jsonの設定

デバッグを有効にするため、tsconfig.jsonでソースマップを有効化します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "commonjs",
    "outDir": "./dist",
    "rootDir": "./src",
    "sourceMap": true,
    "strict": true
  }
}

launch.json設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "TypeScript: Launch",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/src/index.ts",
      "preLaunchTask": "tsc: build - tsconfig.json",
      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
      "sourceMaps": true,
      "skipFiles": ["<node_internals>/**"]
    }
  ]
}

ts-nodeを使用したデバッグ

コンパイルなしで直接TypeScriptをデバッグする設定です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "ts-node: Launch",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "node",
      "runtimeArgs": [
        "-r",
        "ts-node/register"
      ],
      "args": ["${workspaceFolder}/src/index.ts"],
      "skipFiles": ["<node_internals>/**"],
      "sourceMaps": true
    }
  ]
}

ソースマップの問題解決

ブレークポイントがグレー表示(無効)になる場合、以下を確認してください。

症状 原因 解決方法
ブレークポイントがグレー ソースマップが見つからない outFilesパスを確認
別の行で停止 ソースマップのずれ tscでリビルド
まったく停止しない パス解決の問題 resolveSourceMapLocationsを設定
1
2
3
4
5
6
{
  "resolveSourceMapLocations": [
    "${workspaceFolder}/**",
    "!**/node_modules/**"
  ]
}

PythonのVSCode デバッグ設定

Pythonのデバッグには、Python Debugger拡張機能(debugpy)が必要です。Python拡張機能をインストールすると自動的にインストールされます。

基本的なlaunch.json設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: Current File",
      "type": "debugpy",
      "request": "launch",
      "program": "${file}",
      "console": "integratedTerminal",
      "justMyCode": true
    }
  ]
}

主要な設定オプション

オプション 説明 デフォルト
justMyCode 自分のコードのみデバッグ true
stopOnEntry プログラム開始時に停止 false
args コマンドライン引数 []
cwd 作業ディレクトリ ${workspaceFolder}
env 環境変数 {}
envFile .envファイルのパス なし
python Pythonインタープリタのパス 選択されたインタープリタ

モジュールとして実行

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: Module",
      "type": "debugpy",
      "request": "launch",
      "module": "mypackage.main",
      "justMyCode": false
    }
  ]
}

Flaskアプリケーションのデバッグ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: Flask",
      "type": "debugpy",
      "request": "launch",
      "module": "flask",
      "env": {
        "FLASK_APP": "app.py",
        "FLASK_DEBUG": "1"
      },
      "args": ["run", "--no-debugger", "--port", "5000"],
      "jinja": true
    }
  ]
}

Djangoアプリケーションのデバッグ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: Django",
      "type": "debugpy",
      "request": "launch",
      "program": "${workspaceFolder}/manage.py",
      "args": ["runserver", "--noreload"],
      "django": true
    }
  ]
}

リモートデバッグ

Dockerコンテナやリモートサーバー内のPythonプロセスにアタッチする設定です。

リモート側のコード:

1
2
3
4
5
6
import debugpy

debugpy.listen(("0.0.0.0", 5678))
print("Waiting for debugger attach...")
debugpy.wait_for_client()
debugpy.breakpoint()  # この行で停止

launch.json:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: Remote Attach",
      "type": "debugpy",
      "request": "attach",
      "connect": {
        "host": "localhost",
        "port": 5678
      },
      "pathMappings": [
        {
          "localRoot": "${workspaceFolder}",
          "remoteRoot": "/app"
        }
      ]
    }
  ]
}

ブレークポイントの種類と活用法

VSCode デバッグでは、複数の種類のブレークポイントを使い分けることで、効率的なデバッグが可能になります。

通常のブレークポイント

行番号の左側(ガター)をクリック、またはF9キーで設定します。

  • 赤い丸: 有効なブレークポイント
  • グレーの丸: 無効化されたブレークポイント
  • 白抜きの丸: 検証できないブレークポイント(ソースマップの問題など)

条件付きブレークポイント

特定の条件が満たされた場合のみ停止するブレークポイントです。

設定方法:

  1. ガターを右クリック → 「Add Conditional Breakpoint」を選択
  2. 条件式を入力
1
2
3
4
5
// 例: ループで特定の値のときだけ停止
// 条件式: i === 50
for (let i = 0; i < 100; i++) {
  processItem(items[i]);  // ここにブレークポイント
}

活用例:

シナリオ 条件式の例
特定のユーザーID user.id === 'admin'
エラー発生時 error !== null
配列の長さ array.length > 10
オブジェクトのプロパティ obj.status === 'failed'

ヒットカウントブレークポイント

指定回数だけ通過した後に停止するブレークポイントです。

設定方法:

  1. ガターを右クリック → 「Add Conditional Breakpoint」
  2. ドロップダウンから「Hit Count」を選択
  3. 条件を入力(例: >10, ==5, %3
構文 動作
5 または ==5 5回目で停止
>10 10回を超えたら毎回停止
<3 最初の2回のみ停止
%3 3回ごとに停止

トリガーブレークポイント

他のブレークポイントがヒットした後に有効になるブレークポイントです。

設定方法:

  1. ガターを右クリック → 「Add Triggered Breakpoint」
  2. トリガーとなるブレークポイントを選択

活用シナリオ:

  • 初期化処理完了後のみデバッグしたい
  • 特定のエラーハンドラー通過後の動作を確認したい

インラインブレークポイント

1行に複数の文がある場合、特定の位置で停止させるブレークポイントです。

設定方法: Shift+F9

1
2
// 3つの関数呼び出しがある行で、特定の位置に設定可能
const result = func1(a) + func2(b) + func3(c);

関数ブレークポイント

関数名を指定して、その関数が呼び出されたときに停止するブレークポイントです。

設定方法:

  1. BREAKPOINTSセクションの「+」ボタンをクリック
  2. 関数名を入力
// 入力例
processData
MyClass.prototype.render

ログポイントの活用

ログポイントは、コードを変更せずにログを出力できる機能です。console.logを追加してビルドし直す必要がなくなります。

ログポイントの設定

  1. ガターを右クリック → 「Add Logpoint」を選択
  2. ログメッセージを入力({}内は式として評価される)
// ログメッセージの例
User logged in: {user.name}
Processing item {index} of {total}: {item.name}
Current state: {JSON.stringify(state)}

ログポイントの利点

利点 説明
コード変更不要 ソースを編集せずにログ出力
実行継続 停止せずにデバッグコンソールに出力
条件付き 条件式と組み合わせ可能
本番調査 本番環境での調査に活用可能

条件付きログポイント

ログポイントにも条件を設定できます。

// メッセージ
Error occurred: {error.message}

// 条件(Condition)
error !== null && error.code >= 500

変数ウォッチとデータインスペクション

VARIABLESセクション

デバッグ中、VARIABLESセクションには以下のスコープが表示されます。

スコープ 内容
Local 現在の関数内のローカル変数
Closure クロージャで参照されている変数
Global グローバルスコープの変数

変数の操作

操作 方法
値の確認 変数名にホバー
値の変更 右クリック → 「Set Value」またはF2
コピー 右クリック → 「Copy Value」
式としてコピー 右クリック → 「Copy as Expression」
ウォッチに追加 右クリック → 「Add to Watch」

WATCHセクション

特定の式を継続的に監視する機能です。

活用例:

1
2
3
4
5
// ウォッチに追加する式の例
user.permissions.includes('admin')
items.filter(i => i.status === 'active').length
Object.keys(cache).length
performance.now() - startTime

変数のフィルタリング

Ctrl+Alt+Fで変数をフィルタリングできます。大量の変数がある場合に便利です。

コールスタックの分析

コールスタックとは

コールスタックは、現在の実行位置に至るまでの関数呼び出しの履歴です。バグの原因が「どこから呼ばれたか」に関係する場合、コールスタックの分析が重要になります。

コールスタックの読み方

// コールスタックの例(上が現在位置)
processPayment (payment.js:45)      ← 現在停止中
validateOrder (order.js:120)
handleCheckout (checkout.js:78)
onClick (button.js:15)
(anonymous) (main.js:1)

スタックフレームの移動

コールスタック内の任意のフレームをクリックすると、そのフレームのコンテキスト(ローカル変数など)を確認できます。

skipFilesの設定

ライブラリ内部のコードをスキップし、自分のコードに集中できます。

1
2
3
4
5
6
7
{
  "skipFiles": [
    "<node_internals>/**",
    "${workspaceFolder}/node_modules/**",
    "**/lib/**/*.js"
  ]
}

スキップされたファイルはコールスタックでグレー表示されます。

Restart Frameの活用

コールスタック内のフレームを右クリック → 「Restart Frame」で、そのフレームから再実行できます。変数の値を変更してから再実行することで、異なる条件でのテストが可能です。

複合デバッグ構成(Compound Configurations)

フロントエンドとバックエンドなど、複数のプロセスを同時にデバッグする設定です。

複合構成の設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Server",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/server/index.js"
    },
    {
      "name": "Client",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}/client"
    }
  ],
  "compounds": [
    {
      "name": "Full Stack",
      "configurations": ["Server", "Client"],
      "stopAll": true,
      "preLaunchTask": "npm: build"
    }
  ]
}

複合デバッグの操作

  • デバッグツールバーのドロップダウンでセッションを切り替え
  • CALL STACKセクションで各セッションを確認
  • stopAll: trueにより、一方を停止すると全体が停止

実践的なデバッグシナリオ

シナリオ1: 非同期処理のデバッグ

非同期処理のデバッグでは、async/awaitのステップ実行と、Promise内部のエラー追跡が重要です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 条件付きブレークポイントで特定のエラーをキャッチ
async function fetchUserData(userId) {
  try {
    const response = await fetch(`/api/users/${userId}`);
    const data = await response.json();  // ブレークポイント: !response.ok
    return data;
  } catch (error) {
    console.error('Failed to fetch user:', error);
    throw error;
  }
}

シナリオ2: ループ内の特定条件でのデバッグ

大量のデータを処理するループで、特定の条件のときだけ停止します。

1
2
3
4
// 条件: item.price < 0 || item.quantity > 1000
for (const item of inventory) {
  processItem(item);  // 異常値のときだけ停止
}

シナリオ3: イベントハンドラのデバッグ

イベント駆動のコードでは、トリガーブレークポイントが有効です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 初期化完了後のクリックイベントのみデバッグ
let initialized = false;

function init() {
  // ... 初期化処理
  initialized = true;  // ブレークポイント1
}

button.addEventListener('click', () => {
  handleClick();  // トリガーブレークポイント(ブレークポイント1の後に有効化)
});

シナリオ4: メモリリークの調査

WATCHセクションを活用してメモリ使用量を監視します。

1
2
3
4
5
// ウォッチに追加
process.memoryUsage().heapUsed / 1024 / 1024  // MB単位

// または
performance.memory.usedJSHeapSize / 1024 / 1024  // ブラウザ

デバッグのベストプラクティス

効率的なデバッグのためのTips

Tip 説明
仮説を立ててからデバッグ 闇雲にブレークポイントを置かない
二分探索的アプローチ 問題箇所を絞り込んでいく
ログポイントを活用 最初はログポイントで全体像を把握
条件付きで絞り込む 再現条件が明確なら条件付きブレークポイント
skipFilesを設定 ライブラリコードはスキップ

避けるべきアンチパターン

アンチパターン 問題点
ブレークポイントの乱立 本質的な問題箇所が見えなくなる
console.logの多用 コードが汚れ、ビルド時間が増える
グローバル変数での確認 副作用による誤解が生じる
デバッグコードの放置 本番環境に影響を与える可能性

デバッグ設定の共有

チーム開発では、.vscode/launch.jsonをGitで共有することを推奨します。

1
2
3
4
// .gitignore
.vscode/*
!.vscode/launch.json
!.vscode/tasks.json

トラブルシューティング

よくある問題と解決方法

問題 原因 解決方法
ブレークポイントがグレー ソースマップの問題 outFilessourceMapsを確認
変数がundefined表示 スコープ外 コールスタックで正しいフレームを選択
デバッガーが起動しない 構成エラー デバッグコンソールでエラーを確認
意図しない場所で停止 例外ブレークポイント 「Uncaught Exceptions」の設定を確認
処理が遅い ログ出力が多すぎる ログポイントの数を減らす

デバッグ情報の診断

コマンドパレットで「Debug: Diagnose Breakpoint Problems」を実行すると、ブレークポイントの問題を診断できます。

まとめ

VSCode デバッグ機能を効果的に活用することで、バグの原因特定と修正にかかる時間を大幅に短縮できます。本記事で紹介した機能を実践で使いこなすことで、開発効率が向上します。

今すぐ実践すべきこと:

  1. launch.jsonを作成し、プロジェクトに合わせたデバッグ構成を設定する
  2. console.logの代わりにログポイントを使う習慣をつける
  3. 条件付きブレークポイントで効率的に問題箇所を特定する
  4. コールスタックを活用して、問題の根本原因を追跡する

これらのテクニックを日常の開発に取り入れることで、デバッグ作業のストレスが軽減され、より本質的な開発作業に集中できるようになります。

参考リンク