본문 바로가기
SPA/React

[React] SSE (Server-Sent Events) 사용하여 실시간 통신하기

by J4J 2024. 5. 8.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 sse (server-sent events) 사용하여 실시간 통신하는 방법에 대해 적어보는 시간을 가져보려고 합니다.

 

 

 

관련 글

 

[SpringBoot] SSE (Server-Sent Events) 사용하여 실시간 통신하기

 

 

반응형

 

 

들어가기에 앞서

 

해당 글에서는 sse API가 존재할 때 react에서 어떻게 활용할 수 있는지에 대해서 적어보려고 합니다.

 

만약 sse에 대한 기본 개념에 대해서 먼저 알고 싶으신 분들은 위의 링크를 참고해 주시면 됩니다.

 

 

 

 

SSE (Server-Sent Events) 사용 환경 설정

 

react에서 sse 사용 환경 설정하는 방법에 대해 적어보겠습니다.

 

sse API는 관련 글에서 확인할 수 있는 spring에서 제공해주는 API를 활용해 보겠습니다.

 

  • 구독 API → [GET] http://localhost:8080/subscribe/{id}
  • 발송 API → [POST] http://localhost:8080/send/{id}

 

 

 

react에서 sse를 사용하기 위해 추가적으로 package를 설치하는 등의 행위는 하지 않아도 됩니다.

 

다음과 같이 javascript에서 기본적으로 제공해 주는 기능을 활용하여 구현해 볼 수 있습니다.

 

import axios from 'axios';
import { FormEvent, useState } from 'react';

interface EventMessage {
    eventName: string;
    data: string;
}

export default function App() {
    // state
    const [id, setId] = useState<string>('');
    const [eventName, setEventName] = useState<string>('');
    const [data, setData] = useState<string>('');
    const [eventMessages, setEventMessages] = useState<EventMessage[]>([]);

    // message event config
    const configMessageEvent = (event: MessageEvent) => {
        setEventMessages((prev) => [
            ...prev,
            {
                eventName: event.type,
                data: event.data,
            },
        ]);
    };

    // event handler
    const handleSubmitSubscribe = (e: FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        const eventSource = new EventSource(`http://localhost:8080/subscribe/${id}`);

        // 연결된 sse emitter의 event name(connect, alarm, message 등)에 맞는 event가 전달되는 경우
        eventSource.addEventListener('connect', (event) => {
            configMessageEvent(event);
        });

        eventSource.addEventListener('alarm', (event) => {
            configMessageEvent(event);
        });

        eventSource.addEventListener('message', (event) => {
            configMessageEvent(event);
        });
    };

    const handleSubmitSend = async (e: FormEvent<HTMLFormElement>, eventName: string, data: string) => {
        e.preventDefault();
        await axios.post(`http://localhost:8080/send/${id}`, {
            eventName,
            data,
        });
    };

    return (
        <main>
            <div>
                <h2>SSE Subscribe</h2>
                <form onSubmit={(e) => handleSubmitSubscribe(e)}>
                    <input type="text" placeholder="id" value={id} onChange={(e) => setId(e.target.value)} />
                    <button>Subscribe</button>
                </form>
            </div>

            <div>
                <h2>SSE Send</h2>
                <form onSubmit={(e) => handleSubmitSend(e, eventName, data)}>
                    <input
                        type="text"
                        placeholder="event name"
                        value={eventName}
                        onChange={(e) => setEventName(e.target.value)}
                    />
                    <input type="text" placeholder="data" value={data} onChange={(e) => setData(e.target.value)} />
                    <button>Send</button>
                </form>
            </div>

            <div>
                <h2>SSE Event Messages</h2>
                <div>
                    {eventMessages.map((eventMessage, index) => (
                        <ul key={index}>
                            <li>event name : {eventMessage.eventName}</li>
                            <li>data : {eventMessage.data}</li>
                        </ul>
                    ))}
                </div>
            </div>
        </main>
    );
}

 

 

 

 

 

SSE (Server-Sent Events) 사용 환경 설정 테스트

 

spring 쪽에서 postman을 이용하여 테스트했던 방식 그대로 react에서도 테스트를 해보겠습니다.

 

먼저 서버를 구동시키면 다음과 같은 화면을 확인할 수 있습니다.

 

초기 화면

 

 

 

그리고 연결할 emitter의 id에 jforj를 입력한 뒤 Subscribe 버튼을 클릭하면 구독과 함께 event message가 적재되는 것을 볼 수 있습니다.

 

구독 결과 화면

 

 

 

 

다음은 발송 테스트를 해보겠습니다.

 

소스 코드에 event name이 alarm인 경우에 대한 listener를 등록도 해놨기 때문에 다음과 같이 event name과 data를 입력하여 Send 버튼을 클릭하면 id에 해당되는 sse emitter를 가지고 있는 client에 전달되는 것을 볼 수 있습니다.

 

alarm 발송 결과 화면

 

 

 

spring때와 동일한 결과를 얻기 위해 이번에는 event name이 message인 경우에 대해 발송 테스트를 해보겠습니다.

 

이 또한 소스 코드에 event name이 message인 경우에 대한 listener를 등록해놨기 때문에 다음과 같은 결과를 확인할 수 있습니다.

 

message 발송 화면 결과

 

 

 

 

마지막으로 소스 코드에 등록해두지 않은 listener로 정보를 입력하여 발송 테스트를 해보겠습니다.

 

id에 해당되는 sse emitter는 존재하기 때문에 API 서버 입장에서는 해당 emitter에 관련 정보를 전달하겠지만 client 입장에서는 지켜보고 있는 event name이 아니기 때문에 이벤트 처리를 수행하지는 않습니다.

 

no-listener 발송 결과 화면

 

 

 

 

 

 

 

 

이상으로 sse (server-sent events) 사용하여 실시간 통신하는 방법에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

 

 

 

728x90
반응형

댓글