質問とスコープ
ユーザーがアドレスバーに https://shop.example/products?id=42#reviews と入力してEnterキーを押してから、ページが表示されるまでに何が起きますか?URLパース、名前解決、接続セキュリティ、HTTP、サーバー側の処理、ブラウザのナビゲーション、レンダリングを網羅してください。また、キャッシュや接続の再利用によってどの段階をスキップできるかも説明してください。
回答が互換性のない経路間でブレないよう、明確な前提条件から始めてください。これは新規のトップレベルドキュメントナビゲーションです。入力は完全なURLであり、検索クエリではありません。レスポンスを提供するService Workerは存在せず、直接使用できるほど新しいHTTPレスポンスはなく、再利用可能な互換性のある接続はなく、ホストの名前解決が必要であり、最終的なサーバーレスポンスはステータス200のHTMLとします。ウォームキャッシュ、リダイレクト、HTTP/3は、このベースラインの後の分岐として扱います。
このクロスレイヤーの基礎的な質問は、バックエンド、クライアント、フルスタック、インフラストラクチャ、SRE、一般的なソフトウェアエンジニアリングの面接に適しています。タスクは、キャッシュとプロトコルの前提から実際の経路を導き出し、ネットワーク、サーバー、レンダリングの各段階を観測可能な証拠に対応付けることです。
面接官がテストしていること
第1に、候補者が一連の流れを説明する前に前提条件を提示できるかどうかです。「DNS、TCP、TLS、HTTP、レンダリング」の暗記では、キャッシュ、Service Worker、接続の再利用、HTTP/3が見落とされます。実際の経路は、ナビゲーションの種類、キャッシュされた状態、プロトコルネゴシエーション、レスポンスによって異なります。優れた回答は、1つの決定論的なベースラインを確立し、それを変化させる条件を挙げます。
第2に、プロトコルの境界を正確に維持できるかどうかです。#reviews はURLフラグメントであり、HTTPリクエストターゲットからは除外されます。HTTPSのデフォルトポートは443です。DNSはホストを解決しますが、毎回のナビゲーションで必ずしもルートサーバーから開始するわけではありません。HTTP/1.1とHTTP/2は通常TCPを使用し、HTTP/3はUDP上で動作しTLS 1.3を統合したQUICを使用します。
第3に、ナビゲーションのコミット、リソースの読み込み、画面上のピクセル描画を区別できるかどうかです。最初のバイトを受信してもページは表示されず、ナビゲーションをコミットしたからといってすべてのリソースが読み込まれたわけではありません。ブラウザはレンダラーを選択し、HTMLをパースし、サブリソースを発見し、DOMとCSSOMを構築し、スタイル計算、レイアウト、ペイント、コンポジット(合成)を実行する必要があります。
第4に、このモデルを使用してデバッグできるかどうかです。一連のシーケンスだけでは「どこが遅いのか?」に答えられません。質の高い回答は、DNS、接続、TLS、ファーストバイト、ダウンロード、メインスレッドのレンダリングを、Navigation Timing、ネットワークパネル、パフォーマンストレースの証拠に対応付けます。
最初に明確にすべき点
- 入力は確実にURLか? アドレスバーは通常のテキストを検索エンジンに送信することもあります。このプロンプトではスキームを含む完全なHTTPS URLが提供されているため、ナビゲーションとして進めます。
- これはドキュメントナビゲーションか、それともアプリ内のSPA遷移か?
history.pushState()の呼び出しは、同一のクロスドキュメントナビゲーションを自動的に実行するわけではありません。ベースラインは新規のトップレベルドキュメントです。 - これはコールドパスかウォームパスか? HTTPやDNSのキャッシュ、Service Worker、preconnect、既存のHTTP/2やHTTP/3接続によって段階を省略できます。まずコールドパスを説明し、その後に分岐を説明します。
- どのプロトコルとネットワーク環境が適用されるか? HTTP/1.1、HTTP/2、HTTP/3では接続確立の方法が異なります。プロキシ、VPN、エンタープライズゲートウェイ、利用できないUDP経路などもルートを変更する可能性があります。
- どのようなレスポンスが返ってくるか? 200 HTMLドキュメント、リダイレクト、ダウンロード、証明書エラー、ネットワーク障害では異なる分岐を辿ります。ベースラインでは200 HTMLを使用します。
- 「表示される(visible)」とは何を意味するか? First Paint、Largest Contentful Paint、
DOMContentLoaded、loadはそれぞれ異なるマイルストーンです。この回答では最初の可視化に到達し、その後の読み込みについても説明します。
30秒の回答フレームワーク
「コールド状態のトップレベルHTTPSナビゲーションを前提とします。ブラウザはURLをパースし、フラグメントをクライアント側に保持します。キャッシュまたはDNSからアドレスを取得し、接続を再利用するか、HTTP/1.1やHTTP/2のためにTCPとTLSを確立するか、HTTP/3のためにTLS 1.3統合QUICを確立します。パスとクエリを送信します。レスポンスを確認してレンダラーを選択した後、ナビゲーションをコミットします。レンダラーはHTMLをパースし、サブリソースを読み込み、DOM、CSSOM、レンダーツリーを構築し、レイアウト、ペイント、コンポジットを実行します。読み込みが遅い場合は、DNS、接続/TLS、TTFB、ダウンロード、メインスレッドの時間に切り分けて診断します。」
ステップごとの詳細解説
ステップ1: アドレスバーの入力を分類し、URLをパースする
ブラウザはまず、アドレスバーの入力がナビゲーション可能なURLか検索クエリかを判定します。この入力には https:// が含まれているため、URLとしてパースされます。結果は以下の通りです。
| コンポーネント | 値 | 目的 |
|---|---|---|
| scheme | https | セキュアなHTTPセマンティクスと適切なトランスポートを選択 |
| host | shop.example | 名前解決、接続、サーバーID検証に使用 |
| port | 443(デフォルト) | 省略時にHTTPSスキームによって提供 |
| path | /products | ターゲットリソースのパスを特定 |
| query | id=42 | リクエストターゲットに含まれて送信 |
| fragment | reviews | ドキュメント内の位置指定用にクライアント側に保持。HTTPターゲットからは除外 |
ブラウザはURL Standardのパースおよび正規化ルールも適用し、ナビゲーションポリシーをチェックします。古いページのunload処理、ブラウザのセキュリティポリシー、無効なURLなどにより、ネットワークリクエストが開始される前に結果が変わることがあります。Enterキーを押すことは、即座にパケットを送信することと同義ではありません。
ステップ2: ネットワークアクセスを回避できるかを判定する
実際のブラウザは、既存のドキュメント状態、Service Worker、HTTPキャッシュ、プリロード状態、再利用可能な接続を考慮します。適用可能な最新のキャッシュレスポンスがあれば、オリジンへの問い合わせを回避できます。制御しているService Workerは、キャッシュされたレスポンスを返すか、独自のfetchを実行するか、またはその両方を組み合わせることができます。キャッシュヒットであってもブラウザの作業がすべてなくなるわけではありません。返されたHTMLのパースとレンダリングは依然として必要になる場合があります。
ベースラインでは、これらのショートカットのいずれもドキュメントを提供できないと仮定するため、ネットワークアクセスを継続します。「すべてのキャッシュを確認してからDNSを実行する」といった画一的な順序を主張することは避けてください。レスポンスキャッシュ、DNSキャッシュ、接続プールは異なる状態を保持しており、ブラウザの実装によっては一部の作業を投機的または並行して実行できます。
ステップ3: ホストを到達可能なアドレスに解決する
ブラウザまたはOSは、まず有効期限内の名前解決結果を使用します。キャッシュミスの場合、設定された再帰リゾルバーに問い合わせます。そのリゾルバーもキャッシュを使用し、回答がない場合にのみDNS委譲を辿り、最終的に適切なアドレスレコードを返します。結果として、アプリケーションオリジンではなくCDNやエッジサーバーに到達する場合があります。
したがって、「ブラウザは読み込みごとにルート、トップレベルドメイン、権威サーバーに問い合わせる」というのは不正確です。クライアントは通常、再帰的な処理をリゾルバーに委譲し、キャッシュとレコードのTTLによって追加の問い合わせが必要かどうかが決まります。ブラウザは暗号化DNSを使用する場合もあります。これは問い合わせのトランスポートとプライバシーの境界を変えるものであり、ホストを到達可能なサービスアドレスに対応付けるという根本的な目的を変えるものではありません。
ステップ4: セキュアな接続を再利用または確立する
候補となるアドレスが利用可能になると、ブラウザはまずターゲットと互換性のある接続の再利用を試みます。利用可能な接続がない場合、パスは選択されたHTTPバージョンに依存します。
- HTTP/1.1またはHTTP/2は通常、TCPを確立してからTLSハンドシェイクを実行します。TLSはホストに対して証明書を検証し、暗号パラメータをネゴシエートし、ALPNを使用してHTTP/2またはHTTP/1.1を選択できます。
- HTTP/3はQUICを使用します。QUICはUDP上で動作し、接続確立処理にTLS 1.3ハンドシェイクを統合しているため、TCPの3ウェイハンドシェイクはHTTPSにおいて普遍的なものではありません。
- 使用可能なQUIC/UDP経路がない場合、クライアントはTCPベースのHTTPにフォールバックできます。正確な競合およびフォールバックのポリシーはブラウザの実装の詳細です。固定されたタイムラインを1つに決めつけないでください。
IPルーティング、ローカルリンク、NAT、プロキシ、VPNはすべてパケット配送に関与します。時間に制限のある面接では、面接官から質問されない限り、すべてのネットワークホップを展開することなく、これらのレイヤーの存在に言及するにとどめてください。
ステップ5: HTTPを送信し、サーバーレスポンスを処理する
接続が使用可能になると、ブラウザはリクエストを構築します。HTTP/1.1のテキスト表現は重要なセマンティクスを表しています。
GET /products?id=42 HTTP/1.1
Host: shop.example
Accept: text/htmlリクエストターゲットにはパスとクエリが含まれますが、#reviews は含まれません。ブラウザはドメイン、パス、SameSite、セキュリティ、関連ルールに従って各Cookieを添付するかどうかを決定し、コンテンツネゴシエーションやキャッシュ検証のフィールドを追加できます。「ブラウザはすべてのCookieを送信する」というのは大雑把すぎます。HTTP/2とHTTP/3はこのHTTP/1.1ワイヤフォーマットを使用しませんが、メソッド、ターゲット、フィールド、レスポンスのセマンティクスには直接の対応関係があります。
リクエストは、アプリケーション、キャッシュ、データベースの前に、CDN、リバースプロキシ、またはロードバランサーに到達する可能性があります。シンプルなサーバーであれば直接応答することもあります。これらは必須の段階ではなく、アーキテクチャの可能性として扱ってください。レスポンスにはステータス、フィールド、コンテンツが含まれます。リダイレクトの場合は、新しい場所への後続ナビゲーションを開始します。304 Not Modified は既存のキャッシュレスポンスと結合されます。ベースラインでは 200、HTMLコンテンツタイプ、レスポンスボディを受信します。
ステップ6: ブラウザナビゲーションをコミットする
レスポンスが届くと、ブラウザはそのステータス、コンテンツタイプ、ダウンロードの判断、セキュリティポリシーを処理し、遷移先に適したレンダラーを選択します。Chromiumはナビゲーションのコミットとドキュメントの読み込みを区別します。コミットによってレスポンスがレンダラーに転送され、現在のドキュメントの所有権が変更されます。残りの読み取り、パース、スクリプト、サブリソースの処理はその後も継続できます。
エラーステータスが必ずしも「ページなし」を意味するわけではありません。サーバーからのHTMLエラーレスポンスが新しいドキュメントになることもあります。一方、証明書エラー、接続エラー、ブラウザによるブロックの場合は、ブラウザが生成したエラーページが表示されることがあります。ナビゲーションがコミットされるのはステータス200の場合だけであるとするのは断定的すぎます。
ステップ7: パース、読み込み、画面へのピクセル描画
レンダラーはHTMLをDOMへと段階的にパースします。スタイルシート、スクリプト、フォント、画像などの参照を検出すると、サブリソースのリクエストをスケジュールします。これらのリソースはDNSの回答や接続を再利用することもあれば、追加の名前解決や接続処理を必要とする他のオリジンから取得されることもあります。各サブリソースが必ずしも完全なハンドシェイクシーケンスを繰り返すわけではありません。
CSSをパースするとCSSOMが生成されます。DOMとCSSOMは可視コンテンツのレンダーツリーを構成し、スタイル計算、レイアウト、ペイントが続きます。その後、ブラウザはレイヤーを合成(コンポジット)してピクセルを表示します。適切な defer、async、またはモジュールの挙動を持たない従来のスクリプトはHTMLパースをブロックする可能性があり、CSSは初期レンダリングに影響を与えます。First Paintは、すべての画像や非同期スクリプトが完了する前に発生することがあります。DOMContentLoaded も、一部のサブリソースの load 完了より前に発生することがあります。
#reviews フラグメントはサーバーに送信されませんでした。ドキュメントがターゲット可能になると、ブラウザは一致する要素までスクロールできます。スクリプトが後からその要素を作成する場合、最終的な動作はページコードにも依存します。
ステップ8: フェーズ固有の証拠を用いて「遅さ」を診断する
まず、ユーザーに見えているのがDNSエラー、接続エラー、真っ白なページ、コンテンツの遅延、インタラクションのブロックのどれであるかを特定します。次に、その症状を各段階に対応付けます。
| 段階 | 主要な証拠 | 解釈の境界 |
|---|---|---|
| DNS | domainLookupStart から domainLookupEnd | 名前解決が遅いからといって、アプリケーションサーバーが遅いとは限らない |
| 接続 | connectStart から connectEnd(セキュア接続時間を含む) | 新規接続、ネットワーク経路、またはTLSが支配的である可能性がある |
| TTFB | requestStart から responseStart | リクエストの転送、エッジ/サーバーの処理、ファーストバイトの返却を含む |
| ダウンロード | responseStart から responseEnd | ボディサイズ、帯域幅、輻輳がすべて影響する |
| レンダリング | パフォーマンストレースにおけるペイント、ロングタスク、レイアウト | レンダリングはストリーミングダウンロードとオーバーラップ可能。メインスレッドの処理が支配的である可能性がある |
ページは初動のトリアージのために自身のナビゲーションレコードを検査できます。
const [nav] = performance.getEntriesByType("navigation");
console.table({
dns: nav.domainLookupEnd - nav.domainLookupStart,
connect: nav.connectEnd - nav.connectStart,
ttfb: nav.responseStart - nav.requestStart,
download: nav.responseEnd - nav.responseStart,
protocol: nav.nextHopProtocol,
});これらの差分は観測点であり、自動的な根本原因ではありません。再利用された接続では、一部のタイムスタンプが等しくなることがあります。Service Worker、キャッシュ、リダイレクト、プロキシもそれらの意味を変える可能性があります。TTFBが高いからといって常にデータベースのせいにするのではなく、ブラウザのネットワークパネル、サーバー側のトレーシング、パフォーマンストレースを使用して仮説を検証してください。
優れた回答例
「コールド状態のベースラインを定義します。Service Workerの応答、HTTPキャッシュヒット、再利用可能な接続がなく、200 HTMLレスポンスで終了する新規のトップレベルHTTPSナビゲーションです。
ブラウザは https://shop.example/products?id=42#reviews をHTTPSスキーム、ホスト、デフォルトポート443、パス、クエリ、フラグメントにパースします。フラグメントはクライアント側に残るため、リクエストターゲットは /products?id=42 となります。次にブラウザまたはOSはDNSキャッシュを使用するか、再帰リゾルバーに問い合わせます。リゾルバーも回答をキャッシュするため、毎回のナビゲーションで必ずしもルート、TLD、権威サーバーに接続するわけではありません。
アドレスを取得した後、ブラウザはまず再利用可能な接続がないか確認します。HTTP/1.1またはHTTP/2は通常TCPとTLSを使用し、サーバー証明書を検証します。HTTP/3はQUICハンドシェイクにTLS 1.3が統合されたUDP上のQUICを使用するため、すべてのHTTPSリクエストでTCPが必須とは言えません。接続されると、ブラウザはパスとクエリを含みフラグメントを含まないGETを送信します。CDN、ロードバランサー、アプリケーションが処理するか、サーバーが直接応答して、ステータス、レスポンスフィールド、HTMLを返します。
ブラウザはレスポンスタイプとセキュリティポリシーを確認し、レンダラーを選択してナビゲーションをコミットします。レンダラーはHTMLを段階的にパースしてDOMを構築し、CSS、JavaScript、フォント、画像を発見します。これらのリソースは接続やキャッシュを再利用できます。DOMとCSSOMがレンダーツリーを構成し、レイアウト、ペイント、コンポジットが続きます。すべてのリソースが完了する前に最初の可視化が行われることがあり、ブラウザはその後にドキュメント内ターゲットとして #reviews を適用できます。
ページの読み込みが遅い場合、フェーズごとに証拠を収集します。DNS、接続、TTFB、ダウンロードにはNavigation Timing、プロトコル、キャッシュ、リダイレクトにはネットワークパネル、メインスレッドのスクリプト、スタイル、レイアウト、ペイントにはパフォーマンストレースを使用します。固定されたパイプラインを暗誦するのではなく、名前解決、ネットワークとサーバーの時間、ブラウザのレンダリングを切り分けて考えます。」
よくある間違い
- 1つの固定されたシーケンスをすべての実際のパスとして扱う → キャッシュ、Service Worker、再利用された接続によりネットワーク処理がスキップされる → コールドのベースラインを述べた上で、それを短縮する条件を挙げる。
- HTTPSは常にTCPから始まると主張する → HTTP/3はTLS 1.3を統合したUDP上のQUICを使用する → TCPベースのHTTPとQUICベースのHTTPを区別する。
- サーバーに
#reviewsを送信する → HTTPターゲットはフラグメントを除外する →/products?id=42を送信し、フラグメントはクライアント側に保持する。 - ブラウザが毎回ルートDNSサーバーに問い合わせると主張する → クライアント、再帰リゾルバー、委譲チェーンはすべてキャッシュを使用できる → 必須の問い合わせシーケンスを決めつけずに、再帰と委譲を説明する。
- サブリソースごとにDNS、TCP、TLSを繰り返す → 同一オリジンの接続とキャッシュされた状態は再利用されることが多い → 新しいオリジン、古い状態、または互換性のない接続の場合にのみ処理を追加する。
- CDN、マイクロサービス、キャッシュ、データベースを必須とする → サーバーのトポロジーは多様である → 「〜を経由する可能性がある」と表現し、実際のアーキテクチャについてのみ掘り下げる。
- 受信したHTMLを完了したページと同等と見なす → コミット、パース、First Paint、
DOMContentLoaded、loadは別々のマイルストーンである → 議論している完了ポイントを定義する。 - パフォーマンスを診断せずにプロトコル名だけを挙げる → 回答にエンジニアリングとしての判断力が示されない → DNS、接続、TTFB、ダウンロード、レンダリングを観測可能な証拠に対応付ける。
フォローアップ質問
フォローアップ1: 最新のHTTPキャッシュエントリまたはService Workerが利用可能な場合、何が変わりますか?
最新のキャッシュエントリがあれば、オリジンに問い合わせることなくレスポンスを提供できます。古いエントリの場合は、条件付きリクエストと304レスポンスが必要になることがあります。Service Workerは自身のキャッシュレスポンスを返すか、fetchを転送するか、あるいは両方を組み合わせることができます。ソースに関係なく、ブラウザはドキュメントのコミット、パース、レンダリングを行う必要がある場合があります。「キャッシュがあるから何もしない」と言うのではなく、キャッシュのソースと検証状態を特定してください。
フォローアップ2: HTTP/3のパスはHTTP/2とどう異なりますか?
HTTP/2は通常、TCP上のTLS上で動作します。HTTP/3はHTTPセマンティクスをQUICに対応付けます。QUICはUDP上で動作し、TLS 1.3を統合しています。どちらも1つの接続で並行ストリームをサポートしますが、HTTP/3の1つのストリームでのトランスポートパケットロスは、関係のない他のストリームに対して単一のTCPバイトストリームの回復を待つことを強制しません。利用可能なQUIC経路がない場合、クライアントはTCPベースのHTTPを使用できます。
フォローアップ3: サーバーが別のホストへの301を返した場合、どのステップが繰り返されますか?
ブラウザはリダイレクトと Location を処理し、新しいURLをパースして、リダイレクトおよびセキュリティポリシーを適用します。新しいホストに使用可能なDNSの回答や互換性のある接続がない場合は、名前解決と接続確立が再度必要になります。再利用可能な状態があれば、これらのステップを省略できます。最終的なレスポンスを取得するかリダイレクト制限に達するまで、別のリクエストを送信します。HTTPセマンティクスにおいて、フラグメントのない Location は元のフラグメントを継承し、独自のフラグメントを持つ Location は新しいフラグメントを使用します。どちらのフラグメントもHTTPリクエストターゲットには含まれません。
フォローアップ4: DNSとTTFBは高速ですが、ページが真っ白なままです。まず何を調査しますか?
ネットワークの証拠によってすでに調査範囲は絞り込まれています。HTMLが届いていること、コンテンツタイプやセキュリティポリシーによって必要なリソースがブロックされていないことを確認します。次に、パフォーマンストレースでロングタスク、同期スクリプト、スタイルシート、フォント、負荷の高いレイアウトを調査します。DNSを再最適化するのではなく、First Paintをクリティカルリソースのウォーターフォールおよびメインスレッドのタイムラインと照合して、描画を妨げている最初の依存関係を見つけます。
フォローアップ5: DOMContentLoaded の後でも画像が表示されないことがあるのはなぜですか?
DOMContentLoaded はドキュメントのパースと関連するブロッキングスクリプトをカバーするものであり、すべての画像やその他のサブリソースを待つわけではありません。load はドキュメントと依存リソースの完了に近いものですが、遅延読み込み(lazy loading)、その後のスクリプトによるフェッチ、継続的な更新が後から続く場合があります。単一のイベントを「すべて完了した」と見なすのではなく、ユーザーから見える目標に一致するパフォーマンスマイルストーンを選択してください。