はじめまして、花王株式会社の @TsuchiyaK です。
生成AIチャットアプリなどで「AIの回答をリアルタイムに順次表示したい」という要件はよくあるかと思います。
その際によく使われるのが Server-Sent Events (SSE) です。
本記事では、SSEの概要と、フロントエンドでの実装方法についてまとめます。
Server-Sent Events (SSE)とは?
SSEは、サーバーからクライアント(主にWebブラウザ)へ、一方向にリアルタイムでデータをプッシュするための仕組みです。
WebSocketと違い、クライアント→サーバーの通信はできませんが、HTTP/1.1ベースで実装がシンプル、サーバー側の負担も比較的軽いのが特徴です。
生成AIチャットアプリでは、AIの回答を「一文字ずつ」や「一文ずつ」ストリーミング表示する際によく使われます。
クライアント側のSSE実装方法
SSEを受け取る方法はいくつかあります。代表的なものを3つ紹介します。
1. EventSource
EventSourceオブジェクトを使い、サーバーとコネクションを張りっぱなしにしてtext/event-stream
形式のデータを受信します。
const eventSource = new EventSource('/sse-endpoint');
eventSource.onmessage = (event) => {
console.log(event.data); // サーバーからのデータ
};
メリット
- 実装が簡単で、ブラウザ標準対応
- 自動で再接続される
デメリット
- HTTPメソッドはGETのみ(POST不可)
- カスタムヘッダーが付けられないため、CORSや認証に工夫が必要な場合がある
2. fetch + ReadableStream
fetch
でSSEエンドポイントにアクセスし、ReadableStreamでストリームを逐次処理します。
バイナリデータをテキストにデコードし、必要に応じてJSONにパースします。
const response = await fetch('/sse-endpoint');
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
// bufferを適宜パースして利用
}
メリット
- POSTやカスタムヘッダーが利用可能
- 細かい制御や独自プロトコルにも対応しやすい
デメリット
- 自動再接続などの仕組みは自前で実装が必要
- 実装がやや複雑
3. Axios
HTTPクライアントライブラリのAxiosを使用してresponseType: 'stream'
を指定することでストリームレスポンスを受け取れますが、これはNode.js環境限定です。
ブラウザ環境のXMLHttpRequestのResponseTypeでは'stream'
は使えません。
// Node.jsの場合
const axios = require('axios');
const response = await axios.get('/sse-endpoint', { responseType: 'stream' });
response.data.on('data', (chunk) => {
console.log(chunk.toString());
});
メリット
- Node.js環境でのストリーム処理が簡単
デメリット
- ブラウザ環境では
responseType: 'stream'
が使えない
ブラウザでAxiosを使いたい場合
adapter: 'fetch'
を指定することで、2.のfetchと同様の方法でストリームを受け取れます。
参考:Fetch adapter | axios | promise based HTTP client
import axios from 'axios';
const response = await axios.get('/sse-endpoint', {
adapter: 'fetch'
// 他のfetchオプションも指定可能
});
// response.bodyはReadableStream
まとめ
- SSEは生成AIチャットアプリなどで「リアルタイムにサーバーからデータを受け取る」用途に便利
- 実装方法は用途や環境に応じて選択(EventSource, fetch, Axios)
- 認証やPOSTリクエストが必要な場合はfetchが柔軟
SSEを活用して、よりリッチなリアルタイムWeb体験を実現しましょう!