서버 전송 이벤트란?

Server Sent Event는 이벤트 스트림을 통해 서버로부터 데이터를 받는 것 외에는 아무것도 아닙니다. 이것은 단방향 통신이며 서버만 데이터를 클라이언트에 푸시할 수 있습니다. WebSocket은 양방향으로 작동하고 페이로드가 있는 이벤트를 서버에 보낼 수 있고 서버는 클라이언트에 이벤트를 트리거할 수 있습니다.

EventSource는 서버에서 이벤트 스트림을 여는 데 사용되는 클래스입니다. EventSource 클래스의 객체를 생성하고 생성자 내부에 API URL을 전달해야 합니다. 그런 다음 서버에서 트리거되는 이벤트를 구독하십시오. API에 의해 트리거되는 맞춤 이벤트가 없는 경우 메시지는 구독할 수 있는 기본 이벤트입니다.

아래 예시를 확인하세요.

let eventStream = new EventSource(`${URL}?city=${selectedCityValue}&sec=${secondsToUpdate.value}`);
    eventStream.addEventListener('open', () => {
        console.log("Connected and subscribed to channel ");
    });
    eventStream.addEventListener('UPDATE', (event) => {
        const data = JSON.parse(event.data);
        console.log('eventStream data', data);
        time.innerHTML = data.dateTime;
    });
    eventStream.addEventListener('error', (err) => {
        console.error("EventSource failed:", err);
    });


쿼리 매개변수를 API URL로 보내어 부분적으로 양방향 통신을 할 수 있습니다. 🙂 그리고 쿼리 매개변수를 보내거나 업데이트할 때마다 이 이전 연결을 닫고 다른 연결을 열면 됩니다.

이벤트 소스 개체에서 제공하는 닫기 메서드를 사용하여 연결을 닫습니다.

if(eventStream) {
    eventStream.close();
}


저는 백엔드 기술에 대한 경험이 많지 않지만 예제 목적으로 간단한 노드 서버를 만들었습니다.

const express = require('express');
const app = express();
const MAX_LIMIT = 100;

function getFormattedDate() {
    const d = new Date();
    return `${d.getDate()}/${d.getMonth()+1}/${d.getFullYear()} ${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
}
app.get('/event-stream', (req, res) => {
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Access-control-Allow-Origin', '*');
    res.setHeader('Connection', 'keep-alive');

    res.flushHeaders();
    const sec = (req.query && req.query.sec) ? req.query.sec : 5
    const timezone = (req.query && req.query.city) ? req.query.city : 'Asia/Calcutta';
    let count = 0;
    process.env.TZ = timezone;
    console.log('Request Param -> ', timezone, ' seconds -> ', sec);
    let interval = setInterval(() => {
        count++;
        if(count >= MAX_LIMIT) {
            console.log('Interval Reached Max Limit Closing the Connection'); 
            clearInterval(interval);
            res.end();
            return;
        }
        const obj = {
            id: count,
            dateTime: getFormattedDate()
        };
        const time = new Date().getTime();
        res.write(`id: ${time}_${count}\n`);
        res.write(`event: UPDATE\n`);
        res.write(`data: ${JSON.stringify(obj)}\n\n`);
    }, sec * 1000);

    req.on('open', (event) => {
        console.log('connection open ', event);
    });
    res.on('close', () => {
        console.log('closed connection');
        clearInterval(interval);
        res.end();
    });
});
app.listen(3000, () => { 
    console.log('listening on port 3000');
});


SSE를 사용하여 현재 서버 시간을 표시하려면 live example을 선택하십시오. ( Full Source Code )

The limitation of SSE is browser can open only six connections and this limit is per browser with the domain. This limitation is there only when using HTTP/1, not for HTTP/2 has increased this limit.



SSE를 활용할 수 있는 실용적이고 현실적인 시나리오는 서버 측에서 처리해야 하는 대규모 데이터 세트가 있고 해당 프로세스가 언제 완료될지 정확히 알 수 없는 경우입니다. 이 문제를 해결하기 위한 두 가지 솔루션이 있습니다.
  • 서버에 REST API 요청을 전송하여 처리를 시작한 다음 API를 통해 서버에서 상태를 가져오기 시작하여 프로세스 완료 여부를 확인합니다.
  • 서버에 REST API 요청을 전송하여 프로세스를 시작한 다음 일부 고유한 프로세스 ID를 쿼리 매개변수로 사용하여 이벤트 소스 객체를 생성합니다. 프로세스가 완료되면 서버에서 작업을 발송합니다. 두 번째 방법은 때때로 서버에서 상태를 가져오는 것보다 더 깔끔합니다.



  • 이 시나리오를 시연할 수 있는 live example을 확인하십시오. ( Source Code )

    좋은 웹페이지 즐겨찾기