12月 21, 2025
21 分で読める

Node.jsシニアバックエンド面接質問集

interview
career-advice
job-search
Node.jsシニアバックエンド面接質問集
Milad Bonakdar

Milad Bonakdar

著者

Event Loop、Streams、APIセキュリティ、システム設計、スケーリング、パフォーマンス、テスト、本番運用責任を扱う30問で、Node.jsシニアバックエンド面接に備えましょう。


Node.jsシニアバックエンド面接質問集

Node.jsのシニア面接では、構文だけでなく、Event Loop、バックプレッシャー、API境界、分散システム、Observability、セキュリティ、本番運用での判断が問われます。強い回答は、Node.jsの内部動作と、実際のサービスで行った設計判断を結びつけて説明します。

この30問は、シニアらしい簡潔な説明を練習するためのものです。各テーマについて、スケーリング判断、性能問題、信頼性インシデント、設計上のトレードオフなど、自分の経験から1つ例を用意しておきましょう。


高度な Node.js の概念 (10個の質問)

1. Node.js のイベントループについて詳しく説明してください。異なるフェーズは何ですか?

回答: Event Loopは、JavaScriptが通常1つのメインスレッドで動きながら、Node.jsがノンブロッキングI/Oを扱えるようにする仕組みです。待ち時間のある処理や重い処理はOSまたはlibuvが扱い、完了後にJavaScriptが実行するコールバックとしてキューに入ります。

  • Timers: setTimeout()setInterval() のコールバックを実行します。近年のNode.jsでは、pollフェーズの処理量がタイマー実行のタイミングに影響することがあります。
  • Pending callbacks: 次のループ反復に延期された一部の低レベルI/Oコールバックを実行します。
  • Idle, prepare: libuv内部用のフェーズです。
  • Poll: 新しいI/Oイベントを取得し、I/O関連のコールバックを実行します。キューが空の場合、Node.jsはI/Oを待つか、setImmediate() があれば次へ進みます。
  • Check: setImmediate() のコールバックを実行します。
  • Close callbacks: socket.on('close', ...) などのcloseハンドラーを実行します。

シニアの回答では、マイクロタスクキューにも触れるべきです。process.nextTick() はPromiseのマイクロタスクより先に実行され、どちらもEvent Loopが続行する前に処理されます。使いすぎるとI/Oを待たせます。

希少性: 非常に一般的 難易度: 難しい


2. process.nextTick()setImmediate() の違いは何ですか?

回答:

  • process.nextTick(): イベントループの一部ではありません。現在の操作が完了した直後、ただしイベントループが続行する前に発生します。setImmediate() よりも優先度が高くなります。過度に使用すると、イベントループをブロックする可能性があります(飢餓状態)。
  • setImmediate(): イベントループのチェックフェーズの一部です。ポーリングフェーズの後に実行されます。

希少性: 一般的 難易度: 普通


3. Node.js はシングルスレッドの場合、どのように並行処理を処理しますか?

回答: Node.js は、イベント駆動型のノンブロッキング I/O モデルを使用します。

  • メインスレッド: JavaScript コードを実行します (V8 エンジン)。
  • Libuv: イベントループとスレッドプールを提供する C ライブラリ(デフォルトは4スレッド)。
  • メカニズム: 非同期操作(ファイル I/O やネットワークリクエストなど)が開始されると、Node.js はそれを Libuv にオフロードします。Libuv は、そのスレッドプール(ファイル I/O、DNS 用)またはシステムカーネルの非同期メカニズム(ネットワーク用)を使用します。操作が完了すると、コールバックはメインスレッドによって実行されるように、イベントループキューにプッシュされます。

希少性: 一般的 難易度: 普通


4. Node.js の Streams とその種類について説明してください。

回答: Streams は、連続したチャンクでソースからデータを読み取ったり、宛先にデータを書き込んだりできるオブジェクトです。データをすべてメモリにロードする必要がないため、メモリ効率が高くなります。

  • 種類:
    1. Readable: データを読み取るため (例: fs.createReadStream)。
    2. Writable: データを書き込むため (例: fs.createWriteStream)。
    3. Duplex: 読み取りと書き込みの両方 (例: TCP ソケット)。
    4. Transform: 出力が入力に基づいて計算される Duplex ストリーム (例: zlib.createGzip)。

希少性: 一般的 難易度: 普通


5. Streams における Backpressure と、その処理方法は何ですか?

