ID: key_26_22_05_25_P3_3_5 Created date: 5월 25 2026 월요일

연관 문서


개요

실시간 인앱 알림 시스템을 구현한다. SSE(Server-Sent Events) 또는 WebSocket을 사용한다.

  • 예상 소요: 4~5일
  • 선행 조건: 실시간 통신 방식 결정 (SSE 권장 — 단방향 알림에 적합)
  • 완료 기준: 이슈 할당 시 담당자 브라우저에 실시간 알림 수신 확인

Claude Code 작업 수행서

작업 지시

CIRA 서버 + UI에 실시간 알림 시스템을 구현해줘.
방식: SSE (Server-Sent Events)

[서버 수행 작업]

1. 알림 도메인 패키지
   com.tas.cira.notification/
   ├── controller/NotificationController.java
   ├── service/NotificationService.java
   ├── service/SseEmitterService.java
   ├── repository/NotificationRepository.java
   ├── entity/Notification.java
   └── dto/NotificationResponse.java

2. SSE 연결 관리
   SseEmitterService:
   - emitters: ConcurrentHashMap<UUID(userId), SseEmitter>
   - connect(userId): SseEmitter
     * SseEmitter TTL: 600초
     * onCompletion/onTimeout: emitter 맵에서 제거
   - send(userId, NotificationResponse): void
     * emitter 존재 시 sendEvent
     * IOException 발생 시 emitter 제거
   - broadcast(List<UUID> userIds, event): void

3. SSE 엔드포인트
   GET /api/v1/notifications/subscribe
   - 헤더: Accept: text/event-stream
   - 연결 성공 시 "CONNECTED" 이벤트 발송
   - Spring SseEmitter 반환

4. 알림 API
   GET    /api/v1/notifications           — 알림 목록 (최근 50건)
   PUT    /api/v1/notifications/{id}/read — 단건 읽음 처리
   PUT    /api/v1/notifications/read-all  — 전체 읽음
   GET    /api/v1/notifications/unread-count — 미읽음 수

5. 알림 발송 시점
   NotificationService.send()를 다음 이벤트에서 호출:
   - 이슈 할당: "'{이슈키}' 이슈가 회원님께 할당되었습니다"
   - 이슈 상태 변경: "'{이슈키}' 상태가 {상태}로 변경되었습니다"
   - 댓글 작성 (이슈 담당자/보고자): "'{이슈키}'에 새 댓글이 달렸습니다"
   - 멘션(@): "'{작성자}'님이 댓글에서 회원님을 멘션했습니다"
   - 스프린트 시작/종료: 스프린트 멤버 전체

6. 알림 설정 API
   GET /api/v1/notification-preferences
   PUT /api/v1/notification-preferences
   Request: [
     { "type": "ISSUE_ASSIGNED", "inApp": true, "email": false },
     { "type": "COMMENT_ADDED", "inApp": true, "email": true },
     ...
   ]

[UI 수행 작업]

7. SSE 훅
   파일: src/hooks/useNotifications.ts
   - useEffect에서 EventSource 연결
   - 이벤트 수신 시 React Query 캐시 업데이트 + toast 표시
   - 컴포넌트 unmount 시 EventSource.close()

8. 알림 벨 UI
   파일: src/components/layout/NotificationBell.tsx
   - 헤더 우측 벨 아이콘
   - 미읽음 배지 (최대 99+)
   - 클릭 → 알림 드롭다운 패널
   - 알림 항목 클릭 → 해당 이슈 이동 + 읽음 처리

9. 알림 드롭다운
   - 최근 10건 표시
   - "전체 보기" → /notifications 페이지
   - "모두 읽음" 버튼
   - 알림 타입별 아이콘 (이슈 할당, 댓글, 멘션 등)
   - 상대 시간 표시

[준수 사항]
- SSE 연결은 로그인 후 자동 시작
- 브라우저 탭 전환 시 Visibility API로 재연결 처리
- 연결 끊김 감지 시 3초 후 재연결 시도 (최대 5회)

완료 기준

항목기준
SSE 연결브라우저 로그인 후 자동 연결
실시간 알림이슈 할당 시 1초 이내 수신
미읽음 배지카운트 정확
읽음 처리단건/전체 정상 동작
재연결연결 끊김 후 자동 재시도