Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

new_bird-hyun

Next.js에서 SSE(Server-Sent Events)와 Zustand를 활용한 실시간 알림 배지 시스템 구현 본문

코딩 공부

Next.js에서 SSE(Server-Sent Events)와 Zustand를 활용한 실시간 알림 배지 시스템 구현

새혀니 2025. 3. 19. 23:02

 

  • SSE(Server-Sent Events)와 Zustand를 활용하여 실시간 알림 배지 표시
  • 특정 이벤트가 발생할 때 클라이언트가 알림을 받고 UI를 자동 업데이트하는 방법
  • 서버에서 주기적으로 새로운 알림을 전송하고, 클라이언트에서 알림 개수를 표시하는 UI 구현

    npm install zustand

    store/useNotificationStore.js (Zustand 전역 상태)

import { create } from 'zustand';

const useNotificationStore = create((set) => ({
  notifications: [],
  unreadCount: 0,
  addNotification: (notif) =>
    set((state) => ({
      notifications: [...state.notifications, notif],
      unreadCount: state.unreadCount + 1,
    })),
  markAllRead: () => set({ unreadCount: 0 }),
}));

export default useNotificationStore;

pages/api/notifications.js (SSE 알림 API)
export default function handler(req, res) {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  const sendNotification = (message) => {
    res.write(`data: ${JSON.stringify({ message, time: new Date().toLocaleTimeString() })}\n\n`);
  };

  sendNotification('새로운 알림 시스템이 시작되었습니다.');

  const interval = setInterval(() => {
    sendNotification(`새로운 이벤트 발생!`);
  }, 7000);

  req.on('close', () => {
    clearInterval(interval);
  });
}

components/NotificationBadge.js (알림 배지 UI)
'use client';

import { useEffect } from 'react';
import useNotificationStore from '../store/useNotificationStore';

export default function NotificationBadge() {
  const { unreadCount, addNotification, markAllRead } = useNotificationStore();

  useEffect(() => {
    const eventSource = new EventSource('/api/notifications');

    eventSource.onmessage = (event) => {
      addNotification(JSON.parse(event.data));
    };

    return () => eventSource.close();
  }, [addNotification]);

  return (
    <div>
      <h2>실시간 알림 배지</h2>
      <button onClick={markAllRead}>
        알림 보기 {unreadCount > 0 && <span>({unreadCount})</span>}
      </button>
    </div>
  );
}

components/NotificationList.js (실시간 알림 UI)
'use client';

import useNotificationStore from '../store/useNotificationStore';

export default function NotificationList() {
  const notifications = useNotificationStore((state) => state.notifications);

  return (
    <div>
      <h2>알림 목록</h2>
      <ul>
        {notifications.map((notif, index) => (
          <li key={index}>{notif.message} ({notif.time})</li>
        ))}
      </ul>
    </div>
  );
}

app/page.js
import NotificationBadge from '../components/NotificationBadge';
import NotificationList from '../components/NotificationList';

export default function Home() {
  return (
    <div>
      <NotificationBadge />
      <NotificationList />
    </div>
  );
}

SSE와 Zustand를 활용하면 실시간 알림 배지 및 알림 UI를 쉽게 구축 가능