HTTP/2とHTTP/3 - Webプロトコルの進化

14分 で読める | 2025.12.05

公式ドキュメント

HTTPの進化

HTTPは、Webの基盤となるプロトコルです。1991年のHTTP/0.9から始まり、現在はHTTP/3まで進化しています。

flowchart LR
 H09["HTTP/0.9<br/>(1991)"] --> H10["HTTP/1.0<br/>(1996)"]
 H10 --> H11["HTTP/1.1<br/>(1997)"]
 H11 --> H2["HTTP/2<br/>(2015)"]
 H2 --> H3["HTTP/3<br/>(2022)"]

HTTP/1.1の課題

Head-of-Line Blocking

1つのTCP接続では、リクエストを順番に処理する必要があります。

sequenceDiagram
 participant C as クライアント
 participant S as サーバー

 Note over C,S: HTTP/1.1 - 順次処理
 C->>S: リクエスト1
 S-->>C: レスポンス1
 C->>S: リクエスト2
 S-->>C: レスポンス2
 C->>S: リクエスト3
 S-->>C: レスポンス3

 Note over C,S: 先のリクエストがブロックすると<br/>後続も待たされる

複数接続の必要性

並列性を確保するため、ブラウザは1ドメインあたり6-8本のTCP接続を使用します。

flowchart TB
 subgraph Domain["ドメイン: example.com"]
 TCP1["TCP接続1: script.js"]
 TCP2["TCP接続2: style.css"]
 TCP3["TCP接続3: image1.jpg"]
 TCP4["TCP接続4: image2.jpg"]
 TCP5["TCP接続5: image3.jpg"]
 TCP6["TCP接続6: image4.jpg"]
 end

 Note["接続のオーバーヘッド、リソースの無駄"]

HTTP/2の特徴

多重化(Multiplexing)

1つのTCP接続で複数のリクエスト/レスポンスを並列処理できます。

flowchart TB
 subgraph TCP["HTTP/2: 単一TCP接続"]
 subgraph Requests["リクエスト(並列)"]
 R1["Req 1"]
 R2["Req 2"]
 R3["Req 3"]
 R4["Req 4"]
 end
 subgraph Responses["レスポンス(並列)"]
 S1["Res 1"]
 S2["Res 2"]
 S3["Res 3"]
 S4["Res 4"]
 end
 R1 --> S1
 R2 --> S2
 R3 --> S3
 R4 --> S4
 end

 Note["並列処理、順序に依存しない"]

バイナリプロトコル

HTTP/1.1のテキストベースからバイナリフレームに変更。

flowchart TB
 subgraph HTTP11["HTTP/1.1(テキスト)"]
 Text["GET /index.html HTTP/1.1\r\n<br/>Host: example.com\r\n"]
 end

 subgraph HTTP2["HTTP/2(バイナリフレーム)"]
 Header["Length | Type | Flags"]
 StreamID["Stream ID"]
 Payload["Payload"]
 Header --> StreamID --> Payload
 end

ヘッダー圧縮(HPACK)

ヘッダーを効率的に圧縮し、重複するヘッダーを省略します。

flowchart LR
 subgraph First["1回目のリクエスト"]
 F1[":method: GET"]
 F2[":path: /index.html"]
 F3[":authority: example.com"]
 F4["user-agent: Mozilla/5.0..."]
 F5["accept: text/html"]
 end

 subgraph Second["2回目のリクエスト"]
 S1[":path: /style.css"]
 S2["(他は前回と同じなので省略)"]
 end

 First --> Second
 Note["ヘッダーサイズが大幅に削減"]

サーバープッシュ

クライアントがリクエストする前に、サーバーからリソースを送信できます。

sequenceDiagram
 participant C as クライアント
 participant S as サーバー

 C->>S: index.html リクエスト
 S-->>C: index.html レスポンス
 S-->>C: style.css プッシュ(リクエストなしで送信)
 S-->>C: script.js プッシュ

 Note over C,S: RTTを削減

注意: サーバープッシュは実際にはあまり使われておらず、Chrome 106以降では無効化されています。代替として103 Early Hintsの活用を検討してください。

優先度制御

ストリームに優先度を設定し、重要なリソースを先に処理できます。

flowchart TB
 subgraph Priority["優先度制御"]
 S1["ストリーム1 (HTML): 優先度 高"]
 S2["ストリーム2 (CSS): 優先度 高"]
 S3["ストリーム3 (画像): 優先度 低"]
 end

 S1 & S2 --> Load["HTML/CSSを先にロード"]
 S3 -.-> Load

HTTP/2の課題

TCPレベルのHead-of-Line Blockingは解決できていません。

