파일 전송은 흔한 기능입니다.
그래서 더 오래 붙잡게 됐습니다. 화면에는 버튼 하나와 진행률 하나만 보이지만, 실제로는 연결, 권한, 메모리, 저장, 무결성, 운영이 한꺼번에 엮입니다. PonsWarp는 갑자기 나온 아이디어가 아니라, 몇 년 동안 같은 불편을 다른 이름으로 다시 만진 결과에 가깝습니다.
첫 글에서 영웅담을 만들 생각은 없습니다. KronDelivery, filetransfer, wormhole-file-gate, 그리고 PonsWarp로 이어지는 흐름을 보면, “나는 왜 또 파일 전송인가”라는 질문은 낭만보다 집요한 미해결 문제에 가깝습니다.
🧭 같은 문제로 계속 돌아왔습니다
증거 인덱스에 남겨 둔 전사 저장소는 세 개입니다. KronDelivery는 2021년 11월 30일, filetransfer는 2022년 5월 31일, wormhole-file-gate는 2025년 4월 30일의 기록으로 정리돼 있습니다. 각각의 코드가 지금 모두 같은 깊이로 열려 있지는 않기 때문에, 이 글에서는 확인 가능한 범위를 넘겨 과장하지 않겠습니다.
파일 전송은 개발자에게 묘한 함정입니다. “파일을 선택해서 상대에게 보낸다”라고 쓰면 기능 정의는 끝난 것처럼 보입니다. 그런데 실제 제품에서는 그 문장이 거의 아무것도 보장하지 않습니다. 상대가 온라인인지, 브라우저가 얼마나 버퍼를 견디는지, 모바일이 백그라운드로 내려가도 이어지는지, 저장이 끝난 뒤에야 완료라고 말하는지까지 모두 따져야 합니다.
🏗️ PonsWarp는 처음부터 단일 기능이 아니었습니다
PonsWarp의 루트 커밋은 2025-11-20 ad322f3, 메시지는 feat : first commit입니다. 그날 바로 c647df9의 WebRTC 서비스 개선 및 프로덕션 환경 로깅, 4efb394의 STUN 서버 적용 같은 커밋이 이어집니다. 첫날부터 관심사가 예쁜 전송 화면에만 머물지 않았다는 뜻입니다.
기술 스택도 그 판단을 따라갑니다. React 19, TypeScript 5.9, Vite 7로 화면을 만들고, simple-peer 기반 WebRTC로 직접 전송을 구성하며, StreamSaver와 File System Access API로 저장 경계를 다룹니다. 더 아래에는 Rust/WASM 코어인 pons-core-wasm이 있고, 서버 쪽에는 Rust signaling 서버가 있습니다.
🔍 집착의 중심은 “보냈다”가 아니라 “믿어도 된다”였습니다
전송 완료와 저장 완료는 같은 말이 아니었습니다. PonsWarp의 초반 커밋은 그 차이를 제품이 직접 책임져야 한다는 쪽으로 움직입니다.
2025년 11월 20일 638bc83에는 대용량 파일 다운로드 시 메모리 폭발 방지 기능이 들어갑니다. 다음 날 21dc9ba는 파일 전송 완료 후 수신자 저장까지 대기하는 양방향 핸드셰이크입니다. progress bar가 100%가 되는 순간과 사용자가 파일을 믿어도 되는 순간을 분리해서 보기 시작한 시점입니다.
sender가 청크를 읽고, packet을 만들고, WebRTC data channel로 보내고, receiver가 재정렬과 검증을 거쳐 writer에 넘깁니다. 사용자는 그 사이를 보지 못합니다. 하지만 제품은 그 모든 단계를 알고 있어야 합니다. 특히 수신자가 디스크에 실제로 써내기 전까지는 완료라고 말하면 안 됩니다.
⚙️ 구조는 점점 네 층으로 갈라졌습니다
시리즈 설계 문서에서는 PonsWarp를 네 층으로 나눕니다. 첫째는 Product and UI입니다. App shell, SenderView, ReceiverView, CloudSenderView가 사용자의 선택과 상태를 표현합니다. 둘째는 Browser transfer engine입니다. sender worker, receiver worker, adaptive chunk/batch, AES-256-GCM, backpressure 같은 전송 제어가 여기에 들어갑니다.
셋째는 Storage and recovery입니다. DirectFileWriter, StreamSaver, File System Access API, high/low watermark, partial recovery가 이 층의 언어입니다. 넷째는 Core and backend입니다. pons-core-wasm은 compression, crypto, packet, reordering_buffer, zip64, file_signature, merkle_tree 같은 저수준 책임을 맡고, ponswarp-signaling-rs는 health, ready, websocket, auth, billing, cleanup 같은 운영 책임을 가집니다.
📦 직접 전송만으로는 사용자의 시간을 다 설명할 수 없었습니다
| 경로 | 사용 조건 | 제품 판단 |
|---|---|---|
| Direct SEND / RECEIVE | 양쪽 브라우저가 동시에 온라인 | 최대 크기 제한 없는 직접 전송 |
| Cloud Drop | 받는 사람이 나중에 다운로드 | Cloudflare R2 기반 임시 링크 |
2026년 5월 12일 4847872의 async Cloud Drop, 같은 날 b6f3ea8의 Cloud Drop pricing page, 2026년 5월 14일 3628858의 resumable multipart upload는 직접 전송만으로 전체 사용자 플로우를 설명하기 어렵다는 쪽으로 제품이 이동한 기록입니다.
Cloud Drop은 direct mode의 실패를 감추는 장식이 아닙니다. 둘은 다른 상황을 해결합니다. direct mode는 동시에 온라인인 두 사람의 큰 파일을 빠르고 직접적으로 옮기는 경로입니다. Cloud Drop은 한쪽이 기다릴 수 없을 때 링크라는 비동기 경로를 제공합니다.
🧪 실패 기록이 제품 언어를 바꿨습니다
2025년 11월 29일 4650d02의 메시지는 강합니다. 파일 깨짐 문제 완전 해결 및 대용량 전송 성능 대폭 개선. 이 문장을 승리 선언으로 읽기보다, 그 전에 파일 깨짐이 실제 문제로 존재했고 성능과 무결성이 같이 얽혀 있었다는 증거로 읽는 편이 안전합니다.
전송 서비스에서 파일 손상은 작은 버그가 아닙니다. 사용자가 다시 시도할 수 있더라도 신뢰는 이미 깨집니다. 그래서 PonsWarp는 속도 표시, 저장 완료 핸드셰이크, partial recovery, receiver-side offset, mobile resume 같은 기능을 계속 덧붙였습니다. 제품의 문장도 “빠르게 보냅니다”에서 “중단되거나 늦어져도 상태를 잃지 않습니다” 쪽으로 바뀌어야 했습니다.
🧾 지금 돌아보면, 이것은 전송 프로젝트가 아니라 경계 프로젝트였습니다
PonsWarp를 파일 전송 앱이라고 부르는 건 틀리지 않습니다. 하지만 조금 부족합니다. 실제로 붙잡은 것은 브라우저와 디스크의 경계, sender와 receiver의 속도 차이, 온라인과 오프라인의 경계, 데모와 운영의 경계, 완료 표시와 실제 저장 완료의 경계였습니다.
계속 파일 전송 프로젝트를 만든 이유도 이제는 조금 분명합니다. 파일 전송은 기능 목록에서는 작게 보이지만, 제품을 만드는 데 필요한 거의 모든 판단을 한 번씩 요구합니다. 사용자는 단순한 버튼을 기대하지만, 구현자는 연결성, 메모리, 저장, 무결성, 비용, 운영을 모두 통과해야 합니다. 그 간격이 계속 신경 쓰였고, PonsWarp는 그 간격을 가장 끝까지 밀어붙인 버전입니다.
content/ponswarp-retrospective/series-plan.md — PonsWarp 회고 시리즈의 서비스 분석 기준과 4층 구조content/ponswarp-retrospective/evidence-index.md — KronDelivery, filetransfer, wormhole-file-gate, PonsWarp 커밋 계보PonsWarp/README.md:26-58 — direct mode와 Cloud Drop의 제품 정의, 기능 구조PonsWarp/README.md:60-94 — sender worker, receiver worker, DirectFileWriter, signaling, Rust/WASM 코어 구성PonsWarp commits — ad322f3, c647df9, 638bc83, 21dc9ba, 4650d02, 4847872, b6f3ea8, 3628858'개발 회고' 카테고리의 다른 글
| [PonsWarp] - wormhole-file-gate는 무엇을 시험한 프로젝트였나 (1) | 2026.06.24 |
|---|---|
| [PonsWarp] - `KronDelivery`와 `filetransfer`에서 이미 드러난 집착 (0) | 2026.06.24 |
| [PonsWarp] - 브라우저 앱인데 왜 코어가 Rust인가 (0) | 2026.06.24 |
| [PonsWarp] - 암호화와 성능 최적화가 충돌하던 지점 (0) | 2026.06.24 |
| [PonsWarp] - reordering buffer를 WASM으로 옮긴 이유 (2) | 2026.06.24 |




