← PPI Docs

PPI · 아동 네트워크 안정성 · BACKLOG PROPOSAL

자료는 한 번만 받고,
쓰지 않는 다운로드는 멈추기

마지막 업데이트 2026-10-02

모바일·태블릿에서 같은 자료의 중복 전송과 화면 이탈 뒤의 회선 낭비를 줄이는 백로그입니다.

2026-10-02 · develop 257f82f5ecea91aab61b82d303a40cb7c0038904 기준

코드 조사 완료 · 구현 제안. 실제 중복 요청 빈도·운영 장애 원인·개선율은 아직 측정하지 않았습니다. 아래 수치는 구현 후 검증할 완료 조건이며, 이번 작업에서는 애플리케이션 코드를 변경하지 않았습니다.

왜 이 지점을 개선하는가

가정용 공유기나 이동 중 회선에서 아동 카메라·마이크 송출, AI 음성 수신, 자료 다운로드가 회선을 함께 사용합니다. 이 백로그는 그중 자료 다운로드의 불필요한 다운링크 사용을 줄이는 범위입니다.

현재동일 파일 동시 요청 → 각 요청이 캐시 미스를 확인 → 다운로드가 겹칠 수 있음
변경 제안동일 파일·버전·화질 → 진행 중 요청 1개 공유 → 모든 소비자에게 결과 전달
화면 이탈일부 소비자 이탈 → 유지
마지막 소비자 이탈 → 다운로드·재시도 취소

이미 배치 사전 다운로드는 순차 처리하고, 대기실에서는 입장 전 stopAndDrain으로 중단·정리합니다. 남아 있는 lazy 요청의 공유·취소 경계를 보완하며, 입장 조건이나 미디어 송출 구조는 바꾸지 않습니다.

효과는 캐시 미스·동시 요청·빠른 화면 전환 때 기대됩니다. 카메라 업링크 절감, 무선망 단절 복구, 전반적인 보안 강화의 효과로 확대 해석하지 않습니다.

백로그 초안 · 외부 이슈 미등록P2 제안소규모 · 공통 캐시 경계

[아동 네트워크] 같은 자료의 중복 다운로드와 화면 이탈 후 요청 낭비 줄이기

문제 정의

확정: useResourceCache의 전역 Map은 완료된 Response·blob URL을 저장합니다. getResourceUrl의 캐시 조회와 다운로드 사이에 진행 중 Promise를 공유하는 장치가 없고, 옵션에 취소 signal도 없습니다. 같은 자료의 콜드 캐시 요청이 겹치면 각각 다운로드를 시작할 수 있습니다. E04

미확정: 실제 수업에서 중복 요청이 발생하는 빈도와 낭비 바이트. 이미 캐시가 있는 정상 수업에는 개선 폭이 작을 수 있습니다. 모바일 회선 단절 자체를 이 변경으로 해결할 수는 없습니다.

목표와 범위

동일 자료·버전·실제 화질에 대한 진행 중 파일 전송을 1개로 공유하고, 사용자가 모두 떠난 자료 요청은 중단합니다. 새로운 스트리밍 포맷, Service Worker, 입장 게이트 변경, 수업 중 전체 자료 단계별 다운로드는 포함하지 않습니다.

권한: 현재 자료 접근 권한 그대로. 다른 로그인 사용자·세션 사이에 진행 중 요청이나 사설 URL을 공유하지 않도록 수명을 제한합니다.

세부 작업 제안

  1. 가짜 fetch와 지연 응답으로 동일 자료를 동시에 요청하는 characterization 테스트를 먼저 추가. 배치 사전 캐시와 lazy 요청이 겹치는 경우도 포함.
  2. 기존 캐시 훅 옆에 작은 요청 레지스트리를 두고 메타데이터 요청과 본문 다운로드를 각각 공유. 파일명·버전·해결된 화질을 구분하고, 서명 URL 문자열을 영속 키로 사용하지 않음.
  3. 화면의 소비자 수를 추적. 한 소비자의 취소는 다른 소비자를 끊지 않으며, 마지막 소비자 해제 시 fetch와 Range 재시도에 취소를 전파. 성공·실패·취소 후 진행 중 항목 정리.
  4. 우선 영상·이미지의 lazy 호출부에 수명 신호 연결. 화면 전환 후 늦게 도착한 URL을 새 화면에 붙이지 않도록 기존 세대·cleanup 패턴 활용. 완료 캐시의 소유권과 blob URL 해제 시점도 검증.
  5. 진단은 요청 수·중복 합류 수·전송 바이트·취소 이유·활성 요청 수만 집계. 토큰, 서명 URL, 아동 이름·원본 room ID는 새 로그에 기록하지 않음.
완료 조건 제안
  • 동일 키 3회 동시 요청 시 파일 본문 다운로드 1회, 결과 3개 모두 정상 사용. 다른 버전·화질은 섞이지 않음.
  • 소비자 1명 이탈 시 남은 요청 정상 완료. 전원 이탈 시 1초 이내 abort 신호 전달, 뒤따르는 신규 Range 재시도 0회. 이미 전송된 패킷은 회수 대상으로 보지 않음.
  • 겹친 3회 요청 fixture의 본문 다운로드량은 단일 요청 기준 +10% 이내. Range 복구·401/403·캐시 저장 실패·재입장 시 대기 Promise 잔류 0개.
  • 실기기 같은 조건 3회 비교에서 자료 준비 p95가 기준보다 10% 넘게 느려지지 않고, 음성 끊김 횟수가 늘지 않음. 개선 바이트가 확인되지 않으면 효과 검증 미완료로 기록.

테스트케이스

ID / 준비행동기대 결과
N1 · 캐시 없음, 같은 파일3개 소비자 동시 호출, 그중 1개 unmount본문 GET 1회, 나머지 2개 재생 정상
N2 · preload 진행 중같은 버전·화질 lazy 요청 후 preload 취소lazy 소비자가 살아 있으면 다운로드 유지. 입장 barrier는 자기 작업 정리 후 종료
N3 · 480p/기본 화질·버전 변경각 키를 동시에 조회공유 범위가 분리되고 오래된 파일이 새 결과를 덮지 않음
N4 · iPad Safari / Android Chrome3 Mbps↓·0.5 Mbps↑·RTT 200 ms·손실 2% 조건에서 취소 및 5초 단절 후 복구멈춘 요청·무한 재시도 없음. 실제 단말/브라우저 버전을 결과에 기록

리소스: E04, E05, E14, apps/web/hooks/use-resource-cache.test.ts, apps/web/lib/resources/waiting-resource-prefetch.test.ts.

이슈 / 결정 필요: 자료 갱신 중 키 전환 시점과 마지막 소비자 취소 후 blob 보관 정책. 기존 캐시 문서의 후속 논의를 이 백로그로 좁히며, 진행형 다운로드 설계까지 확장하지 않습니다.

코드 근거와 관련 문서

  1. E04 · 캐시 / lazy 요청 — apps/web/hooks/use-resource-cache.ts:81 · 완료 Map; 229행 순차 사전 다운로드, 302행 lazy, 389행 signal 없이 fetchResumable 호출.
  2. E05 · 대기실 중단 장치 — apps/web/lib/resources/waiting-resource-prefetch.ts:110 · stopAndDrain.
  3. E14 · 자료 재시도 — apps/web/lib/fetch-resumable.ts · 기존 Range·취소 경로. MDN: fetch·응답 body 취소.

리소스 캐싱·선다운로드 · HTTP Range 이어받기

검증·적용 방법

같은 단말·자료에서 캐시 있음/없음, 정상망/저속망, 5초 단절을 비교합니다. HTTP 요청 수·바이트·취소 시간과 음성 끊김을 함께 기록합니다. 개발자도구의 HTTP 제한만으로 WebRTC까지 제한했다고 간주하지 않습니다. 차량 환경은 네트워크 shaping 또는 안전한 정차 상태에서 재현합니다.

구현 전 최소 테스트로 동시 요청·공유 소비자 취소를 보호하고 관련 테스트만 실행합니다. 저장소의 설계 승인·Code Quality Guardian 절차를 적용하고, 새 UI 상태가 생기면 Storybook fixture·정적 빌드 검증을 포함합니다. 변경은 독립 PR로 제한하며 정상 다운로드·입장이 회귀하면 적용을 중단합니다.

이번 검증 범위는 현재 코드 대조와 문서·링크·렌더링입니다. 실제 단말 성능 시험과 개선 구현은 후속 작업입니다.

LLM용 인계 맥락
PPI develop 257f82f5ecea91aab61b82d303a40cb7c0038904, 2026-10-02. 백로그: useResourceCache의 동일 자료 진행 중 요청 공유와 소비자 수명 기반 취소. 현재 batch preload는 순차 처리·취소 지원, lazy는 완료 캐시만 공유하고 signal 옵션 없음. 기존 입장 게이트·Range 복구 보존. 동일 키 3회 동시 요청의 본문 GET 1회, 일부 취소는 나머지 소비자 보호, 마지막 취소는 abort 전파. 버전·화질·사용자 수명을 분리. 운영 빈도와 개선율은 미측정, 런타임 구현 미실행.