Monitor 대시보드 (카드뷰·포커스뷰·통합) — 코드레벨 동작 흐름 P1코드레벨

마지막 업데이트 2026-07-22

작성일: 2026-06-14 대상: 개발자 — 진행자 모니터링 화면 구조 파악 핵심 파일: app/monitor-dashboard/, widgets/monitor-dashboard/, stores/use-monitor-*-store.ts

개요 · 범위

진행자(치료사)가 모니터링 중인 모든 세션(1:1 + 그룹)을 한눈에 보는 화면. 대시보드 홈 → 카드뷰(그리드) → 포커스뷰(단일 세션) 3계층. @handover-monitor-dashboard/@handover-card-view/@handover-focus-view 영역.

AI-driven + Jacob 영역: 설계 의도·결정·함정의 원본은 docs/handover/jacob/{monitor-dashboard,card-view,focus-view}.md. 기획 의도(왜 통합했나 등)는 기획자 리지 담당. 본 문서는 코드 흐름 + 그 md의 개발 의도를 인용한다. Jacob 평가: "2주 더 있어도 손볼 거 없음"(안정적).

3계층 라우팅 app/monitor-dashboard/

경로역할
/monitor-dashboard (page.tsx)홈 — 전체 세션 목록(통합 모니터링)
/monitor-dashboard/[group]카드뷰 — 그룹 내 여러 아동 동시 모니터링(그리드)
/monitor-dashboard/[group]/[roomId]포커스뷰 — 단일 세션 집중

