react spring boot 알림 기능

위범석·2022년 9월 1일
2

숨고를 벤치마킹하여 전문가와 유저의 매칭 시스템을 완성 후 ,
현재는 매칭이 되었을 때, axios나 fetch로 spring boot에서 데이터를 받아와서 렌더링을 시켰었는데(CSR(Client Side Rendering),

매칭이 되었을때 카카오톡처럼 매칭이 되었다는걸 프론트에서 따로 데이터를 서버에 요청하지 않고, 단순 백엔드 쪽에서 매칭이 되었거나, 채팅 기록이 남아 있다면, 알람을 보여주는 식으로 나타내보기 위하여

우리는 sse를 선택하게 되었다.. 웹소켓을 이용한 stomp를 사용할려고 했으나, 채팅 쪽에서 웹소켓을 통해 양방향 통신은 한번 다뤄 보아서, 단방향 통신인 sse를 사용해보게 되었다. 시간이 얼마나 걸릴지는 모르겠지만 빨리 알람 기능이 끝났으면 좋겠다 sse개념 부터 보자면,

Server-Sent Events란?
HTML5가 등장하기 전까지는 HTML에 서버 푸시를 위한 표준화된 기술이 없었기 때문에 웹에서 실시간 정보를 받아와야 할 때 외부 플러그인을 이용하거나 서버 푸시를 흉내 낸 Ajax 폴링(polling) 기법 등을 사용했습니다. 하지만 플러그인 종속적인 웹은 해당 플러그인을 설치해야 한다는 불편함이 있으며 폴링처럼 주기적인 요청을 통한 구현은 쓸모없는 요청의 발생으로 인한 대역폭의 낭비가 불가피하였습니다. HTML5의 Server-Sent Events(이하 SSE)는 이러한 문제 없이 서버가 필요할 때마다 클라이언트에게 데이터를 줄 수 있게 해주는 서버 푸시 기술입니다.

SSE의 장점
SSE의 장점으로는 다음과 같은 것들이 있습니다.

전통적인 HTTP를 통해 통신하므로 다른 프로토콜이 필요가 없습니다.
재접속 처리 같은 대부분의 저수준 처리가 자동으로 됩니다.
표준 기술답게 IE를 제외한 브라우저 대부분을 지원합니다.
HTML과 JavaScript만으로 구현할 수 있으므로 현재 지원되지 않는 브라우저(IE 포함)도 polyfill을 이용해 크로스 브라우징이 가능합니다. (여기서 polyfill이란 브라우저가 지원하지 않는 API를 플러그인이나 JavaScript 등으로 흉내 내 구현한 것을 뜻합니다. polyfill에 대한 자세한 설명은 이 블로그 포스트를 참조하시기 바랍니다.)
사실 종합해보면 SSE의 모든 장점은 간편함으로 요약할 수 있습니다.

EventSource 객체의 속성은 다음과 같습니다.

onmessage
기본 메시지가 왔을 때 호출
onopen
접속이 맺어졌을 때 호출
onerror
오류 발생 시 호출
EventSource의 addEventListener()를 사용하면 위 3개의 이벤트뿐만 아니라 따로 지정된 이벤트의 데이터도 받아 처리할 수 있습니다.

import React, { useState,useEffect } from 'react';
import { useSelector } from "react-redux";

function Event() {
  const user_info = useSelector((state) => state.user.user);
  const [listening, setListening] = useState(false);
  const [data, setData] = useState([]);
  let eventSource = undefined;
  if (user_info){
    console.log(user_info.email)
  }

  useEffect(() => {
    if (!listening) {
      console.log('a')
      // { withCredentials: true }
      eventSource = new EventSource(`/test/subscribe`);
      
      // eventSource.onmessage = (event) => {
      //   console.log("result", event.data);
      //   setData(old => [...old, event.data])
      // }

      eventSource.addEventListener("sse", (event) => {
        const result = JSON.parse(event.data);
        console.log("received:", result);
        setData(result)
      });

      eventSource.onerror = (event) => {
        console.log(event.target.readyState)
        if (event.target.readyState === EventSource.CLOSED) {
          console.log('SSE closed (' + event.target.readyState + ')')
        }
        eventSource.close();
      }

      eventSource.onopen = (event) => {
        console.log("connection opened")
      }
      setListening(true);
    }
    return () => {
      eventSource.close();
      console.log("event closed")
    }

  }, [])

  return (
      <>
      <div className="App">
        <header className="App-header">
          Received Data
          {data}
          {/*{data.map(d =>*/}
          {/*    <span key={d}>{d}</span>*/}
          {/*)}*/}
        </header>
      </div>
      </>
  );
}

export default Event;

나는 프론트 엔드 담당이여서 지금 이 코드는 구독을 한 후에 단순하게 백에서 준 data를 나타내는 코드이다. console에서 값은 받아오는데 받는순간 구독이 끊겨 버려서 지금 백에서 오류에 대해 해결 중이다........ 프론트쪽에 자료가 많이 없어서 어디 쪽의 문제인지 정확하게 이해가 가지 않는 상황이다.....

profile
코린이

0개의 댓글