마지막 업데이트 2026-07-30
group-monitoring-claim peer가 재등록되지 않는다. 진행자는 카드뷰를 계속 보고 있는데도
서버 입장에선 "그룹 모니터링 중인 진행자 없음"이 되어, 통합 모니터링 진행자 뱃지가 회색으로 남는다.
새로고침 전까지 유지된다.
2026-04-25 통합 모니터링 도입(#496) 이후 상시 존재해온 누락이다. 같은 문제를 룸 단위에서는
PPI-1012(3c143f4b, #714)에서 이미 고쳤지만, 그룹 훅에는 같은 패치가 들어가지 않았다.
monitor-group-{groupId} 룸 구독 끊김(그룹 알림·아동 전송상태 미수신)이 함께 따라온다.
80ed8d8d (2026-07-30)pWI2Ya-AvRLUydJpAASl → 클레임 group-monitoring:892ff4b4:80ed8d8d:pWI2Ya… 생성 (뱃지 파랑)U7mRkIrTyf6jMJsQAAS3 · Monitor 리나 connected(presence)만 복구, started monitoring group 없음vTNsD0yhaACdAaPXAATW, 역시 클레임 미복구Guest step updated · Host transport state … RTT 7~8ms 정상 — 화면·스텝 동기화는 멀쩡started monitoring group 80ed8d8d 뱃지 복구| 상태 | 재연결 복구 경로 | 결과 |
|---|---|---|
| presence peer | use-monitor-socket.ts connect → MONITOR_CONNECTED |
복구 |
룸 미디어 peer{hostId}-{roomId}-{tabId} |
use-monitor-session.ts:325 재조인 |
복구 (영상·스텝 동기화 정상) |
| 룸 모니터링 클레임 (1:1 포커스뷰) |
use-room-monitoring.ts:145-166 — PPI-1012에서 추가 |
복구 (카드뷰는 이 훅을 쓰지 않음) |
그룹 모니터링 클레임group-monitoring-claim |
없음 — hasStartedRef 가드로 최초 1회만 발송 |
미복구 ← 본 이슈 |
통합 모니터링 카드의 파란 칩은 live-sessions.tsx:199의 monitoringNames로 결정되고, 그 소스는
① 포커스뷰 모니터(session.monitoringHostName) ② groupMonitorsByGroupId(connectedHosts 중
peerKind === "group-monitoring-claim") 둘뿐이다. 카드뷰의 룸 미디어 peer는 monitoringRoomId가
없어 getRoomList의 isMonitoring 판정에 들어가지 않는다. 따라서 카드뷰 진행자의 유일한 표시 근거가 그룹 클레임이다.
broadcast-utils.ts getConnectedHosts에서 제외peersHandlers.ts:112,141이 monitoringGroupId + claim peerKind로 monitors를 뽑는다monitor-group-{groupId} 룸 이탈 — 클레임 등록 시 socket.join(monitoring-handlers.ts:308)하므로, 재조인이 없으면 GUEST_TRANSPORT_STATE(아동 전송상태)·GROUP_ALERT_BROADCAST를 못 받는다. 카드뷰는 getRoomMonitors(monitoringRoomId 필요) 대상이 아니라 이 룸 경로에만 의존한다# 클레임 생성/삭제 대조 — 삭제 뒤 재등록 로그가 없으면 확정 {instance="ppi-socket-prod"} |= "monitoring group" {instance="ppi-socket-prod"} |= "<hostId 앞 8자>" |~ "Cleaning up peer|monitoring group"
Host <hostId> started monitoring group <groupId> — 클레임 등록Cleaning up peer group-monitoring:<hostId>:<groupId>:<socketId> after disconnect — 삭제[Socket] ⚠️ Disconnected {reason: "transport close"} → 직후 ✅ Connected! Socket ID: …(새 ID)Guest step updated가 계속 들어오면 화면은 정상, 표시만 stale인 상태# 같은 시간대 룸 클레임은 재등록된다 (PPI-1012 경로) 09:23:13 Cleaning up peer monitoring:2bf8a401…-monitoring-ac9ed028…_30 after disconnect 09:23:35 Host 2bf8a401…-monitoring-ac9ed028…_30 started monitoring ac9ed028…_30 ← 자동 재등록
apps/web/features/monitor/group-monitoring/model/use-group-monitoring.ts 한 파일. 서버 변경 없음.
+ const hasRegisteredRef = useRef(false); const emitStart = useCallback(() => { socket.emit(SOCKET_EVENTS.HOST_START_GROUP_MONITORING, { groupId, hostId, displayName }); + hasRegisteredRef.current = true; }, [groupId, hostId, hostName]); + // 소켓 재연결 시 그룹 카드뷰 클레임 재등록 (룸 단위는 PPI-1012) + useEffect(() => { + const handleReconnect = () => { + if (hasRegisteredRef.current) emitStart(); + }; + socket.on("connect", handleReconnect); + return () => { socket.off("connect", handleReconnect); }; + }, [emitStart]);
"connect"는 socket.io 내장 이벤트로 최초 연결과 모든 재연결에서 발생한다. 최초 연결은 기존 startMonitoring 경로가 처리하고, 그 시점엔 hasRegisteredRef가 false라 중복 등록이 없다MONITOR_FORCE_KICKED)·언마운트 시 플래그를 되돌려, 클레임을 놓은 뒤 재연결로 되살아나지 않게 한다HOST_START_GROUP_MONITORING은 새 socket.id로 클레임을 만들고 monitor-group 룸에 재조인하므로, 이 emit 하나로 뱃지·내보내기 대상·알림 구독이 함께 복구된다socket.io.on("reconnect")(Manager 이벤트)를 쓰지 않은 이유: 레포의 기존 패턴(use-room-monitoring, use-monitor-socket)이 모두 socket.on("connect")다tsc --noEmit 통과(잔여 에러는 .next 생성 타입의 기존 이슈). 실동작(순단 → 뱃지 복구)은 브라우저 확인 필요:
카드뷰 탭에서 DevTools Network offline→online 토글 → 콘솔 [useGroupMonitoring] Socket reconnected, re-registering group monitoring claim 확인 →
대시보드 홈 탭에서 칩이 파란색으로 돌아오는지 확인. 소켓 서버 로그에 started monitoring group이 다시 찍히는지도 함께 본다.
connect 재등록을 쌍으로 가져야 한다hasStartedRef 같은 "1회 실행 가드" 패턴을 grep으로 훑는 것이 값싼 방어다28fe47c8 · 브랜치 PPI-11743c143f4b, #714) — 룸 단위 클레임 재등록50fe0157 [PPI-765] 통합 모니터링 · 카드 UI 통일 (#496), d2325525 [PPI-812] 그룹 진행자 내보내기 (#437)docs/handover/jacob/monitor-dashboard.md, card-view.md