回答: バックプレッシャーは、Readable StreamがWritable側の処理速度を超えてデータを生成するときに起こります。無視するとバッファが増え、GC負荷が高まり、プロセスがメモリ不足になる可能性があります。

  • stream.pipeline() または node:stream/promisespipeline を使う: Streamを接続し、エラー伝播とクリーンアップを正しく行えます。
  • .write() の戻り値を尊重する: false が返ったら、追加書き込みの前に drain を待ちます。
  • 慎重にチューニングする: highWaterMark は特定のワークロードで有効ですが、計測なしに上げるとメモリ側へ問題を移すだけです。
  • アップロードでは: ファイル全体をメモリに載せず、Object Storageや処理パイプラインへ直接ストリーミングします。

希少性: 普通 難易度: 難しい


6. cluster モジュールはどのように機能しますか?

回答: Node.js はシングルスレッドであるため、単一の CPU コアで実行されます。cluster モジュールを使用すると、同じサーバーポートを共有する子プロセス(ワーカー)を作成できます。

  • マスタープロセス: ワーカーを管理します。
  • ワーカープロセス: それぞれがアプリケーションのインスタンスを実行します。
  • 利点: 使用可能なすべての CPU コアを利用して、スループットを向上させることができます。

希少性: 一般的 難易度: 普通


7. Worker Threads vs Cluster モジュール: どちらをいつ使用しますか?

回答:

  • Cluster: 別のプロセスを作成します。それぞれが独自のメモリ空間と V8 インスタンスを持っています。HTTP サーバー(I/O バウンド)のスケーリングに最適です。
  • Worker Threads: 単一のプロセス内にスレッドを作成します。メモリを共有します(SharedArrayBuffer 経由)。メインのイベントループをブロックしないように、CPU 集中型タスク(例:画像処理、暗号化)に最適です。

希少性: 普通 難易度: 難しい


8. キャッチされない例外と未処理の Promise の拒否をどのように処理しますか?

回答:

  • キャッチされない例外: process.on('uncaughtException', cb) をリッスンします。アプリケーションの状態が破損している可能性があるため、通常はエラーをログに記録して(PM2 などのプロセス管理ツールを使用して)プロセスを再起動するのが最善です。
  • 未処理の拒否: process.on('unhandledRejection', cb) をリッスンします。
  • ベストプラクティス: 常に try/catch ブロックと Promise で .catch() を使用します。

希少性: 一般的 難易度: 簡単


9. package-lock.json の役割は何ですか?

回答: これは、生成された正確なツリーを記述するもので、後続のインストールで、中間的な依存関係の更新に関係なく、同一のツリーを生成できます。これにより、プロジェクトがすべてのマシン(CI/CD、他の開発者)でまったく同じように動作することが保証されます。

希少性: 一般的 難易度: 簡単


10. Express.js の Middleware の概念について説明してください。

回答: Middleware 関数は、リクエストオブジェクト (req)、レスポンスオブジェクト (res)、およびアプリケーションのリクエスト-レスポンスサイクル内の次の Middleware 関数 (next) にアクセスできる関数です。

  • タスク: コードの実行、req/res オブジェクトの変更、リクエスト-レスポンスサイクルの終了、次の Middleware の呼び出し。
  • 順序: 定義された順序で順番に実行されます。

希少性: 一般的 難易度: 簡単


システム設計とアーキテクチャ (10個の質問)

11. リアルタイムチャットアプリケーションをどのように設計しますか?

回答:

  • プロトコル: 全二重通信用の WebSockets (socket.io または ws を使用)。
  • バックエンド: Node.js は、多数の同時接続を処理するイベント駆動型の性質があるため、理想的です。
  • スケーリング:
    • Redis Pub/Sub: 複数のサーバーインスタンスがある場合、サーバー A に接続されたユーザーは、サーバー B のユーザーにメッセージを送信する必要があります。Redis Pub/Sub は、サーバー間でメッセージをブロードキャストするメッセージブローカーとして機能します。
  • データベース:
    • メッセージ: 高い書き込みスループットのための NoSQL (MongoDB/Cassandra)。
    • ユーザー: リレーショナル (PostgreSQL) または NoSQL。

希少性: 非常に一般的 難易度: 難しい


12. Node.js のマイクロサービス: 通信パターン。

回答:

  • 同期: HTTP/REST または gRPC。単純なリクエスト/レスポンスに適しています。
  • 非同期: メッセージキュー (RabbitMQ、Kafka、SQS)。サービスの分離と負荷スパイクの処理に適しています。
  • イベント駆動型: サービスがイベントを発行し、他のサービスがリッスンします。

希少性: 一般的 難易度: 普通


13. 分散トランザクション (Saga パターン) はどのように処理しますか?

回答: マイクロサービスでは、トランザクションが複数のサービスにまたがる場合があります。ACID を保証するのは困難です。

  • Saga パターン: ローカルトランザクションのシーケンス。各ローカルトランザクションはデータベースを更新し、イベントまたはメッセージを発行して、Saga の次のローカルトランザクションをトリガーします。
  • 補償: ローカルトランザクションが失敗した場合、Saga は一連の補償トランザクションを実行して、先行するローカルトランザクションによって行われた変更を元に戻します。

