SSE—その実体、Server-Sent Eventsと単方向ストリーミング

著者: IT Sectr 公開日: 2026-06-02 読了時間: 8 分

SSE(Server-Sent Events)は、サーバーが単方向モードで単一のHTTP接続を通じてクライアントにストリーミングデータを送信できるようにするW3C標準です。WebSocketと違い、SSEは通常のHTTP上で動作し、クライアント側に特別なプロトコルやライブラリを必要としません。W3C HTML Living Standard(2025)仕様によると、EventSource APIは、Chrome、Firefox、Safari、Edgeを含むすべての現代的なブラウザでサポートされています。

まとめ

  • SSEは、HTTP接続を通じてサーバーからクライアントへの単方向データ転送の標準です。
  • EventSource APIは、外部ライブラリなしでSSEを受信するための組み込みブラウザインターフェースです。
  • 自動再接続—接続が切れたとき、ブラウザが自動的に再接続します。
  • テキストプロトコル—データは、簡単なテキスト形式でtext/event-stream形式で送信されます。
  • 単方向コミュニケーション—SSEは通知、ニュースフィード、ティッカー、モニタリングに適していますが、チャットには不向きです。

SSEとは?

SSE(Server-Sent Events)は、ウェブサーバーが接続確立後にいつでもクライアントにデータを送信できるテクノロジーです。これはWHATWGによってHTML Living Standardの一部として標準化され、MIMEタイプtext/event-streamを使用します。SSEは、メッセージ識別子、イベントタイプ、再接続延赤を指定できるテキストデータの送信をサポートします。

双方向プロトコルとアップグレードリクエストが必要なWebSocketと違い、SSEは通常のHTTP上で動作します。サーバーはContent-Type: text/event-streamヘッダーを設定し、データをチャンク単位で送信し、接続を開いたままにします。クライアントは、ブラウザのEventSource APIを通じてデータを受信します。これは自動的にストリームを解析し、イベントを生成します。

CanIUse(2025)によると、EventSource APIはグローバルで97.5%のブラウザでサポートされています。Internet Explorerやいくつかのモバイルブラウザ(バージョン7.0以前のSamsung Internet)ではサポートされていません。これらの場合、XHRストリーミングを通じてEventSourceをエミュレートするポリフィルがあります。SSEはHTTP/1.1パイプライニングでは動作しませんが、HTTP/2サーバープッシュとは完全互換性があります。

歴史と標準化

SSEは2009年にServer-Sent DOM EventsとしてHTML5仕様の一部として提案されました。最初の実装はOpera 9.0、その後Firefox 6.0(2011)、Chrome 9.0(2011)、Safari 5.0(2010)で現れました。2015年に仕様はHTML Living Standardの独立したセクションに移されました。10年以上の歴史にもかかわらず、SSEは単方向であることからWebSocketほど人気がありません。

SSEの仕組み

SSEの仕組みは以下の通りです。クライアントがサーバーエンドポイントのURLを持つEventSourceインスタンスを作成します。ブラウザはAccept: text/event-streamヘッダーを付したGETリクエストを送信します。サーバーはステータス200 OKとContent-Type: text/event-streamヘッダーで答え、その後event-stream形式でデータを送信し始めます。接続は、サーバーが終了シグナルを送るか、クライアントがclose()を呼ぶまで開いたままです。

サーバー側では、データはチャンク単位(chunked transfer encoding)で送信されます。各データチャンクは、フィールド行(event, data, id, retry)からなるテキストメッセージです。サーバーはいつでもメッセージを送信できるため、SSEは通知やステータス更新に最適です。WebSocketのように定期的なハートビートパケットのやり取りは必要ありませんが、retryフィールドが再接続頻度を制御します。

パフォーマンステスト(2024)によると、SSEはメッセージサイズ256バイトで、接続ごとに秒間上 10,000メッセージのスループットを提供します。サーバー側では、各SSE接続は約5–10 KBのメモリを消費し、1 GBのRAMであれば、あるサーバーで50,000以上の同時接続をサポートできます。これは、バイナリプロトコルがないためにWebSocketよりも大幅に少なくなっています。

Event-stream形式

text/event-stream形式は、各メッセージが改行文字で区切られた名前付きフィールドからなる簡単なテキストプロトコルです。各フィールドは“フィールド名: 値”の形式です。メッセージは2つの改行文字(\n\n)で区切られます。

サポートされているフィールド:event(イベントタイプ、デフォルトはmessage)、data(データ文字列、複数行可能)、id(最終イベント識別子、Last-Event-IDに保存)、retry(再接続時間(ミリ秒))。コメントはコロン(:)で始まり、パーサーによって無視されますが、ハートビートに使用できます。

