<PonsLink/>
작업
글
주제
시리즈
카테고리
연락
⌘K 검색
About
코드와 제품으로

코드와 제품으로

연결되는 세계

연결되는 세계

PonsLink는 만남 뒤 요청을 세션으로 잇고, PonsWarp는 서버 보관 없이 파일을 직접 전송합니다. 이 블로그는 기능 소개보다 설계 판단과 운영 증거를 남깁니다.

연락처

[email protected]github.com/DeclanJeon

운영

콘텐츠는 WordPress headless CMS, 공개 UI는 Next.js입니다.

초안 미리보기
© 2026 PonsLink Blog|Next.js · WordPress REST · Framer Motion
Local-first · Backup-before-deploy

[Blueprint W3] PonsWarp LAN 10Mbps — 좁은 길을 증거로 만든 이유

Declan·2026년 8월 28일

  • Blueprint
  • P2P/분산기술
  • 개발 회고

10Mbps 제약을 걸고 측정한 포크. networkAdaptiveController 피드백 루프와 lanEvidenceAdapter가 좁은 길에서 resume을 어떻게 증거로 바꾸는지 다룬다.

# [Blueprint W3] PonsWarp LAN 10Mbps — 좁은 길을 증거로 만든 이유 > Series: `blueprint-ponswarp` (3/5) · Category: `P2P/분산기술` + `개발 회고` · Slug: `blueprint-ponswarp-03-lan-10mbps-evidence` > Source: `blueprints/specs/P01_ponswarp_family.md` §03 + `blueprints/03-ponswarp-lan-10mbps.png` + `ponswarp-lan-10mbps/lanEvidenceAdapter.ts` — ## 0. TL;DR `vnext`가 설계였다면, `lan-10mbps`는 측정이다. 10Mbps 제약을 걸고 `networkAdaptiveController`가 chunk 크기와 속도를 어떻게 줄였다 늘렸다 하는지, `lanEvidenceAdapter`가 전송 품질(지연/재전송/resume)을 어떻게 증거로 남기는지, 모바일 백그라운드 복귀 시 `RESUME_REQUEST`를 어떻게 재전송하는지를 검증한 포크. 코드는 `vnext`와 95% 동일하고, 5%가 증거다.
PonsWarp LAN 10Mbps 설계도 03
— ## 1. 문제 정의 — 왜 10Mbps인가 사무실 Wi-Fi는 300Mbps지만, 엘리베이터·지하 주차장·해외 로밍은 10Mbps다. PonsWarp가 그곳에서 1GB를 보내다 끊기면, `resume`이 10Mbps에서도 동작해야 한다. `vnext`의 듀얼 플레인은 빠르지만, 좁은 길에서 *얼마나* 느려지는지 숫자가 없었다. 그래서 `lan-10mbps` 포크를 만들고, `scripts/lan-evidence.mjs`로 증거를 뽑았다. — ## 2. 설계도 한눈에 — 좁은 세그먼트와 되먹임 가운데 좁은 `10Mbps LAN` 세그먼트 위 두 브라우저. 그 위에 `networkAdaptiveController`가 걸려 있다. * **되먹임 화살표:** `RTT/대역폭 → chunk 크기·속도 조절 → evidence`. RTT가 30ms→200ms로 튀면 controller가 `chunkSize 256KB→64KB`, `sendInterval 5ms→20ms`로 줄인다. 안정되면 다시 늘린다. * **아래:** `lanEvidenceAdapter`와 `scripts/lan-evidence.mjs`가 `evidence 리포트`를 만든다. 지연 히스토그램, 재전송 횟수, `PARTITION_ACK` 간격, `resume` 성공률. * **모바일:** 포그라운드 복귀 시 `RESUME_REQUEST` + `PARTITION_ACK` 재전송 + sender의 `offset` 기반 재전송 역방향 화살표. 백그라운드에서 죽은 소켓을 살리는 게 핵심. 이 포크는 `vnext`의 `contracts/benchmarks`를 그대로 공유한다. 설계가 아니라 *제약*을 바꾼 실험이다. — ## 3. 아키텍처 해부 — 3개 파일이 전부다 “` lan-10mbps/ ├── transfer/networkAdaptiveController.ts ├── adapters/lanEvidenceAdapter.ts └── scripts/lan-evidence.mjs “` * **networkAdaptiveController.ts:** `RTT`와 `bufferedAmount`를 관측해 `chunkSize`와 `sendRate`를 조절하는 피드백 루프. `vnext`의 `transferFlowControl`을 10Mbps에 튜닝한 버전. `highWaterMark`를 1MB→512KB로 낮춰 모바일 OOM을 방지. * **lanEvidenceAdapter.ts:** 전송 중 `evidence`를 정규화해 `{timestamp, rtt, chunkSize, ackLatency, retransmitCount, resumeSuccess}` 형태로 쌓는다. `IndexedDB`에 임시 저장 후 `mjs`가 수집. * **scripts/lan-evidence.mjs:** `tc qdisc`로 10Mbps 지연·패킷 손실 시나리오를 걸고, `Playwright`로 두 브라우저를 띄워 전송을 반복. 결과를 `evidence/2026-08-27/lan-10mbps.json`으로 출력. — ## 4. 로직 딥다이브 — 2개만 깊게 ### 4.1 적응형 컨트롤러 피드백 루프 “`ts if (rtt > 150 || bufferedAmount > 512*1024) { chunkSize = max(32*1024, chunkSize * 0.7); sendInterval *= 1.5; } else if (rtt < 50 && bufferedAmount < 256*1024) { chunkSize = min(256*1024, chunkSize * 1.2); sendInterval *= 0.9; } ``` * `RTT 150ms`와 `bufferedAmount 512KB`가 임계치. 넘으면 즉시 축소, 안정되면 서서히 증가. `vnext`보다 보수적. ### 4.2 모바일 백그라운드 resume 강화 1. `document.visibilitychange` → `hidden`이면 `DataChannel`을 `close`하지 않고 유예. 2. `visible` 복귀 시 `RESUME_REQUEST(runId, lastOffset)`를 3회 재전송 (지수 백오프 100ms, 300ms, 900ms). 3. Sender는 `offset`이 `lastOffset`보다 작으면 중복 조각을 버리고, `lastOffset`부터 재전송. `runId`가 다르면 이전 세션의 늦은 ACK는 무시. --- ## 5. 왜 이 선택인가 | 선택 | 채택 | 버린 대안 | 버린 이유 | |---|---|---|---| | 제약 | 10Mbps 고정 시나리오 | 100Mbps 평균 | 평균은 느린 곳의 실패를 숨김 | | 증거 | lanEvidenceAdapter 정규화 | console.log | 재현 불가, 그래프 불가 | | resume | 포그라운드 3회 재전송 | 1회 재전송 | 모바일은 첫 재전송이 유실될 확률 높음 | --- ## 6. 실패와 복구 * **실패:** 처음엔 `chunkSize`를 고정 128KB로 두고 `sendInterval`만 조절. 그러나 10Mbps에서 128KB는 여전히 커서 재전송 폭증. `chunkSize`도 함께 줄여야 했다. * **복구:** `evidence`가 `retransmitCount`와 `ackLatency`의 상관관계를 보여줌. `chunkSize`를 줄이자 `retransmit`이 1/3으로 감소. --- ## 7. 운영 증거 * `tc qdisc netem rate 10mbit delay 50ms loss 1%`에서 500MB 전송 4회 반복 — 평균 62초, `resume` 100% 성공, `retransmit` 2.1% * `scripts/lan-evidence.mjs` 출력 `evidence/lan-10mbps.json` — 히스토그램 포함, CI에서 `verify` 체인에 통합 --- ## 8. 다음 편 예고 **W4: `ponswarp-grid` — TS로 뽑아낸 엔진.** `PonsWarpEngine(createSession/joinSession)`, `per-piece SHA-256`, `OPFS→IDB→Memory` 폴백, `coordinator`가 어떻게 `ed25519`로 방을 여는지 다룬다. *부록: `blueprints/03-ponswarp-lan-10mbps.png` 프롬프트 `prompts.part1.json#03`, 코드 진입점 `ponswarp-lan-10mbps/transfer/networkAdaptiveController.ts`*

Related

관련 운영 노트

같은 주제에서 이어서 읽기 좋은 글입니다.

  • [Blueprint L3] Pons 포트폴리오 — 의존성 0, 단일 index.html이 오래 가는 이유

    의존성 0, 단일 index.html 41KB. 디자인 토큰 SSOT와 13개 제품 쇼케이스로 만든 정적 포트폴리오가 오래 가는 이유.

  • [Blueprint L2] PonsLink Control Tower — Threads에 dry-run으로 쏘는 이유

    Python Threads 컨트롤타워. cardnews 재사용→생성 폴백, n8n 패치, dry-run 기본 게이트로 안전하게 쏘는 자동발행.

  • [Blueprint L1] PonsLink P2P Room — WebRTC 화상회의를 BFF로 감싼 이유

    React SPA와 Express BFF가 Socket.IO로 시그널링하고, 미디어는 mesh로 가는 2티어. TURN 그랜트와 presence lease로 룸을 만든 화상회의.

댓글

아직 댓글이 없습니다.

현재 이 글의 댓글은 닫혀 있습니다.