🚀

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以降では無効化されています。

優先度制御

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

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アドレスが変わっても接続を維持できます。

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以上の対応が推奨されます。

← 一覧に戻る