server sent event를 사용해서 server to client 이벤트 만들기
수정일: 2026. 1. 29.
태그:
-
SSE
-
SSE를 통해 만들 수 있는 것
-
SSE
- server sent event를 가리킵니다. 말 그대로 서버에서 보내는 이벤트라는 내용입니다.
- 메커니즘
- 클라이언트는 최초 서버와 통신을 합니다.
- 이 때, server는 HTML을 반환하면서 javascript로 client가 구독해야 할 server sent event api 주소를 구독하게 합니다.
- 클라이언트는 최초 서버와 통신을 합니다.
// client.js
const eventSource = new EventSource("/api/stream", {
withCredentials: true,
});
EventSource 객체를 생성합니다. 해당 객체는 인자의 첫번째로 입력한 주소를 구독하게 됩니다.
두번째 인자는 cookie의 credentials값을 구독 요청시 자동으로 보내 이 요청자의 유효성 체크를 위해 사용됩니다.
여기서 제가 굳이 구독이라한 이유는 이 연결을 1회성으로 두지 않고 연결을 유지해둔다는 점이 polling과 SSE를 나눕니다.
// server.js
const stream = new ReadableStream({
start(controller) {
const encoder = new TextEncoder();
controller.enqueue(createSSEMessage({ type: "connected" }));
},
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive", // 이 옵션을 통해 연결을 끊지 않고 유지합니다.
},
});
위 코드는 client의 요청을 받아 Readable Stream을 생성하고, controller에 enqueue합니다. stream은 기본적으로 queue 형태를 하고 있으므로 먼저 요청받은 데이터를 청크하여 맨 뒤에 붙입니다. 그리고 아래의 response를 통해 client에게 전달됩니다.
SSE라고는 해도 처음에 client와의 구독 관계를 가져야만 합니다. 이후에는 server에 요청을 보내는 것으로 client는 구독하고 있는 api로 부터 이벤트를 서버로부터 받게 됩니다.
이러한 모델을 차용한 것은
- 앱의 푸시
- 웹의 notification,
- 알림 등
아주 많은 모델들이 있습니다.
중요한점은 keep alive로 유저와의 연결이 유지되어 빠른 발송이 가능하지만, 서버는 한 객체에 이 연결들을 모두 인메모리로 가지고 있어야하기 때문에 해당 객체의 관리가 필요합니다.
만일 여러 서버 인스턴스를 운영중이라면 하나의 redis나 이를 위한 중앙 집중식 서버를 하나 더 띄우는 것을 추천드립니다.