フィールド必須目的
eventなしイベントタイプ(デフォルトはmessage)
dataありメッセージデータ文字列
idなしLast-Event-ID用のイベント識別子
retryなし再接続延赤(ms)

Event-streamの例

text
: heartbeat comment
event: update
data: {"user": "Alice", "action": "typing"}
id: 1001

event: notification
data: {"type": "info", "text": "New version available"}
data: {"type": "action", "url": "/upgrade"}
retry: 3000

event: close
data: Session ended

クライアント側のEventSource API

EventSource APIは、SSEを受信するための組み込みブラウザインターフェースです。接続を作成するには、エンドポイントのURLを使ってコンストラクタを呼ぶだけです。EventSourceは自動的に接続を確立し、再接続を処理し、入力メッセージをJavaScriptイベントに解析します。

EventSourceのイベント:open(接続確立)、message(イベント指定なしでメッセージを受信)、error(接続エラー)。カスタムイベント(event: custom)の場合は、イベント名でaddEventListenerを使用できます。EventSourceは再接続時に自動的にLast-Event-IDヘッダーを送信し、サーバーが中断された場所からストリームを再開できるようにします。

MDNドキュメント(2025)によると、EventSourceはCORSとクレデンシャル伝送(withCredentials)をサポートしています。カスタムヘッダーやリクエストボディを送信するにはEventSourceは不適切です—fetch + ReadableStreamを使ったマニュアル実装が必要です。EventSourceはバイナリデータをサポートしていません—テキストとJSONのみです。

クライアント側JavaScriptコード

js
const eventSource = new EventSource('/api/events/stream');

eventSource.addEventListener('open', () => {
    console.log('SSE接続が開きました');
});

eventSource.addEventListener('message', (event) => {
    const data = JSON.parse(event.data);
    console.log('受信しました:', data);
    renderUpdate(data);
});

eventSource.addEventListener('notification', (event) => {
    const notification = JSON.parse(event.data);
    showNotification(notification.text);
});

eventSource.addEventListener('error', (error) => {
    console.error('SSEエラー:', error);
    // ブラウザが自動再接続
});

// 接続を閉じる
eventSource.close();

SSE vs WebSocket:比較

SSEとWebSocketは、リアルタイムコミュニケーションのための異なるテクノロジーで、それぞれに得意とする分野があります。WebSocketは双方向データ取り換え(チャット、ゲーム、協力エディティング)に適しており、SSEはサーバーからクライアントへの単方向ストリーム(通知、ニュースフィード、ティッカー)に適しています。

主な違いは、WebSocketがHTTP/1.1からWebSocketプロトコル(ws://)へのアップグレードリクエストを必要とすることで、これは企業用プロキシでブロックされる可能性があります。SSEは通常のHTTP上で動作し、どのプロキシでも通し、サーバーの特別な設定も必要ありません。SSEは実装も簡単です—サーバーに追加のライブラリは不要で、HTTPレスポンスを正しく構成すればよいだけです。

比較テスト(2024)によると、単一サーバープロセスで、SSEはより簡単なプロトコルのおかげでWebSocketより30–50%多い接続をサポートします。ただし、SSEはレイテンシが高く(50–200 ms対10–50 msのWebSocket)なのは、SSEが完全な双方向バイナリフレームではなく、チャンクHTTPを使用するからです。

特徴SSEWebSocket
方向サーバー → クライアント双方向
プロトコルHTTP (text/event-stream)ws:// / wss:// (RFC 6455)
ブラウザ97.5% (組み込みEventSource)97% (組み込みWebSocket)
データテキスト / JSONのみテキスト + バイナリ (Blob, ArrayBuffer)
プロキシ処理どのプロキシでも通るプロキシ設定が必要
再接続自動 (ブラウザ)マニュアル実装
履歴Last-Event-ID組み込みの履歴なし

サーバーでのSSE実装方法

サーバーでのSSE実装にはライブラリが必要ありません—正しいHTTPヘッダーを設定し、text/event-stream形式でデータを送信するだけです。組み込みのhttpモジュールを使用したNode.jsの例を見てみましょう。サーバーはContent-TypeとCache-Controlヘッダーを設定し、N秒ごとにメッセージを送信します。

MDN Web Docs(2025)によると、SSEに必要なヘッダーは、Content-Type: text/event-stream、Cache-Control: no-cache、Connection: keep-aliveです。Cache-Controlがないと、ブラウザがSSEストリームをキャッシュする可能性があり、配信が停止します。Connection: keep-aliveは、ブラウザに接続を開いたままにするよう明示的に指示します。

Node.jsのサーバーコード

js
const http = require('http');

http.createServer((req, res) => {
    res.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive'
    });

    let eventId = 0;
    const interval = setInterval(() => {
        eventId++;
        res.write(`id: ${eventId}\n`);
        res.write(`event: update\n`);
        res.write(`data: {"time": "${new Date().toISOString()}", "id":${eventId}}\n\n`);
    }, 2000);

    req.on('close', () => {
        clearInterval(interval);
    });
}).listen(3000);

