1. WebSocket
2. Polling
3. SSE (Server-Sent Events)
실시간 알림은 서버에서 데이터가 업데이트될 때 클라이언트로 푸시하는 단방향 통신이므로 SSE가 적합하다.
문제: 연결 후 No activity within 45000 milliseconds 오류 발생
Error: No activity within 45000 milliseconds. 41 chars received.
Reconnecting.
SSE 연결 코드
import React, { useEffect, useRef, useState } from "react";
import { Link } from "react-router-dom";
import { FaRegBell } from "react-icons/fa";
import { EventSourcePolyfill } from "event-source-polyfill";
const Alarm = () => {
const [realtimeData, setRealtimeData] = useState(false);
const eventSource = useRef<EventSource | null>(null);
useEffect(() => {
const fetchSSE = () => {
eventSource.current = new EventSourcePolyfill(
`${import.meta.env.VITE_SERVER}/notification/subscribe`,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("ACCESS_TOKEN")}`,
},
heartbeatTimeout: 60000,// 백엔드의 타임아웃보다 충분히 큰 값(예: 60초)으로 설정
withCredentials: true,
}
);
eventSource.current.addEventListener("sse", (e: MessageEvent) => {
const parsedData = JSON.parse(e.data);
setRealtimeData(parsedData);
});
eventSource.current.onerror = () => {
console.error("SSE 연결 오류 발생");
eventSource.current?.close();
setTimeout(fetchSSE, 3000); // 3초 후 재연결 시도
};
eventSource.current.onopen = () => {
console.log("SSE 연결 성공");
};
};
fetchSSE();
return () => {
eventSource.current?.close();
};
}, []);
return (
<Link
to="/alarm"
className="w-14 h-full flex justify-center items-center absolute right-0 top-0"
>
<div className="relative">
<FaRegBell className="text-xl text-bk" />
{realtimeData && (
<span className="absolute -top-1 -right-2 w-2 h-2 bg-red-500 rounded" />
)}
</div>
</Link>
);
};
export default Alarm;