希少性: 普通 難易度: 難しい


14. サーキットブレーカーパターンについて説明してください。

回答: 失敗する可能性が高い操作(例:ダウンしたマイクロサービスの呼び出し)をアプリケーションが繰り返し実行しようとするのを防ぎます。

  • 状態:
    • クローズ: リクエストは通過します。
    • オープン: サービスを呼び出さずに、リクエストはすぐに失敗します(高速フェイル)。
    • ハーフオープン: サービスが回復したかどうかを確認するために、限られた数のリクエストを許可します。

希少性: 普通 難易度: 普通


15. Node.js API をどのように保護しますか?

回答: 強い回答は、単なるパッケージ一覧ではなく脅威モデリングから始まります。Node.js APIでは次を押さえます。

  • 認証と認可: 身元を検証し、オブジェクト単位の権限を強制し、クライアントが送るuser IDやtenant IDを信用しません。
  • 入力検証: 境界で型、形式、範囲、content type、リクエストサイズをZodやJoiなどで検証します。
  • 通信とヘッダー: HTTPS、必要に応じた安全なCookie、CORS allowlist、Helmetやプラットフォームによるヘッダー制御を使います。
  • 悪用対策: rate limit、timeout、body size制限、reverse proxyで低速または大量アクセスを抑えます。
  • 依存関係とシークレット: 依存関係をlockし、脆弱なパッケージを監視し、シークレットをコードに置かず、漏洩時はローテーションします。
  • Observability: セキュリティ上重要な失敗を、機密情報を漏らさずに記録します。

希少性: 一般的 難易度: 普通


16. サーバーレスとは何ですか?また、Node.js とどのように適合しますか?

回答: サーバーレス(例:AWS Lambda)を使用すると、サーバーをプロビジョニングまたは管理せずにコードを実行できます。

  • Node.js の適合性: Node.js は、起動時間(コールドスタート)が速く、軽量であるため、サーバーレスに最適です。
  • ユースケース: API エンドポイント、イベント処理 (S3 アップロード)、スケジュールされたタスク。

希少性: 普通 難易度: 普通


17. GraphQL と REST について説明してください。いつ GraphQL を使用しますか?

回答:

  • REST: 複数のエンドポイント、データの過剰フェッチまたは過少フェッチ。
  • GraphQL: 単一のエンドポイント、クライアントは必要なものだけを要求します。
  • GraphQL の使用: 複雑なデータ要件がある場合、異なるデータ形状を必要とする複数のクライアント (Web、モバイル) がある場合、またはネットワークラウンドトリップを減らす場合。

希少性: 一般的 難易度: 普通


18. Node.js でのキャッシュの実装方法。

回答:

  • インメモリ: node-cache (単一インスタンスには適していますが、再起動時にデータが失われ、共有されません)。
  • 分散: Redis (業界標準)。
  • 戦略: Cache-Aside、Write-Through。
  • HTTP キャッシュ: ETag、Cache-Control ヘッダーを使用します。

希少性: 一般的 難易度: 普通


19. データベース接続プーリング。

回答: リクエストごとに新しいデータベース接続を開くのはコストがかかります。

  • プーリング: 再利用できるデータベース接続のキャッシュを維持します。
  • Node.js: pg (PostgreSQL) や mongoose などのライブラリは、プーリングを自動的に処理します。ワークロードと DB の制限に基づいて、プールサイズを構成する必要があります。

希少性: 普通 難易度: 普通


20. Node.js でのファイルアップロードの処理方法。

回答:

  • Multipart/form-data: ファイルアップロードの標準エンコード。
  • ライブラリ: multer (Express 用の Middleware)、formidablebusboy
  • ストレージ: サーバーのファイルシステムにファイルを保存しないでください (ステートレス)。AWS S3 などのクラウドストレージにアップロードします。ファイルをメモリにロードしないように、ファイルを S3 に直接ストリーミングします。

希少性: 一般的 難易度: 普通


パフォーマンスとテスト (10個の質問)

21. Node.js のメモリリークをどのようにデバッグしますか?

回答:

  • 症状: 時間の経過とともにメモリ使用量が増加する (RSS)、最終的なクラッシュ。
  • ツール:
    • Node.js インスペクター: --inspect フラグ、Chrome DevTools で接続します。
    • ヒープスナップショット: スナップショットを取得して比較し、ガベージコレクションされていないオブジェクトを見つけます。
    • process.memoryUsage(): プログラムで監視します。

希少性: 一般的 難易度: 難しい


22. Node.js アプリケーションのプロファイリング。