flowchart TB
 subgraph TCP["HTTP/2 over TCP"]
 P1["パケット1 ✓"]
 P2["パケット2 ✓"]
 P3["パケット3 ✗ (パケットロス)"]
 P4["パケット4 ✓ → TCP層で待機"]
 P5["パケット5 ✓ → TCP層で待機"]
 end

 P3 --> Block["1つのパケットロスで<br/>全ストリームがブロック"]

 style P3 fill:#f99,stroke:#f00
 style P4 fill:#ff9,stroke:#f90
 style P5 fill:#ff9,stroke:#f90

HTTP/3とQUIC

HTTP/3は、TCPの代わりにQUICプロトコル(UDP上に構築)を使用します。

QUICの特徴

flowchart TB
 subgraph Traditional["従来"]
 T_App["アプリケーション層: HTTP/2"]
 T_Trans["トランスポート層: TCP + TLS"]
 T_Net["ネットワーク層: IP"]
 T_App --> T_Trans --> T_Net
 end

 subgraph HTTP3["HTTP/3"]
 H_App["アプリケーション層: HTTP/3"]
 H_Trans["トランスポート層: QUIC<br/>(UDP + TLS 1.3 統合)"]
 H_Net["ネットワーク層: IP"]
 H_App --> H_Trans --> H_Net
 end

ストリーム独立性

各ストリームが独立しており、1つのパケットロスが他のストリームに影響しません。

flowchart TB
 subgraph QUIC["HTTP/3 over QUIC"]
 S1["ストリーム1: パケット1 ✓ → 処理続行"]
 S2["ストリーム2: パケット2 ✗ (ロス)<br/>→ このストリームのみ再送待ち"]
 S3["ストリーム3: パケット3 ✓ → 処理続行"]
 end

 Note["ストリーム間で独立"]

 style S2 fill:#ff9,stroke:#f90

0-RTT接続

以前接続したサーバーへの再接続が高速化されます。

sequenceDiagram
 participant C as クライアント
 participant S as サーバー

 Note over C,S: 従来のTCP + TLS
 C->>S: 1. TCP SYN
 S->>C: 2. TCP SYN-ACK
 C->>S: 3. TCP ACK + TLS ClientHello
 S->>C: 4. TLS ServerHello
 S->>C: 5. TLS Finished
 C->>S: 6. データ送信開始

 Note over C,S: QUIC 0-RTT
 C->>S: 1. QUIC Initial(前回のセッション情報 + データ)
 Note over C,S: 最初のパケットからデータ送信可能

接続のマイグレーション

IPアドレスが変わっても接続を維持できます。

ポイント: QUICではコネクションIDで接続を識別するため、WiFiからモバイル回線に切り替わっても通信が途切れません。モバイルアプリにとって大きなメリットです

flowchart LR
 subgraph Traditional["従来"]
 T1["WiFi"] --> T2["モバイル回線"]
 T2 --> T3["IPアドレス変更"]
 T3 --> T4["接続切断"]
 T4 --> T5["再接続"]
 end

 subgraph QUIC["QUIC"]
 Q1["WiFi"] --> Q2["モバイル回線"]
 Q2 --> Q3["接続ID維持"]
 Q3 --> Q4["シームレスに継続"]
 end

 style T4 fill:#f99,stroke:#f00
 style Q4 fill:#9f9,stroke:#0f0

パフォーマンス比較

観点HTTP/1.1HTTP/2HTTP/3
接続数複数必要1接続1接続
HoLブロックあり部分的解決解決
接続確立遅い遅い高速
パケットロス耐性低い低い高い
モバイル対応弱い普通強い

対応状況の確認

// ブラウザでの確認
if (window.performance) {
 const entries = performance.getEntriesByType('navigation');
 console.log(entries[0].nextHopProtocol);
 // → "h2" (HTTP/2) または "h3" (HTTP/3)
}
# curlでの確認
curl -I --http2 https://example.com
curl -I --http3 https://example.com

サーバー設定例

Nginx(HTTP/2)

server {
 listen 443 ssl http2;
 ssl_certificate /path/to/cert.pem;
 ssl_certificate_key /path/to/key.pem;
}

Cloudflare(HTTP/3)

Cloudflareを使用している場合、ダッシュボードからHTTP/3を有効化できます。

まとめ

HTTP/2は多重化とヘッダー圧縮により、HTTP/1.1の課題を大幅に改善しました。HTTP/3はQUICプロトコルにより、さらにパケットロス耐性とモバイル対応を強化しています。現代のWebサイトでは、HTTP/2以上の対応が推奨されます。

実践メモ: CloudflareやAWS CloudFrontなどのCDNを利用すれば、サーバー側の設定を変更せずにHTTP/3対応が可能です。

参考リソース

← 一覧に戻る
PR
PR
PR
PR