feat: 알림 SSE 실시간 반영과 견적 요청 UX 개선 - #101
Conversation
미읽음 뱃지를 SSE로 갱신하고, 견적 요청 성공 시 보낸 견적 목록으로 이동하며 긴 주소는 박스 안에서 말줄임 처리한다. pre-commit용 eslint-plugin-storybook도 추가한다. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 18 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (10)
📝 WalkthroughWalkthrough알림 SSE 구독과 재연결, 이벤트별 캐시 갱신을 추가했습니다. 알림 유형과 메시지 템플릿을 정리했습니다. 견적 요청 성공 후 이동 경로와 지역 표시 레이아웃을 변경했습니다. 개발 의존성 버전도 업데이트했습니다. Changes실시간 알림
견적 요청 화면
개발 의존성
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant 사용자
participant NotificationTrigger
participant useNotificationSse
participant NotificationSseApi
participant 알림서버
사용자->>NotificationTrigger: 헤더 렌더링
NotificationTrigger->>useNotificationSse: SSE 연결 시작
useNotificationSse->>NotificationSseApi: accessToken과 함께 구독
NotificationSseApi->>알림서버: GET /notifications/sse/subscribe
알림서버-->>NotificationSseApi: notification 이벤트 전송
NotificationSseApi-->>useNotificationSse: 이벤트명과 data 전달
useNotificationSse-->>NotificationTrigger: 미읽음 수 및 목록 캐시 갱신
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
⚔️ Resolve merge conflicts 💡
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/hooks/notifications/useNotificationSse.ts`:
- Around line 99-100: In the normal-completion path after
subscribeNotificationSse returns, await sleep(INITIAL_RETRY_DELAY_MS,
abortController.signal) before starting the next connection, while retaining the
retryDelayMs reset.
In `@src/lib/api/notificationSse.ts`:
- Around line 36-38: Update the SSE error handling around response validation to
throw a structured error that preserves response.status as a dedicated status
property, then update the useNotificationSse error branch to detect
authentication failures via error.status === 401 instead of parsing
error.message. Preserve existing behavior for other HTTP statuses.
🪄 Autofix
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 Plus
Run ID: d374266b-3a02-4dac-b4f9-4e710d6475a4
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json,!**/package-lock.json
📒 Files selected for processing (8)
package.jsonsrc/components/common/Header/notification/NotificationTrigger.tsxsrc/components/common/Header/notification/notificationMessages.tssrc/components/estimate/request/EstimateRequestForm.tsxsrc/hooks/notifications/useNotificationSse.tssrc/lib/api/notificationSse.tssrc/lib/constants/apiRoutes.tssrc/types/notification.ts
yooseohyeon
left a comment
There was a problem hiding this comment.
작업하느라 수고하셨습니다! 알림 실시간 반영과 견적 요청에서 주소가 긴 경우 ui 등 문제가 잘 해결된 것 같습니다!
다만 견적 요청 성공 시 잠시 안내 화면이 보였다가 (empty state(트럭 이미지+안내문구), cta 버튼) 보낸 견적 요청 페이지로 이동하는데, 바로 이동하는 것이 목적이라면 견적 요청 성공 후에는 안내 화면 자체가 보이지 않도록 수정이 필요해보입니다!
또한 이건 제 실수일수도 있지만 dev 브랜치의 많은 수정 사항들이 누락된 것으로 보여서 한 번 확인 부탁드립니다!
Keep notification SSE subscription and pathname-close behavior together. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
juengseulki
left a comment
There was a problem hiding this comment.
📋 PR 리뷰
전체 변경사항 확인했습니다!
이번 PR은 알림 미읽음 뱃지를 SSE로 실시간 반영하는 흐름, 알림 메시지 타입/템플릿 정리, 견적 요청 완료 후 이동 및 긴 주소 말줄임 UX 개선을 중심으로 확인했습니다.
👍 좋았던 점
- 로그인 상태에서만
useNotificationSse()를 구독하도록 하고, 인증 scope가 준비된 뒤 연결을 시작하도록 한 점이 좋았습니다. - 브라우저 기본
EventSource대신 Authorization 헤더를 넣을 수 있는 fetch 기반 SSE 클라이언트를 별도로 구현한 방향이 현재 인증 구조와 잘 맞습니다. - 장시간 유지되는 SSE 연결에 기존
fetchInstance를 재사용하지 않고 별도 fetch를 사용해 타임아웃 영향을 받지 않도록 한 점이 좋았습니다. - SSE 이벤트 수신 시 unread count 캐시를 즉시 증가시키면서도 이후 invalidate를 수행해 서버 상태와 다시 동기화하도록 한 점이 안정적입니다.
- 알림 목록 캐시도 함께 invalidate해 벨 뱃지만 바뀌고 목록은 이전 상태로 남는 문제를 방지했습니다.
- SSE 연결 종료/오류 시 1초부터 최대 30초까지 backoff를 적용해 재연결 요청이 과도하게 몰리지 않도록 한 점이 좋았습니다.
- 컴포넌트 unmount 또는 인증 scope 변경 시
AbortController로 기존 스트림과 retry 대기를 함께 종료하도록 처리한 점도 잘 구성되어 있습니다. - 401 발생 시 access token refresh를 시도하고 이후 재연결하도록 기존 인증 흐름을 재사용한 점이 좋았습니다.
- SSE parser에서
event:,data:, 빈 줄 기반 flush, heartbeat comment(:)를 구분해 처리하고 있어 기본적인 SSE 메시지 형식에 맞게 구현되어 있습니다. - 견적 요청 성공 후
/estimates/requests로 바로 이동하도록 변경하면서, ACTIVE 캐시가 먼저 갱신되어 기존 활성 견적 안내 화면이 잠깐 노출되는 문제까지 별도 성공 상태 UI로 막은 점이 세심합니다. - 긴 주소에
min-w-0,overflow-hidden,truncate를 함께 적용하고title={value}도 추가해 박스 레이아웃을 유지하면서 전체 주소 확인 방법도 남겨둔 점이 좋았습니다.
🔍 확인 및 제안
1. SSE unread count 증가 후 즉시 invalidate
notification 이벤트에서 unread count를 먼저 +1 한 뒤 바로 동일 Query를 invalidate하고 있습니다.
즉시 UI 반영과 서버 기준 보정을 모두 챙기려는 의도는 이해되고 현재 구조에서도 문제는 없어 보입니다.
다만 이벤트가 매우 자주 들어오는 경우에는 매 이벤트마다 unread count/list refetch가 발생할 수 있으므로,
향후 알림 빈도가 높아진다면 debounce 또는 이벤트 payload를 이용한 직접 캐시 갱신 범위를 넓히는 방향도 검토할 수 있을 것 같습니다.
현재 규모에서는 blocker는 아닙니다.
2. 401 이후 refresh 성공 시 재연결 흐름
401 발생 시 ensureAccessTokenRefreshed()를 실행하고 다음 loop에서 새 access token을 다시 읽는 구조라 흐름은 정상적으로 보입니다.
refresh 실패 시 연결 루프를 종료하도록 한 것도 로그인 만료 상황에서 불필요한 재연결을 막는 방향으로 적절합니다.
3. 알림 타입 제거 범위
NotificationType에서 일부 기존 타입을 제거하고 notificationMessages.ts와 맞춘 부분은 확인했습니다.
이 타입이 프론트 전체에서 "현재 실제로 수신 가능한 백엔드 NotificationType" 자체를 표현하는 타입이라면,
아직 post 로직이 없다는 이유로 enum 값을 제거하는 것은 이후 서버에서 해당 타입이 내려왔을 때 파싱/처리 범위를 좁힐 수 있습니다.
반대로 이 타입이 정말 "현재 알림 패널에서 템플릿을 제공하는 타입"만 표현하는 용도라면 지금 정리 방향도 가능합니다.
현재 주석도 알림 패널 문구 템플릿이 정의된 타입이라고 명시되어 있어 의도는 이해되지만,
백엔드 NotificationType과 동일 이름을 쓰고 있어 역할이 헷갈릴 수 있으므로 타입 이름을 조금 더 명확히 분리하는 것도 고려할 수 있을 것 같습니다.
4. PR 범위 외 Landing 파일 변경 확인
이번 PR 설명에는 SSE/알림/견적 요청 UX가 주요 범위인데 변경 파일 목록에는 여러 Landing 컴포넌트도 포함되어 있습니다.
기능상 문제가 있다는 의미는 아니지만,
PR에 의도적으로 포함된 변경인지 한 번 확인하면 좋을 것 같습니다.
수고하셨습니다! 👍
| return; | ||
| } | ||
|
|
||
| retryDelayMs = Math.min(retryDelayMs * 2, MAX_RETRY_DELAY_MS); |
There was a problem hiding this comment.
로직을 보면 정상 종료됐을 때는 L105에서 retryDelayMs를 1초로 리셋하는데, 이 catch 경로에서는 계속 2배씩만 늘어나고 다시 리셋되는 곳이 없는 것 같아요. 이러면 재연결 실패가 몇 번 쌓여서 delay가 30초까지 커진 다음, 오랜만에 연결이 한 번 끊긴 경우에도 계속 30초 지연이 유지되는 문제가 있을 수 있어요. 연결이 다시 정상적으로 붙었을 때 delay를 초기화하는 지점이 따로 있는지 확인해보시면 좋을 것 같습니다.
|
알림 실시간 반영부터 견적 요청 UX까지 범위가 넓은데도 꼼꼼하게 마무리해주신 것 같습니다. |
📋 작업 내용
🔥 변경 사항
package.json/package-lock.json: pre-commit용eslint-plugin-storybook의존성을 추가했습니다.NotificationTrigger.tsx: 알림 벨에서 SSE 구독 훅을 호출해 미읽음 뱃지가 실시간으로 갱신되게 했습니다.notificationMessages.ts: 아직 post 로직이 없는 알림 타입 문구를 정리하고, 실제 쓰는 타입 위주로 템플릿을 맞췄습니다.EstimateRequestForm.tsx: 견적 요청 성공 시/estimates/requests로 이동하도록 했고, 긴 출발지·도착지 주소는 박스 크기를 유지한 채 앞부분만 보이도록 말줄임 처리했습니다.useNotificationSse.ts: 로그인 상태에서 알림 SSE를 구독하고, 이벤트에 따라 unread/list 캐시를 갱신·재연결하는 훅을 추가했습니다.notificationSse.ts: Authorization을 넣을 수 있는 fetch 기반 SSE 클라이언트(파싱·스트림 읽기)를 추가했습니다.apiRoutes.ts: SSE 구독 경로SSE_SUBSCRIBE를 추가했습니다.notification.ts: 알림 타입을notificationMessages.ts에 있는 타입과 동기화했습니다.✅ 체크리스트
📷 스크린샷 (선택)
🔗 관련 이슈
Closes #
💬 To Reviewer
Summary by CodeRabbit
새 기능
개선