[WarpInfra] 데이터 그리드 시리즈를 시작하며 — desktop과 grid, 그리고 이름
커밋 175개를 시간순으로 읽으면 아무것도 남지 않는다. 이건 내가 직접 해 본 결과다. ponswarp-desktop의 146개 커밋을 날짜순으로 훑으면 "설정 수정", "버그 수정", "리팩토링", "docs 업데이트"가 반복되고, 정작 이 제품이 왜 두 번이나 방향을 바꿨는지는 커밋 제목 어디에도 없다. 방향 전환은 커밋 한 개로 일어나지 않았다. 어느 날 갑자기 WASM을 버린 게 아니라, 몇 주에 걸친 실패 신호가 쌓인 뒤 8aabffc 같은 전환 커밋으로 도장을 찍은 것뿐이다. 시간순 읽기는 그 신호 축적을 전부 지나친다.
실제로 커밋 메시지에서 그 신호 축적을 읽을 수 있다. WASM 경로의 문제는 한 줄로 남지 않았다. 오류가 경계에서 뭉개진다는 언급, 연결 상태를 이벤트 주도로만 전이시키기로 한 결정(9253ddb), 그리고 결국 의존성 제거(8aabffc). 개별 커밋은 사소해 보이지만 나열하면 명확한 패턴이 된다 — WASM이라는 선택이 성능·오류 추적·상태 제어 세 곳에서 동시에 발목을 잡았고, 그래서 네이티브로 갈아탔다. 시간순 로그에서 이건 "버그 수정 3개"로 밖에 안 보인다. 설계 순서로 보면 하나의 서사로 읽힌다. 이 시리즈는 그 서사를 복원하는 작업이다.
그래서 이 시리즈는 시간순을 버렸다. 175개 커밋을 설계 → 구현 → 남은 일 순서로 다시 배열하고, 각 전환점에서 "그때 무엇이 깨졌고, 무엇을 기각했고, 무엇을 남겨 뒀는지"를 기준으로 재구성한다. 이 글이 그 지도다.
먼저 이름부터 정리한다
이 제품을 찾는 사람이 가장 먼저 빠지는 함정이 이름이다. "infrawarp"라는 이름의 저장소는 어디에도 없다. 내부 문서와 커밋에서 이 제품의 정식 이름은 WarpInfra고, 코드는 두 개의 저장소에 나뉘어 살고 있다.
| 레포 | 역할 | 커밋 수 |
|---|---|---|
ponswarp-desktop | 본체 — Warp Node, warp CLI, QUIC piece 경로, Tauri GUI | 146 |
ponswarp-grid | 브라우저/공개 그리드 엔진 — coordinator, room-first mesh | 29 |
이름이 하나고 코드가 둘인 구조는 사고 실패가 아니라 실행 환경의 차이가 만든 결과다. 데스크톱은 QUIC 소켓을 직접 열 수 있고, 브라우저는 WebRTC DataChannel 말고 선택지가 없다. 수송체가 다르면 테스트도, 배포도, 패키징도 갈라진다. 브라우저용 코드를 데스크톱 레포에 얹어 두면, 브라우저 변경 하나 때문에 데스크톱 릴리스를 다시 해야 하는 상황이 반복된다. 두 세계를 한 레포에 얹는 대신 엔진을 분리한 것은 비용 계산의 결과였다. 이 분리의 전체 판단은 S3의 그리드 엔진 편에서 다시 다룬다.
기존 블로그에 PonsWarp의 브라우저 파일 전송 이야기는 이미 많다. 이 시리즈는 거기서 멈추지 않고 세 가지를 더 간다. 데스크톱 네이티브 전송, 사내 인트라넷 데이터 그리드, 그리고 제어면(Control)과 데이터면(Data Plane)의 분리. 특히 세 번째는 이 시리즈 전체를 관통하는 원칙이라서, 이름 정리 다음으로 가장 먼저 짚어 둔다.
커밋 이력이 보여준 세 개의 전환점
146+29개 커밋을 설계 순서로 다시 읽으면 세 지점에서 제품의 방향이 바뀐다.
- 웹 분리 — 데스크톱이 웹과 갈라져 별도 저장소가 됐다 (
2f05196첫 커밋). 한 레포에서 웹과 네이티브를 같이 굴리던 시절의 빌드·테스트 비용이 분리의 직접 원인이었다. 변경 하나를 검증하려면 두 환경을 모두 돌려야 했고, 릴리스 주기가 서로를 끌어당겨 느려졌다. - 네이티브 전환 — WASM 전송 경로를 버리고 네이티브 QUIC로 갈아탔다 (
8aabffc). "웹과 같은 코어를 쓴다"는 이상이 데스크톱에서 성능·오류 추적·상태 제어 세 곳에서 동시에 무너졌다. 앞서 본 "연결됨 표시와 실제 전송의 불일치"가 이 무너짐의 대표 사례다. - 그리드 승격 — 단일 피어 전송을 넘어 여러 Node가 조각을 나눠 받는 그리드로 확장됐다. 2026-07-18 기준 Phase A는 약 95%까지 왔다. 한 파일을 한 피어에게 받는 구조에서, 열 대의 머신이 조각을 나눠 받는 구조로 가는 것은 기능 추가가 아니라 제품 정의의 변경이었다.
세 전환은 각각 독립적인 사건처럼 보이지만, 뒤집어 보면 하나의 원칙이 점점 선명해지는 과정이다. "파일 바이트는 제어면을 지나지 않는다." 웹을 분리한 것도, WASM을 버린 것도, coordinator 라우트를 줄인 것도 이 한 줄의 귀결이다. 중앙이 바이트를 다루는 순간 확장성과 장애 격리가 함께 무너진다는 판단이 반복해서 나오고, 결국 원칙의 언어로 정리된다. 이 원칙이 이 시리즈의 척추니까, 지도에서 가장 먼저 적어 둔다.
원칙을 문장으로 먼저 적고 구현이 따라오는 구조는, 반대로 구현이 먼저 있고 원칙을 나중에 붙이는 구조와 결과가 많이 다르다. 후자의 경우 원칙은 이미 만들어진 것을 정당화하는 수사가 되기 쉽다. 전자의 경우 원칙이 구현을 걸러내는 필터가 된다. coordinator에 파일 릴레이 라우트를 추가하자는 제안이 들어오면 기능의 유용성을 논하기 전에 원칙 위반 여부를 먼저 본다. 이 시리즈에서 채택/기각 표가 매 편 등장하는 이유가 이것이다. 기각된 안을 기록해 두지 않으면 같은 제안이 다른 이름으로 몇 달 뒤 다시 온다.
시리즈 지도
14편을 네 구간으로 나눴다. 각 구간은 커밋 이력의 성격이 다르다.
textS0 프롤로그 (1) 지도·이름·경계 S1 설계 (4) 니치·플레인 분리·로드맵·CLI-first S2 구현 코어 (4) QUIC·스트리밍·piece 스케줄·Phase A S3 구현 그리드 (3) grid 엔진·coordinator·direct/grid 분기 S4 검증·잔여 (2) RC1 게이트·남은 일
S1은 결정의 기록이다. 무엇을 만들지 않기로 했는지(니치), 무엇을 coordinator가 하지 못하게 할지(플레인 분리), 무엇을 나중으로 미루기로 했는지(컴퓨트 그리드)가 전부 부정문으로 쓰여 있다. 기능 목록이 아니라 기각 목록으로 시작하는 로드맵은 드물지만, 무엇을 안 만들지 정하지 않으면 구현 단계에서 매주 다시 논쟁하게 된다. 니치 편에서 다룰 "레지스트리 옆 CLI release get"이라는 좁은 정의도, 넓게 보면 경쟁 제품의 기능 목록 하나하나에 대한 거절의 기록이다.
S2와 S3은 구현의 기록이다. 여기서는 커밋 해시를 그대로 인용한다 — 설계 문서가 아니라 실제로 어떤 순서로 부품이 붙었는지가 이야기이기 때문이다. zip 스트리밍 버그, rarest-first 스케줄러, 브라우저 Blob 한계 같은 사건들이 여기에 있다. 특히 S2의 사건들은 전부 "이론상 되는데 운영상 안 되는" 부류다. WASM은 표준이고, zip은 검증된 포맷이고, 순차 다운로드는 정확한 방식이다. 그런데 데스크톱에서 대용량을 실제로 굴리면 전부 다른 모습으로 무너진다. S3은 그리드 쪽이다. ponswarp-grid의 29개 커밋은 짧지만 밀도가 높다. 브라우저라는 제약 안에서 coordinator 표면을 어떻게 줄였고, 사용자에게 경로 선택을 강요하지 않는 방법이 여기 있다.
S4는 검증의 기록인데, 이 시리즈에서 가장 솔직한 부분이다. RC1 게이트 두 개가 아직 닫히지 않았다. 마지막 편의 백로그는 우선순위가 원칙으로 고정돼 있어서, 시간이 지나도 기준이 흔들리지 않는다.
이 기록을 읽는 방법
이 시리즈는 성공담이 아니라 판단 기록이다. 완성된 제품의 회고가 아니라, Phase A 95% 지점에서 멈춰 있는 제품의 중간 보고에 가깝다. 그래서 각 편의 끝에는 "남은 구멍"을 반드시 적는다. mTLS, 20GB multi-host 실측, 온프레 Control MVP 같은 구멍들은 감쪽가이 가리는 게 아니라 백로그 항목으로 명시한다. 설계가 남긴 약속과 구현이 닿은 선 사이의 거리를 매 편 측정해 두는 것이, 나중에 이 기록을 다시 읽을 때 유일하게 도움이 되는 방식이기 때문이다.
이 기록에 등장하는 근거의 종류도 미리 정리해 둔다. 첫째는 커밋 해시다. 2f05196, 8aabffc, 785ed4a 같은 해시는 "그때 그랬다"는 기억이 아니라 지금도 checkout할 수 있는 증거다. 둘째는 설계 문서다. docs/01-warp-infra-vision-and-naming.md, RC1 게이트 문서처럼 판단 당시의 언어가 고정돼 있는 자료들이다. 셋째는 상태 스냅샷이다. "2026-07-18 기준 Phase A 95%" 같은 숫자는 당시 기준일이 명시된 측정값이지, 지금도 유효한 주장이 아니다. 시리즈 전체에서 이 세 종류의 근거를 섞지 않고 구분해 쓰려고 했다. 기억은 근거가 아니기 때문이다.
이 시리즈가 다루지 않는 것
경계도 미리 그어 둔다. 이 시리즈는 브라우저 파일 전송의 일반론 — WebRTC DataChannel의 기초, backpressure의 개념 같은 주제 — 를 강의하지 않는다. 그런 내용은 이미 이전 블로그 글들에 있다. 또한 Resilio나 Aspera 같은 경쟁 제품의 비판이 목적도 아니다. 경쟁 분석은 S1의 니치 편에서 "우리가 만들지 않을 것"의 근거로만 등장한다.
그리고 가장 중요한 경계 하나. 이 시리즈의 숫자들은 전부 내부 개발 기준의 기록이지, 제품의 성능을 약속하는 벤치마크가 아니다. "Phase A 95%"는 내부 완성도 스냅샷이고, 20GB는 실측 전까지는 목표치다. 이 구분이 흐려지는 순간 개발 기록이 마케팅 문서로 변질된다. 그래서 RC1 원칙에 "20GB 실제 다중 머신 전송 증거가 없으면 RC1로 판정하지 않는다"가 들어가 있는 것이다.
중간 상태의 기록이 가지는 또 하나의 가치는, 판단이 틀렸을 때 되돌아갈 지점이 명확하다는 것이다. 완성된 뒤의 회고는 결과를 보고 이유를 지어내기 쉽다. 95% 지점의 기록은 "지금 이 판단이 맞는지는 20GB 실측이 답할 것"처럼 미해결을 미해결로 남긴다. 이 시리즈를 시간이 지난 뒤 다시 읽게 될 때, 가장 먼저 확인할 것은 이 편의 세 전환점이 예측대로였는지다.
이제 S1부터, 무엇을 만들지 않기로 했는지부터 시작한다.
이 시리즈
- 이전: (시작)
- 다음: 니치, 레지스트리 옆 CLI release get
- 목차: PonsWarp 개발 회고