SSE 실시간 알림 기능 구현
중고 의류 거래 플랫폼 프로젝트를 진행하면서 채팅 기능, 찜하기 기능, 상점 팔로우 기능이 있었고, 누군가가 나에게 채팅을 보내거나 내 상품을 찜하거나, 나의 상점을 팔로우했을 때 알림이 오는 기능을 구현해야 했다.
채팅을 웹소켓으로 구현을 했지만, 양방향 통신을 지원하는 웹소켓에 비해 단방향 통신을 지원하는 SSE를 사용하는 것이 서버 리소스와 네트워크 트래픽을 절약할 수 있다고 판단해 SSE를 활용해 알림 기능을 구현하기로 하였다.
SSE(Server Sent Event)
- 단방향 데이터 흐름(서버 -> 클라이언트)
- 단순성: 표준 HTTP를 통해 작동하기 때문에 WebSocket에 비해 간단함(캐싱, 프록시, 방화벽과 같은 기존 웹 인프라와 쉽게 통합)
- 자동 재연결 메커니즘 내장
WebSocket
- 양방향 통신
- 실시간 상호 작용: 최소한의 대기 시간으로 양방향 동시 데이터 흐름을 처리할 수 있음
- 유연성: 바이너리 데이터를 포함하여 더 복잡하고 다양한 메시지 유형과 형식을 허용
프로젝트에서 구현
React에서는 EventSource 라이브러리를 제공하기 때문에 쉽게 구현할 수 있었다. 구현은 EventSource를 통해 서버에서 보내는 알림을 감지하고 Toast 라이브러리를 활용해 알림을 디자인하는 방식으로 하였다.
코드
useEffect(() => {
if (token) {
const eventSource = new EventSourcePolyfill('https://api.re-use.store/api/subscribe', {
headers: {
Authorization: token,
},
withCredentials: true,
});
eventSource.addEventListener('WISH', event => {
const messageEvent = event as MessageEvent;
toast.success(messageEvent.data, {
icon: <img style={{ width: '20px', height: '20px' }} src="https://ifh.cc/g/00y5Y2.png" alt="pic" />,
position: 'top-right',
draggable: true,
autoClose: 5000,
});
});
return () => {
eventSource.close();
};
}
}, []);
일단 로그인 한 유저만 알림이 오고, 감지를 하기 위해서는 token 값이 있어야 하기 때문에 token 값이 있을 경우에만 실행되도록 로직을 구성하였다. 이후 addEventListener를 통해 알림을 감지하였고, 이벤트가 감지되었을 경우 toast를 통해 알림을 웹 페이지 상에 보여주는 방법을 사용하였다.
코드를 보면 eventSource가 아닌 EventSourcePolyfill 라이브러리를 사용한 것을 볼 수 있는데, 이를 사용한 이유는 eventSource는 type에 headers가 존재하지 않았기 때문이다. 우리 서비스에서는 알림을 감지하기 위해 서버에 token 값을 헤더에 보내줘야 했기 때문에 eventSource를 사용할 수 없었고, 이에 따라 EventSourcePolyfill 라이브러리를 사용하였다.
reference