아동 알림 프리셋 — 동작 흐름

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

진행자가 프리셋을 누르면 아동(게스트) 화면에 "환경소음 안내" 알림이 뜨기까지의 흐름. (이해용 정리)

진행자(모니터) Socket 서버 게스트(아동) 빠름직행 느림Redis 경유

1. 전체 흐름

진행자
① 프리셋 버튼/드롭다운 클릭
포커스뷰 ChildAlertPresetsPanel 또는 카드뷰 SessionControls
진행자
pickAndBroadcastAmbientTemplate() — 이미지 1장 랜덤 선택
템플릿 이미지 목록에서 pickedId/pickedFileName 1개 선택. 동시에 진행자 미러뷰(store.current)를 그 이미지로 갱신. → 여기서 두 갈래로 나간다.
▼   두 신호가 거의 동시에 출발
→ 서버 → 게스트
②-A 스냅샷 HOST_SET_AMBIENT_NOISE_TEMPLATE 느림
고른 단일 이미지를 담은 "스냅샷". 서버가 Redis 저장(await) 후 broadcast → 게스트는 받아서 ambientNoiseTemplateRef에 저장하고 이미지를 미리 캐시. 표시는 하지 않음(준비용).
→ 서버 → 게스트
②-B 트리거 host-session-message 빠름
문자열 {{환경소음N}} + ambientImage(고른 이미지) 동봉. 특정 게스트에게 타겟 전달. 이게 실제로 알림을 띄우는 신호이자 AI 프롬프트.
게스트
③ 트리거 수신 → handleHostMessage(message, hostId, ambientImage)
먼저 AI에 메시지 전달(핑퐁이가 "안 들려" 응답) → 그 다음 알림 표시 여부를 아래 로직으로 판단.
게스트
④ 알림 표시 (15초) — 텍스트 + 이미지 (바운스 모션)
표시 상태는 진행자 미러뷰로도 relay되어 진행자가 "아동이 지금 보는 화면"을 같이 본다.

2. 게스트 판단 로직 (④의 핵심)

Q0. 전역 알림 enabled 인가?
아니오 아무것도 안 함(스킵).
아래로 진행 ↓
Q1. 트리거에 ambientImage가 동봉돼 있나? ★ 현재 기본 경로
그 이미지로 즉시 표시. 스냅샷 도착 타이밍·게스트 랜덤 선택에 의존하지 않음 → 진행자 미러와 항상 동일한 이미지.
아니오 (레거시 호환 경로 — 예: {{환경소음}} 수동 입력) ↓
Q2. 메시지가 현재 활성 스냅샷의 sendText를 포함하나?
활성 스냅샷 이미지로 표시.
아니오 아직 스냅샷이 안 왔을 수 있음(race) → 메시지를 버퍼링. 이후 스냅샷이 도착하면 3초 내 재평가하여 표시(resolved via late snapshot). 안 오면 미발생.
왜 신호가 둘인가? ②-B(트리거)는 "지금 띄워"라는 빠른 신호, ②-A(스냅샷)는 "무엇을 띄울지"를 담은 느린 신호다. 예전엔 게스트가 ②-A를 기다렸다가 ②-B와 매칭해야 했는데, 순서가 뒤집히면 첫 알림을 놓치거나(누락) 게스트가 제 멋대로 다른 이미지를 골라(불일치) 문제였다. 그래서 ②-B에 이미지를 직접 동봉해(Q1) 타이밍 의존을 없앤 것이 현재 구조다.

3. 표시 규칙

⏱ 15초 자동 숨김

표시 후 15초 뒤 자동으로 사라진다.

🖼 표시 중 이미지 고정

표시되는 동안 이미지가 바뀌지 않는다. 게스트·진행자 미러뷰 모두(미러는 클릭 seq로 잠금). 같은 클릭의 URL 로딩 완료만 반영.

🚫 표시 중 진행자 재트리거 차단

아동 알림이 떠 있는 동안 진행자 프리셋 버튼/드롭다운이 비활성화된다.

✕ 아동이 닫으면 즉시 종료

아동이 X를 누르면 표시 종료가 진행자로 relay되어, 진행자가 다시 트리거 가능해진다(15초 전이라도).

4. 한 줄 요약

진행자 클릭 → 고른 이미지를 트리거에 동봉해 게스트로 전송 → 게스트는 그 이미지로 즉시·동일하게 표시. 표시 중에는 양쪽 이미지가 고정되고 진행자 재트리거는 차단되며, 아동이 X로 닫으면 다시 트리거할 수 있다.
작성: 2026-06-09 / chulsu · 관련: PPI-1014 (커밋 id-053·id-020·id-015·id-023)