Commit 0d220e0
feat: SSE 기반 실시간 모임 현황 업데이트 구현 (#87)
* feat: SSE 범용 훅 및 타입 정의 추가
- useServerSentEvent 범용 훅 구현
- SSE 이벤트 타입 정의 (ParticipantCountEvent, GatheringFullEvent)
- 이벤트 타입 동적 등록 지원
- readyState, close, reconnect 기능 제공
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* refactor: useGetGatheringCapacity 폴링 제거
- 10초 폴링 제거하여 SSE 기반 실시간 업데이트로 전환
- 초기 데이터 로드만 수행
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* feat: OpinionFormView에 SSE 통합
- gathering-full 이벤트 감지
- 모임 마감 시 자동으로 결과 페이지로 이동
- useServerSentEvent 훅 사용
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* feat: PendingViewContainer에 SSE 통합
- participant-count 이벤트로 실시간 참여자 수 업데이트
- gathering-full 이벤트로 자동 Complete 페이지 이동
- React Query 캐시 동기화
- SSE 데이터 우선, 실패 시 초기 데이터 사용
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* refactor: PendingViewContainer에서 불필요한 React Query 캐시 업데이트 제거
- queryClient.setQueryData 호출 제거
- useQueryClient, gatheringKeys import 제거
- SSE 데이터를 로컬 상태로만 관리하도록 단순화
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* refactor: SSE 이벤트 핸들러에서 파싱된 데이터 직접 전달
- events 핸들러가 MessageEvent 대신 파싱된 데이터를 직접 받도록 변경
- useServerSentEvent 내부에서 JSON.parse 처리
- 각 핸들러에서 명시적으로 타입 지정 가능
- 에러 핸들링 내장
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* refactor: SSE 이벤트 핸들러가 MessageEvent를 직접 받도록 변경
- events 핸들러가 MessageEvent를 직접 전달받음
- 사용자가 MessageEvent<T>로 타입 지정 가능
- JSON.parse는 사용자가 직접 수행
- 제네릭 제거로 더 단순하고 표준에 가까운 API
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* refactor: SSE 타입 구조 개선
- types.ts → events.ts 리네임 (이벤트 타입임을 명확히)
- Hook Options/Return 타입은 useServerSentEvent.ts에 위치
- events.ts는 순수 이벤트 데이터 타입만 포함
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* fix: Prettier 및 TypeScript 오류 수정
- Prettier 포맷팅 적용
- MessageEvent 타입 캐스팅 수정 (event.data를 string으로 파싱)
- useMemo 제거하여 capacity를 단순 객체로 변경
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* refactor: SSE 재연결 문제 해결 및 Hook 개선
- useServerSentEvent 의존성 배열에서 콜백 제거하여 불필요한 재연결 방지
- useGetGatheringCapacity를 useQuery로 변경하고 enabled 옵션 추가
- reconnect, close 함수 제거로 Hook 단순화
- baseURL 처리를 Hook 내부로 이동하여 일관성 확보
- SSR 호환성을 위해 EventSource 상수 대신 숫자 리터럴 사용
- 디버깅을 위한 콘솔 로그 추가
Co-Authored-By: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>
* refactor: PendingViewContainer SSR 적용 및 SSE Hook 개선
- PendingViewContainer에서 초기 데이터를 서버 컴포넌트에서 가져와 props로 전달
- useGetGatheringCapacity를 useSuspenseQuery로 변경
- SSE 이벤트 핸들러를 useMemo로 최적화하여 불필요한 재생성 방지
- SSE 훅에서 이벤트 리스너 정리 로직 추가
- 불필요한 autoReconnect, reconnectInterval 옵션 제거
- console.log 정리
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* refactor: OpinionFormView SSE 이벤트 핸들러 useMemo 최적화
- eventHandlers를 useMemo로 메모이제이션하여 불필요한 재생성 방지
- accessKey와 router 변경 시에만 이벤트 핸들러 재생성
- PendingViewContainer와 동일한 최적화 패턴 적용
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* chore: prettier 포맷에 맞지 않았던 코드 수정
* feat: participantCount Event Data 에 대한 유효성 검증 및 Parsing 로직 추가:
* fix: 의견 수합 폼 내에서는 SSE 로 정원 초과 여부를 파악하지 않도록 소거
* fix: 코드 리뷰 반영하여 수정
---------
Co-authored-by: Claude (us.anthropic.claude-sonnet-4-5-20250929-v1:0) <noreply@anthropic.com>1 parent a406ad4 commit 0d220e0
File tree
9 files changed
+145
-29
lines changed- app/gathering/[accessKey]/opinion/pending
- src
- hooks
- apis/gathering
- sse
- pageComponents/gathering/opinion
- schemas/sse
9 files changed
+145
-29
lines changedLines changed: 50 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
| 3 | + | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
| 10 | + | |
9 | 11 | | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
13 | | - | |
14 | 15 | | |
15 | | - | |
| 16 | + | |
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
19 | | - | |
20 | | - | |
21 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
22 | 34 | | |
23 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
24 | 41 | | |
25 | | - | |
26 | | - | |
27 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
28 | 67 | | |
29 | 68 | | |
30 | 69 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
7 | | - | |
| 1 | + | |
8 | 2 | | |
9 | 3 | | |
10 | 4 | | |
| |||
15 | 9 | | |
16 | 10 | | |
17 | 11 | | |
18 | | - | |
19 | 12 | | |
20 | 13 | | |
21 | 14 | | |
22 | 15 | | |
23 | 16 | | |
24 | | - | |
25 | 17 | | |
26 | | - | |
| 18 | + | |
27 | 19 | | |
28 | 20 | | |
29 | | - | |
30 | | - | |
31 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
32 | 26 | | |
33 | 27 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | 5 | | |
10 | 6 | | |
11 | 7 | | |
12 | 8 | | |
13 | | - | |
14 | 9 | | |
15 | 10 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
0 commit comments