FLYAI4 / ArtFront-ReactNative

프로젝트 Frontend repo 입니다.
1 stars 1 forks source link

[Frontend] SSE 통신 research 및 테스트 API 연결 #4

Closed heehminh closed 9 months ago

heehminh commented 10 months ago

📌 Description

Back에서 만들어준 테스트용 API로 SSE를 테스트합니다.


🎈 Goal

$\tiny{구체적인\ 산출물을\ 포함한\ 목표를\ 작성해주세요.}$


✏️ Todo

$\tiny{목표\ 달성을\ 위해\ 해야할\ 일을\ 세부적으로\ 작성해주세요.}$

heehminh commented 10 months ago

SSE

SSE(Server Sent Event)란 서버에서 클라이언트로 데이터를 보내는 단방향 통신을 의미한다. 실시간 알림처럼 서버가 클라이언트에게 데이터를 단방향으로 전달해야 할 때 사용한다. (양방향 통신이 불필요할 때)

image

SSE는 첫 연결 시데이터를 주고받은 뒤 연결 상태를 유지하고 서버가 클라이언트에 일방적으로 데이터를 전송한다. websocket과 달리 별도의 프로토콜 없이 HTTP 프로토콜 만으로 사용 가능하고 훨씬 가볍다. 연결이 끊어지면 EventSource가 오류 이벤트를 발생시키고 자동으로 다시 연결을 시도한다. (error recovery)

SSE vs. HTTP 통신

heehminh commented 10 months ago

EventSource

EventSource 인터페이스는 SSE에 대한 웹 콘텐츠 인터페이스이다. EventSource 인터페이스는 text/event-stream 포맷으로 이벤트를 보내는 HTTP 서버에 지속적인 연결을 한다. 연결은 EventSource.close() 호출로 종료되기 전까지 지속된다.

연결이 시작되었을 때, 서버로부터 들어오는 메시지들은 이벤트의 형태로 코드에 전달된다. 들어온 메시지에 이벤트 필드가 있다면, 트리거된 이벤트는 이벤트 필드의 값과 같게 된다. 만약 이벤트 필드가 비어있다면, 그 땐 제네릭 message 이벤트가 발샌된다.

Constructor

EventSource(): creates a new EventSource to handle receiving SSE from a specified URL.

eventSource = new EventSource(url, configuration);

Event handler

실시간 알람으로 SSE를 구현한 프로젝트

 const EventSource = EventSourcePolyfill || NativeEventSource;

  useEffect(() => {
    if (loading && isLogin) {
      let eventSource;
      const fetchSse = async () => {
        try {
          eventSource = new EventSource(
            `${process.env.REACT_APP_BASE_URL}/api/subscribe`,
            {
              headers: {
                Authorization: getCookie("accessToken"),
              },
              withCredentials: true,
            }
          );

          /* EVENTSOURCE ONMESSAGE ---------------------------------------------------- */
          eventSource.onmessage = async (event) => {
            const res = await event.data;
            if (!res.includes("EventStream Created.")) setNewAlarms(true); // 헤더 마이페이지 아이콘 상태 변경
            queryClient.invalidateQueries("myprofile"); // 프로필 업데이트
            queryClient.invalidateQueries("alertNoti"); // 알람 리스트 개수 변경
            queryClient.invalidateQueries("alertLists"); // 알림 목록 업데이트
          };

          /* EVENTSOURCE ONERROR ------------------------------------------------------ */
          eventSource.onerror = async (event) => {
            if (!event.error.message.includes("No activity"))
              eventSource.close();
          };
        } catch (error) {}
      };
      fetchSse();
      return () => eventSource.close();
    }
  });