未分類
ブラウザでURLを叩いて表示されるまでに何が起きているか
技術面接の定番質問である。ネットワークからブラウザレンダリングまでの理解度が問われる。
全体の流れ
図を読み込み中...
1. URL解析
ブラウザがURLをパースする。
https://example.com:443/path?query=value#hash
│ │ │ │ │ │
│ │ │ │ │ └─ フラグメント(ブラウザ側のみ)
│ │ │ │ └─ クエリ文字列
│ │ │ └─ パス
│ │ └─ ポート(省略時: http=80, https=443)
│ └─ ホスト名
└─ スキーム(プロトコル)
2. DNSルックアップ
ホスト名からIPアドレスを取得する。
解決の順序
- ブラウザキャッシュ - 直近のDNS結果をキャッシュ
- OSキャッシュ -
/etc/hostsやOSのDNSキャッシュ - ルーターキャッシュ - ルーターが保持するキャッシュ
- ISPのDNSサーバー - 契約プロバイダのDNS
- 再帰的DNS問い合わせ - ルート → TLD → 権威DNSサーバー
ブラウザ → ISP DNS → ルートDNS(.)
→ TLD DNS(.com)
→ 権威DNS(example.com)
← IPアドレス返却
3. TCP接続(3ウェイハンドシェイク)
信頼性のある接続を確立する。
クライアント サーバー
│ │
│── SYN ──────────→│ 1. 接続要求
│ │
│←─── SYN-ACK ─────│ 2. 要求受諾 + 接続要求
│ │
│── ACK ──────────→│ 3. 接続確立
│ │
4. TLSハンドシェイク(HTTPSの場合)
暗号化通信を確立する。TLS 1.3では1-RTTに短縮。
クライアント サーバー
│ │
│── ClientHello ────────→│ 対応暗号スイート提示
│ │
│←─── ServerHello ───────│ 暗号スイート決定
│←─── Certificate ───────│ サーバー証明書
│←─── ServerHelloDone ───│
│ │
│── ClientKeyExchange ──→│ 共有鍵生成用データ
│── ChangeCipherSpec ───→│ 暗号化開始通知
│── Finished ───────────→│
│ │
│←─── ChangeCipherSpec ──│
│←─── Finished ──────────│
│ │
│ ★ 暗号化通信開始 ★ │
5. HTTPリクエスト送信
GET /path HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 ...
Accept: text/html,application/xhtml+xml
Accept-Language: ja,en
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: session_id=abc123
6. サーバー処理
- Webサーバー(nginx/Apache)がリクエスト受信
- リバースプロキシ → アプリケーションサーバー
- ルーティング処理
- ビジネスロジック実行
- DBクエリ(必要に応じて)
- テンプレートレンダリング or JSON生成
- レスポンス返却
7. HTTPレスポンス受信
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip
Cache-Control: max-age=3600
Content-Length: 12345
<!DOCTYPE html>
<html>...
8. ブラウザレンダリング
ここからがブラウザ内部の処理。クリティカルレンダリングパスと呼ばれる。
8.1 HTMLパース → DOMツリー構築
バイト → 文字 → トークン → ノード → DOMツリー
HTMLを上から順にパース。<script>タグに遭遇するとパースをブロック(async/deferがない場合)。
8.2 CSSパース → CSSOMツリー構築
バイト → 文字 → トークン → ノード → CSSOMツリー
CSSはレンダリングブロッキング。CSSOMが完成するまでレンダリングは待機。
8.3 JavaScriptの実行
- パーサーブロッキング: 通常の
<script>はDOM構築を止める - async: ダウンロード完了次第実行(順序保証なし)
- defer: DOMパース完了後に順序通り実行
8.4 レンダーツリー構築
DOMツリー + CSSOMツリー → レンダーツリー
- 表示されるノードのみ含む
display: noneは含まれないvisibility: hiddenは含まれる(スペースを占有)
8.5 レイアウト(リフロー)
各ノードの正確な位置とサイズを計算。
- ビューポートサイズを基準に計算
%指定は親要素から算出- コストが高い処理(DOM変更で再計算が走る)
8.6 ペイント
レンダーツリーを実際のピクセルに変換。
- 背景色、テキスト、ボーダーなどを描画
- 複数のレイヤーに分けて描画される
8.7 コンポジット
複数のレイヤーを合成して最終的な画面を生成。
transformやopacityはコンポジット層で処理(高速)- GPU加速が効く
レンダリングパイプライン図
┌─────────────────────────────────────────────────────────┐
│ Critical Rendering Path │
└─────────────────────────────────────────────────────────┘
HTML ─→ DOM ─────────────────────────┐
│
├─→ Render Tree ─→ Layout ─→ Paint ─→ Composite
│
CSS ─→ CSSOM ────────────────────────┘
JS ─→ DOM/CSSOM操作 ─→ 上記パイプラインを再実行(部分的に)
面接での回答ポイント
ネットワーク層について問われたら
- DNS解決のキャッシュ階層
- TCP 3ウェイハンドシェイク
- TLSの役割と1-RTT化(TLS 1.3)
- HTTP/2, HTTP/3(QUIC)の違い
レンダリングについて問われたら
- クリティカルレンダリングパス
- パーサーブロッキング vs レンダーブロッキング
- リフロー・リペイントのコスト
async/deferの違い
パフォーマンス改善について問われたら
- DNSプリフェッチ(
<link rel="dns-prefetch">) - プリコネクト(
<link rel="preconnect">) - CSSをhead、JSをbody末尾に
- 画像の遅延読み込み(
loading="lazy") - Core Web Vitals(LCP, FID, CLS)
まとめ
| フェーズ | 主な処理 |
|---|---|
| 1. URL解析 | スキーム、ホスト、パスに分解 |
| 2. DNS | ホスト名 → IPアドレス |
| 3. TCP | 3ウェイハンドシェイクで接続確立 |
| 4. TLS | 暗号化通信の確立 |
| 5. HTTP | リクエスト送信 |
| 6. サーバー | ルーティング、DB、レスポンス生成 |
| 7. レスポンス | HTML/CSS/JS等を受信 |
| 8. レンダリング | DOM→CSSOM→レンダーツリー→レイアウト→ペイント→コンポジット |
各フェーズの詳細も説明できるようにしつつ、全体を俯瞰しておくとよい。