Programming/개인 작업🌻

React에서 SSE를 활용해서 실시간 알림을 적용해보면서 (with Websocket 과 FCM 비교)

감귤밭호지차 2024. 1. 17. 00:04

HTTP 특징은 비연결성 = 연결한 적이 있어도 연결을 끊어버린다. 

-> 대안책 : Polling, Long Polling, Websocket, SSE

 

      SSE ( Server - Sent - Event ) 

 

클라이언트의 별도 추가 요청 없이 서버에서 업데이트를 스트리밍할 수 있는 단방향 통신입니다. 

 

 

SSE의 장점과 단점

 

장점

1. HTTP를 통해 통신하므로 다른 프로토콜은 필요가 없고, 구현이 굉장히 쉽다는 것이다.
2. 네트워크 연결이 끊겼을 때 자동으로 재연결을 시도한다.
3. 실시간으로 서버에서 클라이언트로 데이터를 전송할 수 있다. 폴링 같은 경우는 실시간이라고 보기 어려운 점이 있는데, 이러한 한계를 극복한다.

 

 

단점

1. GET 메소드만 지원하고, 파라미터를 보내는데 한계가 있다.
2. 단방향 통신이며, 한 번 보내면 취소가 불가능하다는 단점이 있다.
3. 클라이언트가 페이지를 닫아도 서버에서 감지하기가 어렵다는것도 단점이다.
4. SSE는 지속적인 연결을 유지해야 하므로, 많은 클라이언트가 동시에 연결을 유지할 경우 서버 부담이 커질 수 있다.

 

 

프로젝트에서 SSE를 쓸 때 " Event-Source-Polyfill" 라이브러리를 쓰는 이유

 

SSE 통신을 할 때 헤더에 토큰이나 쿠키를 담고 싶을 때 넣기 위해서 사용함.

저기서 URL은 서버에 구독하는 요청을 날리는 URL 입니다. 서버랑 정하면 됨 
import { EventSourcePolyfill } from "event-source-polyfill";


const eventSource = useRef<EventSourcePolyfill | null | undefined>();

useEffect(() => {
	if(!eventSource.current){
    	eventSource.current = new EventSourcePolyfill(`${URL}`, {
        	withCredentilas: true,
        })
    };
    
    //연결 성공 헨들러 - 접속이 이루어졌을 때 호출 
    eventSource.current.onopen = async (event) => {
        console.log("SSE: 성공적인 연결 완료 ", event);
    };
    
    //기본 메세지 받았을 때 
    eventSource.current.addEventListener("CONNECT", function (event){
        const customEvent = event as MessageEvent;
        //이 customEvent가 들어올 때가 서버로부터 단방향 통신이 오는 일종의 포인트 
        //원하는 별도의 행동을 하면 된다. Ex. 모달을 열던가 데이터를 업데이트 하던가..
    });
    
    eventSource.current.onerror = (error) => {
    	console.log("SSE에러 : ", error);
    };
    
    return () => {
    	if(eventSource.current){
            eventSource.current?.close(); // 연결 종료
            eventSource.current = null; //참조 제거
            console.log("언마운트 이벤트 헨들러 종료");
        };
    };
    
    
}, [])

 

 

 

      비교 군 ( Websocket , FCM )

Websocket

클라이언트와 서버를 연결하고 실시간으로 통신이 가능하도록 하는 기술입니다. HTTP에서 발생하는 것처럼 별도의 요청을 보내지 않고도 데이터를 수신할 수 있습니다. 일종의 양방향 통신.

 

 

 

 

 

Websocket과 HTTP의 차이점

 

Websocket은 Stateful 프로토콜 

- 클라이언트와 서버가 한 번 연결되면 같은 연결을 이용해 통신하여 TCP 커넥션 비용을 아낄 수 있다. 

 

HTTP포트 80, HTTPS 포트 443 위에서 동작

- TCP 연결 처럼 핸드셰이크를 이용해서 연결을 맺는데 HTTP 업그레이드 헤더를 사용해서 HTTP 프로토콜에서 웹소켓 프로토콜로 변경한다. 즉, 최초 접속시에는 HTTP 프로토콜을 이용해 핸드셰이킹을 하는 것이다. 이후에는 한쪽이 연결을 끊지 않는 한 지속적인 통신을 할 수 있고 이때는 웹소켓 프로토콜로 변경이 된다. 데이터를 암호화하기 위해 WSS 프로토콜을 이용할 수도 있다. 

 

 

STOMPJS

 

 

 

Scoket.io

 

 

 

 

 

 

 

 

 


 

 

Polling 이란?? 

Websocket이 나오기 전 양방향 통신과 실시간 네트워킹을 가능하게 했던 방법이다. 일정한 주기로 서버에 요청을 보내는 방식으로 setTimeout, setInterval 등으로 일정 주기마다 서버에 요청을 보내는 방식이다. 

 

문제는, 불필요한 요청과 Connection을 생성해서 서버에 부담을 주는 방식이다. 그리고 요청 주기가 짧을 수록 이 부하는 커진다. 사실 일정 주기마다 요청을 보내는 방식이기 때문에 실시간으로 보기에는 조금 애매하다고 할 수 있다. 

 

Pollilng을 선택하는 이유라면..

  • 응답을 실시간으로 받지 않아도 되는 경우 
  • 다수의 사용자가 동시에 사용하는 경우 

 

 

 

 

 

Long Polling이란??

 

Polling가 유사하지만 서버가 응답을 바로 전달하지 않는 방식이다. 요청을 보냈을 때, 서버가 응답을 바로 보내지 않고 특정 이벤트나 타임아웃이 발생했을 때 응답을 전달하는 방식이다. 응답을 받은 클라이언트는 다시 서버에 데이터를 요청한다. 

 

불필요한 요청을 보내지 않아도 되서 Polling보다는 나아보이지만 결국 Long Polling도 동시 다발적인 요청과 응답이 생기면 부하가 발생할 확률이 높다. 

 

Long Polling을 선택하는 이유라면...

  • 응답을 실시간으로 받아야하는 경우
  • 적은 수의 사용자가 동시에 사용하는 경우

 

 

 

 


FCM [ Firebase  Cloud Messaging ]

플랫폼에 종속되지 않고 푸쉬 메세지를 전송할 수 있는 교차 플랫폼 메시징 솔루션입니다. 

IOS / Android / Web 각 플랫폼에 푸쉬 메세지를 보내려면 각 플랫폼  환경 별 개발해야하는 불편함이 있는데 이를 FCM 하나로 통합해서 사용할 수 있는 솔루션입니다. 

  • IOS : APNS( Apple Push Notification Service )
  • Android : GCM ( Google Cloud Messaging )

 

 

일반 적으로 실시간으로 서버에게 푸쉬 메시지를 받으려면 유저는 항상 서버에 접속해 있어야 하는데 이는 사용자의 기기나 배터리와 네트워크 리소스를 크게 낭비합니다. 그러나 FCM은 " 클라우드 메시징 서버 " 를 " 메시지를 보내는 서버 " 와 " 유저의 애플리케이션 "  중간에 위치함으로써 사용자는 보다 적은 배터리와 네트워크의 사용량으로 메세지를 실시간으로 송수신 처리를 할 수 있게 된 것이다. 

 

 

https://donghun.dev/Firebase-Cloud-Messaging