回答: プロファイリングは、CPU ボトルネックを特定するのに役立ちます。

  • 組み込みプロファイラー: node --prof app.js。ログファイルを生成します。node --prof-process isolate-0x...log で処理します。
  • Clinic.js: パフォーマンスの問題を診断するためのツールスイート (clinic doctorclinic flameclinic bubbleprof)。

希少性: 普通 難易度: 難しい


23. 「イベントループをブロックしない」ルールについて説明してください。

回答: スレッドが 1 つしかないため、長時間実行される同期操作(例:重い計算、同期ファイル読み取り、複雑な正規表現)を実行すると、イベントループが停止します。他のリクエストは処理できません。

  • 解決策: 計算を分割する (setImmediate)、Worker Threads を使用する、またはマイクロサービスにオフロードする。

希少性: 非常に一般的 難易度: 簡単


24. Node.js のユニットテストと統合テスト。

回答:

  • ユニットテスト: 個々の関数/モジュールを分離してテストします。依存関係をモックします。(ツール:Jest、Mocha、Chai)。
  • 統合テスト: モジュールがどのように連携するかをテストします (例:API エンドポイント + データベース)。(ツール: Supertest)。

希少性: 一般的 難易度: 簡単


25. TDD (テスト駆動開発) とは何ですか?

回答: コードの前にテストを記述する開発プロセス。

  1. 失敗するテストを記述します (赤)。
  2. テストに合格するために最小限のコードを記述します (緑)。
  3. コードをリファクタリングします (リファクタリング)。

希少性: 普通 難易度: 普通


26. 本番環境の Node.js アプリでログをどのように処理しますか?

回答: 本番ログは、構造化され、検索しやすく、Observabilityツールに安全に送れる必要があります。

  • Loggerを使う: 散発的な console.log ではなく、Pino、Winston、またはプラットフォームのLoggerを使います。
  • 構造: request ID、安全な範囲のuser/tenant識別子、route、status、latency、error metadataをJSONで出力します。
  • レベル: error、warn、info、debugを一貫して使います。
  • マスキング: token、password、完全な決済情報、個人の機密コンテンツをログに出しません。
  • 相関: logs、metrics、tracesを結び、複数サービスにまたがる障害を調査できるようにします。

希少性: 一般的 難易度: 簡単


27. セマンティックバージョニング (SemVer) について説明してください。

回答: 形式: MAJOR.MINOR.PATCH (例: 1.2.3)。

  • MAJOR: 互換性のない API の変更。
  • MINOR: 後方互換性のある機能。
  • PATCH: 後方互換性のあるバグ修正。
  • ^ vs ~: ^1.2.3<2.0.0 に更新されます。~1.2.3<1.3.0 に更新されます。

希少性: 一般的 難易度: 簡単


28. 環境変数とは何ですか?また、どのように管理しますか?

回答:

  • 目的: DB URL、API キーなど、環境 (開発、ステージング、本番) によって異なる構成。
  • 使用法: process.env.VARIABLE_NAME
  • 管理: ローカル開発用の .env ファイル (dotenv パッケージを使用)。本番環境では、OS またはコンテナ/プラットフォームの設定で設定します。

希少性: 一般的 難易度: 簡単


29. Node.js アプリケーションをどのようにデプロイしますか?

回答:

  • プロセス管理ツール: PM2 (アプリを稼働させ続け、再起動、ログを処理します)。
  • リバースプロキシ: Nginx (SSL、静的ファイル、ロードバランシングを処理します) -> Node.js アプリ。
  • コンテナ化: Docker (標準)。
  • オーケストレーション: Kubernetes。
  • CI/CD: GitHub Actions、Jenkins。

希少性: 一般的 難易度: 普通


30. イベントエミッターとは何ですか?

回答: events モジュールは、Node.js イベント駆動型アーキテクチャの中核です。

  • 使用法:
    const EventEmitter = require('events');
    const myEmitter = new EventEmitter();
    myEmitter.on('event', () => console.log('an event occurred!'));
    myEmitter.emit('event');
  • 多くのコアモジュールがそれを拡張します: fs.ReadStreamnet.Serverhttp.Server

希少性: 一般的 難易度: 簡単

Newsletter subscription

実際に機能する週次のキャリアのヒント

最新の洞察をメールボックスに直接お届けします

次の面接は履歴書一つで決まる

数分でプロフェッショナルで最適化された履歴書を作成。デザインスキルは不要—証明された結果だけ。

私の履歴書を作成

この投稿を共有

面接のコールバックを2倍に

求人内容に合わせて履歴書をカスタマイズする候補者は、2.5倍多くの面接を獲得します。当社のAIを使用して、すべての応募に対して即座に自動カスタマイズできます。