아동 알림 프리셋 트리거 race · 이미지 동기화 수정

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

아동 알림 프리셋 환경소음 스냅샷 race 이미지 동기화 표시 중 고정 트리거 이미지 동봉 PPI-1014 2026-06-09

TL;DR

아동 알림 프리셋(환경소음 안내)의 트리거/표시에서 발견된 세 가지 증상 — ① 첫 트리거가 가끔 안 뜸, ② 표시 중 이미지가 계속 바뀜, ③ 진행자 미러뷰와 아동 화면의 이미지가 다름 — 을 분석하고 수정했다.

근본 원인은 "진행자가 고른 이미지 스냅샷(HOST_SET, Redis 경유로 느림)"이 "트리거 메시지(host-session-message, 직행으로 빠름)"보다 늦게 도착하는 race와, 게스트가 스냅샷을 못 받은 상태에서 독립적으로 랜덤 이미지를 고르는 설계였다.

최종 해법은 진행자가 고른 단일 이미지를 트리거 메시지에 직접 동봉해, 게스트가 스냅샷 도착 타이밍·랜덤 없이 호스트와 동일한 이미지를 즉시 표시하도록 한 것이다. 함께 "표시 중 이미지 고정"과 "표시 중 진행자 재트리거 차단"도 정리했다.

1. 증상 — 무엇이 문제였나

2. 원인 — 스냅샷 vs 트리거 도착 race

프리셋 버튼을 누르면 두 개의 신호가 거의 동시에 게스트로 향한다.

신호내용경로속도
① 스냅샷 HOST_SET_AMBIENT_NOISE_TEMPLATE표시할 텍스트·이미지·트리거 sendText서버 → Redis 저장(await) → 게스트느림
② 트리거 host-session-message문자열 {{환경소음N}} (AI 프롬프트 + 알림 트리거)서버 → 게스트 직행빠름

게스트는 ②가 왔을 때 message.includes(스냅샷.sendText)로 표시 여부를 판단하고, 이미지는 스냅샷에서 가져온다. 그런데 ②가 ①보다 먼저 오면:

full-list 스냅샷 출처: 게스트 입장(Redis 저장본), 진행자 패널 마운트(broadcastTemplate), 프리셋 토글 ON/저장(broadcastActive) — 모두 이미지 목록 전체를 보낸다. 버튼 클릭(pickAndBroadcastAmbientTemplate)만 1장으로 좁혀 보낸다.

3. 수정 ① — 첫 트리거 race 보정 + X 타이머 누수

트리거가 와도 스냅샷이 없어 매칭 실패하면 버리지 않고 버퍼링하고, 뒤늦게 스냅샷이 도착하는 순간 재평가해 띄운다(양방향 도착 순서 모두 커버).

덤으로 X(닫기) 버튼(clearAmbientNoiseAlert)이 15초 자동 숨김 타이머를 clearTimeout 안 하던 누수도 수정(토글 OFF·언마운트 경로와 일치).

4. 수정 ② — 표시 중 이미지 고정

알림이 한 번 뜨면 그 표시 동안 이미지를 고정한다.

5. 수정 ③ — 표시 중 진행자 재트리거 차단

아동 알림이 표시 중(guestAmbientNoiseAlertVisible)이면 진행자의 프리셋 트리거를 막는다 — 포커스뷰 프리셋 버튼·카드뷰 드롭다운 모두 비활성화. 아동이 X로 닫으면 visible:false가 relay되어 자동 재활성화된다.

6. 수정 ④ (근본) — 트리거에 이미지 동봉

시각 알림의 "표시"는 특정 게스트에게 타겟된 host-session-message가 구동하므로(스냅샷은 글로벌·setup용), 이미지를 이 타겟 트리거에 동봉하면 멀티룸에서도 정확하다.

이미지를 동봉하지 않은 트리거(예: {{환경소음}} 수동 입력)는 기존 sendText 매칭/race 보정 경로로 폴백한다.

결과: 게스트가 호스트가 고른 그 1장(동일 pick의 fileName/id)을 표시 → 미러뷰와 항상 일치하고, 표시 중 고정·표시 중 차단과도 충돌하지 않는다.

7. Before / After

상황
세션 첫 트리거스냅샷 늦으면 누락버퍼 재평가로 표시
표시 중 재클릭/늦은 스냅샷이미지 계속 교체이미지 고정
host vs guest 이미지독립 랜덤 → 불일치동봉 이미지로 항상 일치
표시 중 진행자 트리거가능(혼란)차단, X 후 재허용

8. 주요 변경 파일 · 커밋

커밋

  • id-053 첫 트리거 race 보정 + 진단 로그 + X 타이머 누수
  • id-020 게스트 표시 중 이미지 고정
  • id-015 진행자 미러뷰 표시 중 이미지 고정(seq)
  • id-023 트리거 이미지 동봉 + 표시 중 진행자 재트리거 차단

파일

  • entities/guest-page-session/model/use-guest-page-session.ts
  • entities/ambient-noise-template/model/broadcast-ambient-template.ts
  • entities/monitor-session/model/use-monitor-session.ts
  • entities/socket-connection/model/use-mediasoup-socket.ts
  • stores/use-ambient-noise-alert-store.ts
  • components/sections/host-video.tsx
  • features/session/ui/session-controls.tsx, session-card.tsx
  • widgets/monitor/ui/child-alert-presets-panel.tsx, monitor-control-sidebar.tsx
  • app/monitor-dashboard/[group]/[roomId]/page.tsx
  • apps/socket/src/sfu-socket/handlers/session-handlers.ts
⚠️ socket 서버도 변경됨 — 배포 시 web + socket 둘 다 올려야 ambientImage가 relay된다(미반영 시 레거시 경로로 폴백되어 불일치 재현).

9. 알려진 한계 · 후속