세션 분류: oneOnOne / multi(group) / test 3종(useGroupMonitoring + useScheduledSessions 응답으로 판정, #614). 1:1은 바로 포커스뷰, 그룹은 카드 그리드 경유. 카드 UI는 1:1·그룹 공통(#496). 출처: monitor-dashboard.md#5분

상태·데이터 흐름

/api/scheduled-lessons → useScheduledSessions ─┐ useGroupMonitoring ───────────────────────────┤→ monitor stores ─→ 홈/카드뷰/포커스뷰 Socket.io (host-socket) ───────────────────────┘ (use-monitor-data-store / use-monitor-ui-store) └ disconnect backstop → 타이머 리셋 방지(#357, #448)
  • 세션 카드 병합: 활성(active, 소켓 라이브) + 예약(scheduled API)을 합쳐 카드 목록 구성. 예약 폴링 응답이 잠시 누락돼도 카드 자리가 흔들리지 않게 roomId 기준 sticky 정렬 + 보존 캐시(#578, #622).
  • 전역 상태: use-monitor-data-store(rooms/sessions/toasts/alerts), use-monitor-ui-store(패널 토글 등).
  • 사용자명: UUID 노출 금지, 항상 실제 이름(profile 캐싱, #554/#569).
출처: monitor-dashboard.md#상태·데이터-흐름, card-view.md#invariants

카드뷰 (세션 카드) widgets/monitor-dashboard/session-card/ · entities/monitor-session/use-monitor-session.ts

카드 한 장 = 한 룸(roomId)에 진입한 아동 1명의 라이브 수업. useMonitorSession이 WebRTC 세션 연결·상태를, useHostSocket이 호스트-게스트 소켓을 담당.

기능동작커밋
청취 토글 + 볼륨해당 아동 핑퐁이 음성, 카드별 독립 슬라이더 0~300%#581/#596/#638
포커스뷰 진입카드 청취 자동 OFF(의도된 동작) — 포커스뷰에서 다시 ON#436
자동 응답('응')핑퐁이 무응답 시 진행자 대신 자동 발송(카드별 수동 모드). 이후 수동 발송만 허용으로 정책 변경#399→#455
누적 시간useCumulativeElapsed — lessonStartedAt 기반 + 폴백 타이머#630
스텝 네비/개입 폼/이슈 스탬프카드에서 직접 제어#462/#454/#555
V1/V2 주의: V1 카드뷰(features/session/ui/*, 현 코드에 session-card.tsx 잔존)는 작업 대상 아님. V2(widgets/monitor-dashboard/)만 카드뷰 인수인계 대상. card-view.md#핵심-파일-맵

비디오 확대 features/monitor/video-expansion/use-video-expansion.ts

카드 썸네일은 저화질(mediasoup spatialLayer 0, #10). 특정 아동을 확대하면 expandVideo(peerId, ...)setConsumerLayer(peerId, 2)고화질(L2) 요청, 축소 시 복귀. "보이는 것만 고화질"(SFU selective forwarding). 상세 → #10.

헤드셋 모드 · 환경소음 (Redis settings) widgets/monitor-dashboard/headset-selector/

헤드셋 모드(far/near field)·환경소음 토글은 Redis settings-store에 저장된다(PPI-879/PPI-962, #636). 다중 인스턴스에서 cross-instance hydration fallback 있음(id-006). 저장 순서·롤백 규칙은 #5 Router 매니저 및 redis-infra.md.

룸 설정 변경 규칙(redis-infra.md): Redis 저장 → broadcast 순서(id-019), ack 실패 시 UI 롤백(id-033). 낙관적 업데이트 금지.

예약 세션 · 미접속 알림톡 · 토스트

  • 오늘 예약 세션: /api/scheduled-lessonsuse-today-scheduled-sessions(today-scheduled/ 위젯).
  • 미접속/장시간 감지: use-session-checker. 게스트 미접속 5/10분 시 알림톡 자동 발송.
  • 토스트: 도움 요청·미접속·자동응답 카운트다운 등. 이름은 실제 사용자명(#554), 발송 버튼 포함(#421).
미해결: 미접속 알림톡 재접속 케이스 오발송은 여전히 미해결(방지 PR #378→revert #381은 QA 오류). 임시 회피는 진행자 수동 발송(#421). monitor-dashboard.md#결정과-거절된-대안, known-gaps.md

함정 · 회귀 패턴 출처: card-view.md / monitor-dashboard.md#failure-modes

  • 누적 시간 정합성: lessonStartedAt 기반 계산과 폴백 타이머가 동시 존재 → 어긋남 회귀 반복(#507/#527/#630). 누적시간 변경 시 게스트 자동전환 판정값과 호스트 UI 양쪽 동시 갱신 필수.
  • 카드 자리 흔들림: scheduled 폴링 응답 변동 시 카드 순서 변경 → sticky 캐시로 해결(#578/#622). 정렬 변경 시 sticky 위에 정렬 레이어 권장.
  • 청취 토글 race: 빠른 클릭/포커스 전환 시 OFF 누락(#438/#436).
  • 1:1/그룹 분류 깜빡임: scheduled 응답·렌더 타이밍 의존(#614). 분류 변경 시 useGroupMonitoring + scheduled 파싱 + 카드 라우팅 분기 동시 확인.
  • 소켓 재연결 시 타이머 리셋: disconnect backstop으로 해결(#357/#448). 소켓 이벤트 추가 시 entities/monitor-socket + apps/socket 양쪽 + Redis 채널 prefix(#640) 확인.
  • 테스트 세션 격리: 운영 세션 카운트에 섞이지 않게(#299).

파일 · 라인 레퍼런스

파일역할
app/monitor-dashboard/{page,[group]/page,[group]/[roomId]/page}.tsx홈/카드뷰/포커스뷰 라우팅
widgets/monitor-dashboard/{session-card,live-sessions,today-scheduled,headset-selector}/V2 위젯
stores/use-monitor-data-store.ts, use-monitor-ui-store.ts전역 상태
entities/monitor-session/use-monitor-session.tsWebRTC 세션 연결·상태
features/monitor/video-expansion/use-video-expansion.ts확대 시 layer 2
features/monitor/hooks/{use-scheduled-sessions,use-today-scheduled-sessions}.ts예약 세션
docs/handover/jacob/{monitor-dashboard,card-view,focus-view}.md설계 의도·결정·함정 원본