기본적으로 **SSE(EventSource)**를 사용하여 실시간 알림을 구현했지만,
사용자가 접속하지 않은 상태에서 발생한 알림을 받을 수 없는 문제가 발생함.
백엔드에 API 추가하여, 접속하지 않은 동안 발생한 알림을 조회할 수 있도록 구현
isRead 필드를 추가하여 읽지 않은 알림을 구분.📌 1. useFetchMissedNotifications 구현 (백엔드 API 연동)
📌 2. SideMenu.tsx에서 API 데이터 가져와서 상태 업데이트
const { data: missedNotifications } = useFetchMissedNotifications();
useEffect(() => {
if (missedNotifications?.notifications) {
const formattedNotifications: NotificationProp[] =
missedNotifications.notifications.map((notification) => ({
notificationId: notification.notificationId,
type: notification.type,
message: notification.message,
senderNickname: notification.sender.nickname,
senderProfileUl: notification.sender.profileUrl,
timestamp: notification.createdAt,
isRead: notification.isRead,
}));
setMessages(formattedNotifications);
}
}, [missedNotifications]
📌 3. SSE를 통한 실시간 알림 수신 (기존 코드 유지)
useEffect(() => {
if (!token || messages.length === 0) return;
const eventSource = new EventSourcePolyfill(
`${import.meta.env.VITE_BASE_SERVER_URL}/notifications/stream`,
{
headers: { Authorization: `Bearer ${token}` },
withCredentials: true,
}
);
eventSource.addEventListener('message', (event) => {
const data: NotificationProp = JSON.parse(event.data);
setMessages((prevMessages) => [...prevMessages, data]);
setNewNotification(true);
});
eventSource.addEventListener('error', () => {
eventSource.close();
});
return () => {
eventSource.close();
};
}, [token]);
📌 4**. 백엔드: 읽지 않은 알림 조회 서비스 로직**
async getUnreadNotifications(userId: number) {
// 1. 읽지 않은 알림 조회
const unreadNotifications = await this.prisma.notification.findMany({
where: {
userId: userId,
isRead: false,
},
include: {
sender: {
select: {
nickname: true,
profile_url: true,
},
},
},
orderBy: {
createdAt: 'desc',
},
});
// 2. 데이터를 변환하여 반환
const transformedNotifications = unreadNotifications.map(notification => {
const transformedNotification = {
notificationId: notification.id, //
userId: notification.userId,
senderId: notification.senderId,
type: notification.type,
message: notification.message,
isRead: notification.isRead,
createdAt: notification.createdAt,
sender: {
nickname: notification.sender.nickname,
profileUrl: notification.sender.profile_url, // `profile_url` -> `profileUrl`
},
};
return transformedNotification;
});
return {
notifications: transformedNotifications,
};
}