React 및 Node.js를 사용하여 서버에서 보낸 이벤트로 빌드

이 글은 제가 제 블로그에 쓴 글을 반영한 것입니다. 아래에 제시된 코드의 Python 또는 기본 자바스크립트 예제를 원하시면 언제든지 check it out here

웹에서 실시간 애플리케이션을 구축하는 것이 그 어느 때보다 쉬워졌습니다. 이 게시물에서는 서버 전송 이벤트(SSE)를 사용하여 웹 애플리케이션에 대한 실시간 데이터를 얻는 방법을 설명합니다.

이 기사의 끝에서 알아야 할 사항:
  • 서버 전송 이벤트란 무엇입니까
  • 브라우저에서 서버 전송 이벤트를 수신하는 방법
  • 서버에서 서버 전송 이벤트를 보내는 방법

  • 이 튜토리얼은 웹 개발에 어느 정도 친숙하고 Python 또는 nodejs에 대한 지식이 있는 사람들을 위한 것입니다.



    요점



    서버 전송 이벤트(SSE)는 클라이언트가 시작한 단방향 서버 제어 메시지입니다. SSE 지원 끝점을 쿼리하는 웹 사이트를 방문하면 서버는 해당 페이지를 떠날 때까지 브라우저에 무제한 정보를 보낼 수 있습니다. SSE URL은 항상 브라우저의 비동기 요청을 통해 액세스됩니다. 브라우저에서 SSE 끝점을 제공하는 URL을 방문할 수 있지만 경험하게 될 표준은 없습니다.

    const source = new EventSource('/an-endpoint');
    
    source.onmessage = function logEvents(event) {
       console.log(JSON.parse(data));
    }
    


    이 코드 스니펫에서는 URLEventSource을 수신하는 새 /an-endpoint 객체를 만듭니다. EventSource는 우리를 위해 server-sent-events를 수신하는 무거운 작업을 수행하는 도우미 클래스입니다. 지금 해야 할 일은 logEvents 핸들러에 함수(이 경우에는 onmessage)를 연결하는 것입니다.

    서버가 메시지를 보낼 때마다 source.onmessage가 실행됩니다.

    좀 더 현실적인 예를 들어보자. 아래 코드는 url https://ds.shub.dev/e/temperatures 의 서버에서 수신 대기합니다. 5초마다 서버는 내 거실의 온도와 함께 서버 전송 이벤트를 반환합니다.

    
    // @codepen-link:https://codepen.io/4shub/pen/QWjorRp
    import React, { useState, useEffect } from 'react';
    import { render } from "react-dom";
    
    const useEventSource = (url) => {
        const [data, updateData] = useState(null);
    
        useEffect(() => {
            const source = new EventSource(url);
    
            source.onmessage = function logEvents(event) {      
                updateData(JSON.parse(event.data));     
            }
        }, [])
    
        return data;
    }
    
    function App() {
      const data = useEventSource('https://ds.shub.dev/e/temperatures');
      if (!data) {
        return <div />;
      }
    
      return <div>The current temperature in my living room is {data.temperature} as of {data.updatedAt}</div>;
    }
    
    render(<App />, document.getElementById("root"));
    


    무대 뒤에서 무슨 일이 일어나고 있습니까?





    EventSource의 다음 두 가지 속성을 살펴보겠습니다.
  • url - 변경 사항을 수신할 URL
  • readyState - 연결 상태입니다. 이것은 (0) CONNECTING , (1) OPEN(2) CLOSED 일 수 있습니다. 처음에 이 값은 CONNECTING입니다.

  • EventSource가 호출되면 브라우저는 통과된 헤더Accept: text/event-stream에서 url로 요청을 생성합니다.

    그런 다음 브라우저는 요청이 200 OK 응답과 Content-Type : text/event-stream 를 포함하는 헤더를 반환하는지 확인합니다. 성공하면 readyStateOPEN로 설정되고 onopen 메서드가 트리거됩니다.

    그러면 해당 응답의 데이터는 parsed이 되고 onmessage를 트리거하는 이벤트가 발생합니다.

    마지막으로, 우리가 핑한 서버는 다음까지 무제한의 event-stream 콘텐츠를 보낼 수 있습니다.
  • 페이지를 닫습니다
  • 이벤트 소스
  • 에서 close() 메서드를 실행합니다.
  • 서버가 잘못된 응답을 보냅니다
  • .

    마지막으로 연결을 닫으면 EventSource 개체의 readyStatereadyStateCLOSED로 설정하고 onclose 이벤트를 트리거하는 작업을 시작합니다.

    네트워크 중단의 경우 브라우저는 노력이 "쓸모 없는"것으로 판단될 때까지 재연결을 시도합니다(불행히도 "쓸모 없는"기준은 없습니다).

    서버에서 이벤트 보내기



    서버에서 보낸 이벤트를 보내는 것은 이벤트를 듣는 것만큼 쉽습니다. 아래에는 서버에서 보낸 이벤트를 클라이언트에 보내는 몇 가지 다른 구현을 작성했습니다.

    // @repl-it-link:https://repl.it/@4shub/server-sent-events-node
    const express = require('express');
    
    const server = express();
    const port = 3000;
    
    // create helper middleware so we can reuse server-sent events
    const useServerSentEventsMiddleware = (req, res, next) => {
        res.setHeader('Content-Type', 'text/event-stream');
        res.setHeader('Cache-Control', 'no-cache');
    
        // only if you want anyone to access this endpoint
        res.setHeader('Access-Control-Allow-Origin', '*');
    
        res.flushHeaders();
    
        const sendEventStreamData = (data) => {
            const sseFormattedResponse = `data: ${JSON.stringify(data)}\n\n`;
            res.write(sseFormattedResponse);
        }
    
        // we are attaching sendEventStreamData to res, so we can use it later
        Object.assign(res, {
            sendEventStreamData
        });
    
        next();
    }
    
    const streamRandomNumbers = (req, res) => {
        // We are sending anyone who connects to /stream-random-numbers
        // a random number that's encapsulated in an object
        let interval = setInterval(function generateAndSendRandomNumber(){
            const data = {
                value: Math.random(),
            };
    
            res.sendEventStreamData(data);
        }, 1000);
    
        // close
        res.on('close', () => {
            clearInterval(interval);
            res.end();
        });
    }
    
    server.get('/stream-random-numbers', useServerSentEventsMiddleware, 
        streamRandomNumbers)
    
    
    server.listen(port, () => console.log(`Example app listening at 
        http://localhost:${port}`));
    


    위의 예에서는 사용자에게 매초 임의의 숫자를 보내는 이벤트 스트림이 있는 서버를 만들었습니다.

    결론



    많은 회사에서 서버 전송 이벤트를 사용하여 데이터를 사용자에게 실시간으로 전달합니다. LinkedIn은 에 대해 서버 전송 이벤트를 사용하고, Mapbox는 SSE를 사용하여display live map data, 많은 분석 도구는 SSE를 사용하여 실시간 사용자 보고서를 표시합니다. SSE는 모니터링 도구와 실시간 이벤트가 사용자와 더 관련성이 높아짐에 따라 더욱 두드러질 것입니다.

    당신이 그것을 시도하면 알려주세요 - 나는 당신이 무엇을 생각해내는지 보고 싶습니다!

    좋은 웹페이지 즐겨찾기