Python(Flask)でのSSE

python
from flask import Response, Flask
import time
import json

app = Flask(__name__)

@app.route('/stream')
def stream():
    def generate():
        event_id = 0
        while True:
            event_id += 1
            data = json.dumps(
                {'ticker': 'AAPL', 'price': 150.25})
            yield f'id: {event_id}\nevent: price\ndata: {data}\n\n'
            time.sleep(1)
    return Response(generate(),
        mimetype='text/event-stream')

モバイルアプリでのSSE

モバイルアプリでのSSEの使用は、iOSやAndroidにネイティブなEventSource実装がないために制限されています。モバイルプラットフォームでは、SSEはサードパーティライブラリを通じて実装されます:iOSではURLSessionとNSURLProtocolを使用し、AndroidではOkHttpとSSEサポート(okhttp-sse)を使用します。React NativeやFlutterには、EventSourceをエミュレートするパッケージが用意されています。

iOSでは、SSEのネイティブ実装はURLSessionDataDelegateを通じて可能です。urlSession(_:dataTask:didReceive:)メソッドでデータを受信する際、アプリはバッファを簯積し、event-stream形式をマニュアルで解析します。iOS開発ブログ(2024)によると、ハートビートパケットがないため、iOSでのSSEの電池消費は一定的なWebSocket接続より40%低くなっています。

Androidでは、OkHttpがSSEストリームにサブスクライブするためのEventSource.Factoryクラスを提供しています。Androidアプリは、FCMが利用不可な場合の通知や、バックグラウンドのデータ同期にSSEを使用できます。AndroidでのSSEは、長期間のバックグラウンドタスクにWorkManagerと組み合わせて良く動作します。OkHttpドキュメント(2025)によると、okhttp-sseはカスタムリスナーで自動再接続をサポートしています。

よくある質問

SSEとWebSocketの違いは?

SSEはHTTP上での単方向伝送(サーバー → クライアント)で、クライアント側にライブラリは不要です。WebSocketはバイナリプロトコルによる双方向伝送です。SSEは実装が簡単で、WebSocketはクライアントもデータを送信するタスクに適しています。

SSEはバイナリデータをサポートしていますか?

いいえ、SSEはテキストデータのみを伝送します。バイナリデータ(画像、音声)にはBase64エンコードが必要で、サイズが33%増加します。バイナリストリームにはWebSocketを使用するほうが良いです。

SSEは接続切断をどう処理しますか?

EventSourceは切断が発生したときに自動的に再接続します。延赤時間はストリームでretryフィールド(デフォルト1000 ms)で設定されます。再接続時にブラウザはLast-Event-IDヘッダーを送信し、サーバーが中断された場所からストリームを再開できるようにします。

ブラウザは何つのSSE接続を保持できますか?

各ブラウザには、同じドメインへの同時HTTP接続の制限があります。HTTP/1.1の場合はドメインごとに6–8接続、HTTP/2の場合は最大100接続です。SSEは1つの接続を使用するため、他のリクエストと競合することはありません。

SSEをチャットに使用できますか?

SSEはメッセージの受信(入力)のみに適しています。メッセージの送信(出力)には、別途HTTPリクエスト(POST)が必要です。完全なチャットには、単一接続で双方向コミュニケーションを提供するWebSocketやSocket.IOを使用するのが便利です。

まとめ

  • SSEは、追加のライブラリなしで通常のHTTP接続を通じてサーバーからクライアントへの単方向データ転送の標準です。
  • EventSource APIは、97.5%の現代ブラウザでサポートされている組み込みブラウザインターフェースです。
  • 簡単なテキストプロトコル text/event-streamで、event、data、id、retryのフィールドを持ちます。
  • 自動再接続—Last-Event-IDをサポートし、中断された場所からストリームを再開できます。
  • 効率的—SSEはより簡単なプロトコルにより、WebSocketよりも多くのサーバー接続(50,000+)をサポートします。
  • モバイルプラットフォームではSSEは、マニュアルなストリーム解析とともにOkHttp(Android)やURLSession(iOS)を通じて実装されます。
  • 単方向ストリーム(通知、フィード、ティッカー)にはSSEを選択し、双方向コミュニケーションにはWebSocketやSocket.IOを選択してください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください