Skip to content

feat: subscribe to notification SSE#16

Merged
seoJing merged 1 commit into
mainfrom
feat/notification-sse
Jun 3, 2026
Merged

feat: subscribe to notification SSE#16
seoJing merged 1 commit into
mainfrom
feat/notification-sse

Conversation

@seoJing

@seoJing seoJing commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Add useNotificationSSE hook for /notifications/subscribe EventSource subscription
  • Invalidate notification React Query cache when notification SSE events arrive
  • Mount a global NotificationSSEProvider under QueryProvider for authenticated/known users

Test Plan

  • pnpm lint
  • pnpm build
  • Notjing final gate: pass

Notes

  • Lint passes with 6 existing unrelated warnings.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능
    • 실시간 알림 시스템이 추가되었습니다. 서버에서 전송되는 알림을 실시간으로 수신하고 자동으로 갱신되는 기능이 새로 도입되었습니다. 인증된 사용자만 알림 구독이 활성화됩니다.

@vercel

vercel Bot commented Jun 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
frontend Ready Ready Preview, Comment Jun 3, 2026 6:28am

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@seoJing, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 51 minutes and 50 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 202c7636-0bfa-43e1-a4fd-6a4f8debcbbc

📥 Commits

Reviewing files that changed from the base of the PR and between 99374af and 010b7cb.

📒 Files selected for processing (4)
  • src/app/layout.tsx
  • src/app/providers/notification-sse-provider.tsx
  • src/features/notification/index.ts
  • src/features/notification/model/use-notification-sse.ts
📝 Walkthrough

개요

SSE(Server-Sent Events) 기반 실시간 알림 구독 기능을 추가합니다. 클라이언트 훅이 EventSource를 통해 알림 스트림에 연결되고, notification 이벤트를 수신하면 React Query 캐시를 무효화하여 즉시 갱신됩니다. 제공자 컴포넌트가 인증 상태에 따라 구독을 조건부로 활성화하며, 루트 레이아웃에 통합됩니다.

변경사항

SSE 알림 구독

레이어 / 파일(들) 요약
SSE 훅 구현 및 내보내기
src/features/notification/model/use-notification-sse.ts, src/features/notification/index.ts
useNotificationSSE 훅을 구현하여 enabled 및 EventSource 가용성에 따라 연결을 생성/정리하고, notification 이벤트 수신 시 notificationKeys.all 쿼리를 무효화합니다.
인증 기반 SSE 제공자 컴포넌트
src/app/providers/notification-sse-provider.tsx
NotificationSSEProvider를 생성하여 useAuthStore에서 인증 상태와 userId를 구독하고, 이를 기반으로 훅의 enabled 옵션을 설정합니다.
루트 레이아웃 통합
src/app/layout.tsx
NotificationSSEProvider를 import하고 QueryProvider 내부에 감싸서 인증된 사용자가 자동으로 SSE 구독에 참여하도록 합니다.

시퀀스 다이어그램

sequenceDiagram
  participant RootLayout as 루트 레이아웃
  participant NotificationSSEProvider
  participant useNotificationSSE as useNotificationSSE 훅
  participant EventSource
  participant ReactQuery as React Query
  
  RootLayout->>NotificationSSEProvider: 제공자 마운트
  NotificationSSEProvider->>NotificationSSEProvider: useAuthStore에서 인증 상태 구독
  alt 인증됨 또는 userId 존재
    NotificationSSEProvider->>useNotificationSSE: enabled = true로 호출
    useNotificationSSE->>EventSource: /api/notifications/stream 연결
    EventSource-->>useNotificationSSE: 연결 확립
  else 미인증
    NotificationSSEProvider->>useNotificationSSE: enabled = false로 호출
    useNotificationSSE->>useNotificationSSE: 즉시 정리하고 반환
  end
  
  loop 연결 활성 상태
    EventSource-->>useNotificationSSE: notification 이벤트
    useNotificationSSE->>ReactQuery: notificationKeys.all 무효화
    ReactQuery-->>useNotificationSSE: 캐시 갱신
  end
Loading

예상 코드 리뷰 노력

🎯 2 (단순) | ⏱️ ~12분

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 변경사항의 주요 내용인 SSE 기반 알림 구독 기능 추가를 명확하고 간결하게 요약하고 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/notification-sse

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/features/notification/model/use-notification-sse.ts (1)

33-33: ⚡ Quick win

useEffect 의존성 배열에서 queryClient를 제거하는 것을 고려하세요.

queryClient가 의존성 배열에 포함되어 있어 참조가 변경될 경우 EventSource가 불필요하게 재연결됩니다. React Query의 QueryClient는 일반적으로 안정적인 참조를 제공하지만, 명시적으로 보장되지는 않습니다.

♻️ 제안하는 리팩토링
 export function useNotificationSSE({
     enabled = true,
 }: UseNotificationSSEOptions = {}) {
     const queryClient = useQueryClient();
+    const queryClientRef = useRef(queryClient);
+
+    useEffect(() => {
+        queryClientRef.current = queryClient;
+    });

     useEffect(() => {
         if (!enabled || typeof EventSource === 'undefined') return;

         const es = new EventSource(
             backendProxyEndpoint(endpoints.notifications.subscribe),
         );

         es.addEventListener('notification', () => {
-            queryClient.invalidateQueries({ queryKey: notificationKeys.all });
+            queryClientRef.current.invalidateQueries({ queryKey: notificationKeys.all });
         });

         es.addEventListener('ping', () => {
             // keep-alive 이벤트는 연결 유지용이므로 별도 처리하지 않는다.
         });

         return () => es.close();
-    }, [enabled, queryClient]);
+    }, [enabled]);
 }

필요한 import 추가:

-import { useEffect } from 'react';
+import { useEffect, useRef } from 'react';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/notification/model/use-notification-sse.ts` at line 33,
useNotificationSSE의 useEffect 의존성 배열에 있는 queryClient 때문에 참조 변경 시 EventSource가
불필요하게 재연결됩니다. 이 훅에서 실제로 재실행이 필요한 값만 남기고 queryClient를 의존성에서 제거하도록 정리하세요.
useNotificationSSE 내부의 useEffect와 EventSource 생성/정리 로직을 기준으로 수정하면 됩니다.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/notification/model/use-notification-sse.ts`:
- Around line 17-33: The current useEffect hook in use-notification-sse.ts lacks
error handling and reconnection logic for the EventSource instance. To fix this,
add an 'error' event listener to the EventSource object to handle connection
errors gracefully. Implement a reconnection strategy, such as retrying the
connection with exponential backoff, when an error occurs or the connection
closes unexpectedly. Ensure this logic is contained within the useEffect hook
managing the EventSource lifecycle to maintain a stable subscription.

---

Nitpick comments:
In `@src/features/notification/model/use-notification-sse.ts`:
- Line 33: useNotificationSSE의 useEffect 의존성 배열에 있는 queryClient 때문에 참조 변경 시
EventSource가 불필요하게 재연결됩니다. 이 훅에서 실제로 재실행이 필요한 값만 남기고 queryClient를 의존성에서 제거하도록
정리하세요. useNotificationSSE 내부의 useEffect와 EventSource 생성/정리 로직을 기준으로 수정하면 됩니다.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 48c7a237-86d4-46cc-aa56-17fe4861174b

📥 Commits

Reviewing files that changed from the base of the PR and between f31bfa1 and 99374af.

📒 Files selected for processing (4)
  • src/app/layout.tsx
  • src/app/providers/notification-sse-provider.tsx
  • src/features/notification/index.ts
  • src/features/notification/model/use-notification-sse.ts

Comment thread src/features/notification/model/use-notification-sse.ts Outdated
@seoJing seoJing force-pushed the feat/notification-sse branch from 99374af to 010b7cb Compare June 3, 2026 06:28
@seoJing seoJing merged commit c92eb1d into main Jun 3, 2026
5 checks passed
@seoJing seoJing deleted the feat/notification-sse branch June 3, 2026 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant