post-22에서 성능보다 무결성이 먼저라는 판단까지 왔다면, 다음 질문은 자연스럽습니다.
왜 그 책임을 PonsWarp 앱 안의 TypeScript 코드로 계속 들고 가지 않고 pons-core-wasm이라는 별도 코어로 분리했을까. 대답은 “JS가 느려서 Rust로 바꿨다”보다 좁고, 그래서 더 중요합니다. 분리의 핵심은 속도 언어가 아니라 경계 언어였습니다.
🧭 분리는 언제 필요해졌나
시리즈 evidence index는 pons-core-wasm의 root를 2025-12-04 15aef19 feat: 초기 pons-core-wasm 프로젝트 설정으로 기록합니다. 직전 흐름을 보면 이 날짜가 우연처럼 보이지 않습니다. 11월 말에는 청크 순서 역전, 중복 완료, 파일 깨짐, 파이프라인 병렬화, 멀티 채널, backpressure가 연달아 등장했습니다.
series-plan.md도 PonsWarp를 Product/UI, Browser transfer engine, Storage/recovery, Core/backend로 나눕니다. Core and backend 아래의 pons-core-wasm 책임 목록은 compression, crypto, fec, packet, reordering_buffer, zero_copy_pool, zip64, file_signature, merkle_tree입니다. 화면 컴포넌트나 브라우저 이벤트가 아니라, 바이트가 어떤 구조로 만들어지고 검증되고 다시 순서대로 놓이는지를 다루는 목록입니다.
그래서 별도 모듈의 필요성은 “성능이 부족했다” 하나로 설명하기 어렵습니다. 성능도 한 축이지만, 더 큰 이유는 책임의 성격이 달라졌기 때문입니다. React 상태와 WebRTC channel 상태는 브라우저 현실과 맞물리고, packet header, CRC, ZIP64, reordering buffer는 더 결정적이고 재사용 가능한 규칙이어야 합니다.
🧱 `pons-core-wasm`으로 내려간 책임
가장 분명한 책임은 packet입니다. 이전 글들이 정리한 현재 구조에서 packet header는 FileIndex, ChunkIndex, Offset, DataLen, Checksum을 담는 22바이트 경계로 설명됩니다. pons-core-wasm/src/packet.rs의 PacketEncoder는 payload CRC32를 header에 기록하고, PacketDecoder::verify는 길이와 checksum을 다시 계산해 검증합니다.
두 번째는 대용량 파일 형식과 압축 경계입니다. evidence index에는 2025-12-05 1b6fb15 feat(zip64): 4GB 이상 파일 지원을 위한 ZIP64 스트리밍 압축 기능 추가와 2025-12-05 7b0301d feat(sender): WASM ZIP64 압축으로 마이그레이션이 이어서 기록됩니다. ZIP64는 단순 UI 기능이 아니라, 큰 파일을 어떤 포맷 경계로 스트리밍할 것인지의 문제입니다.
세 번째는 순서와 메모리 경계입니다. 2025-12-06 58e6b89는 수신측 패킷 재정렬 버퍼를 WASM으로 마이그레이션한 커밋입니다. post-20에서 정리한 현재 구조도 src/services/wasmReorderingBuffer.ts가 WasmReorderingBuffer를 먼저 초기화하고, 실패하면 JS ReorderingBuffer fallback으로 전환한다고 설명합니다. post-15는 ZeroCopyPacketPool이 WASM 선형 메모리 안의 사전 할당 버퍼로 JS/WASM 경계 복사를 줄이려는 구조라고 정리했습니다.
네 번째는 후속 신뢰 장치입니다. evidence index의 2025-12-08 e589cf2는 압축, Merkle Tree, 파일 서명 기능 추가를 기록하고, 2025-12-08 7fe0ca1은 암호화 지원 Zero-Copy Pool 구현을 기록합니다. 즉 코어는 단일 CRC 함수 하나가 아니라, 전송 제품이 바이트를 믿기 위해 필요한 여러 저수준 규칙의 집합으로 커졌습니다.
⚠️ JS/browser land에 남아야 했던 것
pons-core-wasm이 생겼다고 해서 PonsWarp가 브라우저 앱이 아니게 된 것은 아닙니다. 사용자가 보는 SenderView와 ReceiverView, 파일 선택, 진행률, 완료 표시, 오류 메시지, QR/session 흐름은 여전히 JS와 React의 책임입니다.
WebRTC DataChannel 운용도 브라우저 쪽에 남습니다. channel open/close, bufferedAmount, backpressure, worker message protocol, peer 상태는 Rust 코어가 단독으로 해결할 수 있는 문제가 아닙니다. post-22가 정리한 것처럼 DataChannel의 bufferedAmount는 sender 로컬 큐일 뿐 receiver 저장 완료가 아닙니다.
저장 계층도 마찬가지입니다. DirectFileWriter, StreamSaver, File System Access API, OPFS fallback, write buffer watermark는 사용자의 브라우저와 운영체제 조건에 강하게 묶여 있습니다. WASM reordering buffer가 순서 경계를 도와도, 실제 저장을 어떤 API로 끝까지 써낼지는 브라우저 land의 책임입니다.
🔄 별도 저장소/모듈이라는 선택의 의미
pons-core-wasm이 앱 내부 유틸 폴더가 아니라 별도 코어로 보이는 이유는 책임의 재사용성과 변경 리듬이 달랐기 때문입니다. series-plan.md에서 Season 3 자체가 Rust/WASM 코어 분리로 잡혀 있고, post-24 뒤에는 ZIP64, zero-copy, Merkle tree/file signature, reordering buffer, 암호화와 성능 충돌, “브라우저 앱인데 왜 코어가 Rust인가”가 이어집니다.
별도 경계가 있으면 PonsWarp 앱은 사용자 흐름과 브라우저 현실을 다룰 수 있고, 코어는 byte-level invariant를 다룰 수 있습니다. packet이 어떻게 생겼는지, checksum을 어디에 넣는지, ZIP64 스트림이 어떤 조건을 만족해야 하는지, reordering buffer가 어떤 offset을 기다리는지는 UI 변경과 독립된 규칙이 됩니다.
UI는 “WASM이 있으니 완료”라고 말할 수 없습니다. receiver writer가 실제로 저장을 끝내고, 크기와 순서가 맞아야 완료입니다.
🧭 지금 돌아보는 판단
pons-core-wasm을 따로 만든 이유는 PonsWarp가 브라우저 앱이기를 포기해서가 아닙니다. 오히려 브라우저 앱으로 남아야 하는 부분과 브라우저 앱 안에 두면 계속 흔들리는 부분을 분리하기 위해서였습니다.
JS/browser land는 사용자, 네트워크, 저장 API처럼 변수가 많은 세계를 맡습니다. Rust/WASM core는 packet, checksum, compression, reordering, zero-copy, Merkle tree, file signature처럼 반복 가능하고 검증 가능한 세계를 맡습니다. 이 경계가 생기면서 PonsWarp는 “빠르게 보내는 화면”에서 “받은 바이트를 믿을 수 있는 제품” 쪽으로 한 단계 더 내려갈 수 있었습니다.
별도 pons-core-wasm은 기술 과시가 아니라 책임 분리였습니다. 빠른 UI와 복잡한 브라우저 호환성은 JS가 계속 다루고, 파일 신뢰를 결정하는 바이트 규칙은 독립된 코어가 다룹니다. 이 경계가 있었기 때문에 다음 글들의 ZIP64, zero-copy, Merkle tree, reordering buffer 이야기가 각각 독립된 주제로 설 수 있습니다.
content/ponswarp-retrospective/evidence-index.md:17-21 — pons-core-wasm root와 핵심 구간 기록content/ponswarp-retrospective/evidence-index.md:79-87 — WASM 코어 분리 관련 커밋 목록content/ponswarp-retrospective/series-plan.md:137-148 — Core/backend 계층의 pons-core-wasm 책임 목록content/ponswarp-retrospective/series-plan.md:208-216 — ZIP64, reordering buffer, merkle tree, file signature, zero-copy, crypto 목록content/ponswarp-retrospective/series-plan.md:273-281 — Season 3 Rust/WASM 코어 분리 글 목록content/ponswarp-retrospective/drafts/post-11.txt:39-45 — packet header, CRC32, PacketEncoder/PacketDecoder, Merkle Tree/file signature 근거content/ponswarp-retrospective/drafts/post-15.txt:35-39 — ZeroCopyPacketPool과 WASM 선형 메모리 경계 근거content/ponswarp-retrospective/drafts/post-20.txt:35-39 — WasmReorderingBuffer 우선 초기화와 JS fallback 근거content/ponswarp-retrospective/drafts/post-22.txt:49-51 — sender/receiver worker의 pons-core-wasm 사용과 core 책임 요약'개발 회고' 카테고리의 다른 글
| [PonsWarp] - zero-copy와 메모리 경계 문제 (0) | 2026.06.24 |
|---|---|
| [PonsWarp] - ZIP64가 필요해진 진짜 이유 (0) | 2026.06.24 |
| [PonsWarp] - JS로 버티다 Rust로 내려간 순간 (0) | 2026.06.24 |
| [PonsWarp] - 빠른 전송보다 무결성이 먼저라는 판단 (0) | 2026.06.24 |
| [PonsWarp] - partial file recovery를 왜 늦게 붙였나 (0) | 2026.06.24 |




