Node.jsの面接は、イベントループと非同期コードから始まり、API、エラーハンドリング、ストリーム、パフォーマンス、セキュリティへと進みます。候補者がつまずく最も一般的な理由は、イベントループを魔法のように説明してしまうことです。どこで何が実行されるのか、何がブロックするのかを明確に説明できるかどうかが、面接官が聞いているポイントです。
以下は、回答付きの24問です。コードサンプルは短いので、記憶を頼りに書けるはずです。
イベントループと非同期
1. Node.jsとは何ですか?
ChromeのV8エンジン上に構築された、ブラウザの外で動作するJavaScriptランタイムです。JavaScriptはシングルスレッドのイベントループで動かし、I/Oはノンブロッキングで処理します。そのため、ほとんどの時間を待機に費やす多数の接続を扱うのが得意です。
2. イベントループはどのように動作しますか?
JavaScriptのコードは1つのスレッドで実行されます。ファイルの読み込みやリクエストの送信などのI/O操作を開始すると、Nodeはそれをシステムまたはスレッドプールに任せて処理を続けます。操作が完了すると、そのコールバックがキューに入り、コールスタックが空になったときにイベントループがそれを実行します。ループはフェーズを順に進みます。タイマー、ペンディングコールバック、ポーリング(I/O)、チェック(setImmediate)、クローズコールバックです。
3. process.nextTick、Promise、setTimeout、setImmediateの順序はどうなりますか?
console.log('1 sync');
setTimeout(() => console.log('4 timeout'), 0);
setImmediate(() => console.log('5 immediate'));
Promise.resolve().then(() => console.log('3 promise'));
process.nextTick(() => console.log('2 nextTick'));
同期コードが最初に実行されます。次にprocess.nextTickのコールバック、続いてPromiseのマイクロタスク、その後でループの各フェーズです。setTimeout(0)とsetImmediateの順序はメインモジュールでは変わり得ますが、I/Oコールバックの中ではsetImmediateが必ず先に実行されます。ただ暗唱するのではなく、説明できるようにしておきましょう。
4. 「イベントループをブロックする」とはどういう意味で、どう避けますか?
巨大なJSONのパース、大きなループ、リクエストハンドラ内でのfs.readFileSyncなど、長時間の同期処理は、それが終わるまで他のすべてのリクエストを止めてしまいます。避けるには、非同期APIを使う、処理を分割する、CPU負荷の高い処理をワーカースレッドや別プロセスに移すといった方法があります。
5. コールバック、Promise、async/awaitの違いは何ですか?
コールバックは元々のスタイルで、深くネストすることがあります。Promiseは将来の値を表し、thenでチェーンできます。async/awaitはPromiseの上に載った構文で、同期コードのように読め、try/catchと組み合わせて使えます。
6. 非同期タスクを並列で実行するにはどうしますか?
const [user, orders] = await Promise.all([getUser(id), getOrders(id)]);
Promise.allは1つでも失敗すると拒否されます。Promise.allSettledはすべてを待ち、それぞれの結果を報告します。Promise.raceは最初に確定したものを返します。呼び出しが独立しているなら、ループの中でawaitしてはいけません。
7. ワーカースレッド、子プロセス、クラスタの違いは何ですか?
ワーカースレッドは1つのプロセス内の別スレッドでJavaScriptを実行し、メモリを共有できるため、CPU負荷の高い処理に適しています。子プロセスは別のプログラムを起動します。clusterモジュールはアプリのコピーをコアごとに複数フォークし、ポートを共有するので、すべてのCPUを使ってリクエストを処理できます。
モジュールとツール
8. CommonJSとESモジュールの違いは何ですか?
CommonJSはrequireとmodule.exportsを使い、同期的に読み込みます。ESモジュールはimportとexportを使い、JavaScriptの標準で、トップレベルawaitをサポートします。Nodeはどちらもサポートしており、ファイル拡張子かpackage.jsonのtypeフィールドで選択します。
9. package.jsonには何が含まれ、dependenciesとdevDependenciesの違いは何ですか?
メタデータ、スクリプト、依存関係が含まれます。dependenciesは実行時に必要で、devDependenciesは開発とテストにのみ必要です。ロックファイルは正確なバージョンを記録するので、インストールが再現可能になります。
10. 環境設定はどのように扱いますか?
環境変数を使い、process.envを通して読み込み、検証済みの設定モジュールを用意します。シークレットはリポジトリに置かず、本番ではシークレットマネージャーを使います。
APIとExpress
11. Expressのミドルウェアとは何ですか?
リクエスト、レスポンス、nextにアクセスできる関数です。ミドルウェアは順番に実行され、リクエストを変更したり、レスポンスを終了させたり、制御を次に渡したりできます。典型的な用途は、ロギング、ボディのパース、認証、エラーハンドリングです。
app.use((req, res, next) => {
console.log(req.method, req.url);
next();
});
12. Expressアプリでエラーはどのように扱いますか?
非同期ハンドラ内でエラーを捕捉し、next(err)に渡し、4つの引数(err, req, res, next)を持つエラーハンドリングミドルウェアで一貫したレスポンスを返します。Express 5では、ハンドラから拒否されたPromiseは自動的に転送されます。捕捉されない例外と未処理の拒否については、未知の状態で続行するのではなく、ログに記録してプロセスを再起動します。
13. 注文を作成するREST APIエンドポイントはどのように設計しますか?
入力を検証し、ユーザーを認証し、権限を確認し、データベーストランザクション内で注文を作成し、新しいリソースとその場所とともに201を返し、冪等キーで重複を処理し、適切なステータスコードとともに明確なエラーを返します。
14. ユーザー認証はどのように行いますか?
Cookieを使ったセッション、またはJWTなどのトークンを使います。パスワードはbcryptやargon2のような低速なアルゴリズムでハッシュ化します。JWTでは、有効期限を短く保ち、リフレッシュトークンを慎重に扱い、トークンに機密データを保存しないようにします。
ストリーム、ファイル、パフォーマンス
15. ストリームとは何か、なぜ使うのか?
ストリームは、データをすべてメモリに読み込むのではなく、チャンク単位で処理します。種類は readable、writable、duplex、transform です。大きなファイル、アップロード、ダウンロードに使います。
const fs = require('node:fs');
const { pipeline } = require('node:stream/promises');
const zlib = require('node:zlib');
await pipeline(fs.createReadStream('in.log'), zlib.createGzip(), fs.createWriteStream('in.log.gz'));
16. バックプレッシャーとは?
writable ストリームが readable ストリームに追いつけないとき、ソースに速度を落とすよう信号を送ります。pipeline と pipe がこれを処理してくれます。手動で書き込む場合は、write() の戻り値を確認し、drain イベントを待ちます。
17. メモリリークはどうやって見つける?
時間の経過とともにメモリを監視し、ヒープスナップショット(Chrome DevTools または --inspect)を取得して比較し、どのオブジェクトが増えているかを確認します。よくある原因は、期限切れにならないグローバルキャッシュ、削除されないイベントリスナー、大きなオブジェクトを保持するクロージャです。
18. Node.js アプリケーションはどうやってスケールさせる?
cluster モジュールやプロセスマネージャーで複数のプロセスを実行し、ロードバランサーの背後に置き、セッションを Redis やデータベースに移してアプリをステートレスに保ち、キャッシュを使い、コンテナでスケールアウトします。CPU を大量に使う処理はワーカーや別サービスに移します。
19. 遅いエンドポイントはどうやってプロファイリングする?
まずログとタイミングで計測し、次に --prof や --cpu-prof、またはフレームグラフツールを使ってホットな関数を見つけます。データベースクエリを確認しましょう。遅さは JavaScript よりもそこにあることのほうが多いです。
セキュリティと信頼性
20. Node.js でよくあるセキュリティ問題は?
インジェクション(SQL、NoSQL、コマンド)、クロスサイトスクリプティング、弱い認証、脆弱な依存関係、コード内のシークレット、レート制限の欠如、安全でないデシリアライズです。入力検証、パラメータ化クエリ、helmet、依存関係の監査(npm audit)、最小権限の原則で軽減します。
21. グレースフルシャットダウンはどうやる?
SIGTERM を受けたら、新しい接続の受け付けを停止し、処理中のリクエストを完了させ、データベース接続を閉じてから終了します。フォールバックとしてタイムアウトを設定します。
process.on('SIGTERM', () => {
server.close(() => process.exit(0));
});
22. Node.js のコードはどうやってテストする?
組み込みの node:test、Jest、Vitest などのランナーでユニットテストを行い、外部呼び出しはモックします。テスト用データベースに対する統合テストと、Supertest などのツールによる HTTP レベルのテストを行います。テストは高速で独立したものに保ちます。
設計とシナリオ
23. 負荷がかかると API が遅い。どう調査する?
レイテンシと CPU のメトリクスを確認します。1 つのコアで CPU が高い場合は、ブロッキングコードや重い JSON 処理を探します。CPU が低くレイテンシが高い場合は、データベースや他のサービス待ちを調べます。その後、キャッシュ、インデックス、コネクションプーリング、バッチ処理を追加し、負荷をかけて再度テストします。
24. 大きなファイル用のアップロードエンドポイントはどう作る?
メモリにバッファリングするのではなく、アップロードをストレージへ直接ストリーミングします。たとえば、pre-signed URL を使ったオブジェクトストレージです。サイズ制限を設定し、種類を検証し、必要ならスキャンし、その後はバックグラウンドジョブで処理します。
準備の方法
認証、データベース、アップロードルートを備えた小さな API を書き、負荷ツールでプロファイリングして 1 つの問題を修正しましょう。イベントループを描き、上記のような小さなスクリプトの出力を説明する練習をしましょう。パフォーマンスや信頼性の問題をデバッグした実体験を 1 つ用意しましょう。コーディング面接についてはコーディング面接アシスタントガイドを、設計についてはシステムデザインガイドをご覧ください。
答えを声に出して言い、用語を説明せずに使ってしまった箇所がないかトランスクリプトを読み返しましょう。ライブ面接では、AI ツールに関する雇用主のルールに従ってください。
YesToTheOfferでNode.jsの面接回答を練習しましょう
模擬技術面接を実行し、イベントループを声に出して説明し、後で文字起こしを確認しましょう。30分無料、サブスクリプション不要。



