PonsWarp가 packet checksum과 save-complete handshake까지 붙였을 때, 얼핏 보면 파일 무결성 문제는 거의 닫힌 것처럼 보입니다.
하지만 packet 하나가 맞다는 사실은 전체 파일의 구조가 맞다는 뜻이 아니고, 저장이 끝났다는 사실은 저장된 파일이 기대한 산출물이라는 뜻이 아닙니다. 그래서 Season 3의 pons-core-wasm 쪽에는 Merkle tree와 file signature가 같이 등장합니다.
🧱 packet-level check는 어디까지 책임졌나
현재 시리즈에서 반복해서 확인한 packet 경계는 분명합니다. constants.ts는 FileIndex, ChunkIndex, Offset, DataLen, Checksum을 합쳐 HEADER_SIZE = 22로 설명하고, pons-core-wasm/src/packet.rs의 PacketEncoder는 payload CRC32를 header에 기록합니다. receiver 쪽 PacketDecoder::verify는 길이와 checksum을 다시 계산해 맞지 않으면 false를 반환합니다.
브라우저 receiver worker도 packet byte length가 header가 말한 크기와 다르면 corrupt packet으로 보고, WASM 검증 또는 fallback CRC32 비교를 사용합니다. 다만 packet-level check는 이름 그대로 packet 하나의 계약입니다. packet들이 각자 맞아도 전체 파일에서 빠진 구간이 있는지, 부분 검증을 나중에 다시 증명할 수 있는지, 최종 산출물이 기대 형식인지까지 모두 말해 주지는 않습니다.
⚙️ save-complete도 최종 무결성의 동의어는 아니었다
21dc9ba가 붙인 양방향 핸드셰이크는 sender가 마지막 chunk를 보낸 사건과 receiver가 저장을 끝낸 사건을 분리했습니다. post-22의 현재 코드 근거처럼 receiver는 DirectFileWriter.writeChunk() Promise가 끝난 뒤 ACK를 보내고, partition 경계에서는 writer.waitForIdle() 이후 PARTITION_ACK를 보냅니다. 마지막에는 onComplete(actualSize)가 DOWNLOAD_COMPLETE로 이어집니다.
save-complete는 저장 완료의 신호이지, 저장된 바이트가 이후 어떤 부분 검증 경로를 제공하는지 또는 파일 형식 경계가 맞는지까지 보장하지는 않습니다.
🌳 Merkle tree는 전체 파일 신뢰를 부분 증명으로 바꿨다
pons-core-wasm/src/merkle_tree.rs는 post-11 QA에서 이미 대용량 파일 부분 무결성 검증과 proof verification의 근거로 묶였습니다. checksum은 packet payload가 header와 맞는지를 봅니다. Merkle tree는 chunk hash들을 묶어 상위 hash를 만들고, root까지 이어지는 증명 경로를 통해 특정 부분이 전체 파일의 약속된 구조 안에 있는지를 확인합니다.
대용량 전송에서는 이 차이가 큽니다. 전체 파일을 매번 처음부터 끝까지 다시 읽고 비교하는 방식은 브라우저 전송 제품에서 부담이 큽니다. 반면 Merkle proof는 특정 chunk와 sibling hash 경로를 통해 root와의 관계를 확인할 수 있습니다. partial recovery도 같은 방향입니다. 복구된 조각이 전체 파일의 어느 위치와 어떤 hash 관계를 갖는지 확인할 언어가 필요하기 때문입니다.
🖋️ file signature는 최종 산출물의 경계를 따로 세웠다
file signature는 Merkle tree와 또 다른 위치에 있습니다. packet이 맞고, 저장이 끝났고, Merkle proof가 특정 조각의 관계를 설명해도, 사용자가 받은 최종 산출물이 기대한 형식의 파일인지에 대한 질문이 남습니다. post-11에서 ZIP totalSize와 실제 ZIP byte length 차이를 다룬 이유도 여기에 있습니다.
이 글에서는 저장소 근거 이상으로 특정 signature 알고리즘을 invent하지 않습니다. 확인 가능한 것은 e589cf2가 압축, Merkle Tree, 파일 서명 기능을 같은 커밋 제목으로 묶었고, 시리즈 설계 문서가 pons-core-wasm 책임 목록에 file_signature와 merkle_tree를 함께 둔다는 점입니다. 압축과 ZIP64가 들어오면 최종 산출물의 형식 경계가 더 중요해지고, 그 경계를 코어가 다뤄야 합니다.
🔐 신뢰 모델은 여러 층으로 닫혀야 했다
PonsWarp의 신뢰 모델은 단일 보안 장치 하나로 설명하기 어렵습니다. UI는 완료와 오류를 사용자에게 말하고, browser transfer engine은 WebRTC DataChannel과 sender/receiver worker를 다룹니다. storage/recovery 층은 DirectFileWriter, reordering buffer, partial recovery를 맡습니다. core 층은 packet, CRC32, Merkle tree, file signature 같은 검증 언어를 담당합니다.
🧭 지금 돌아보는 판단
이 시점의 판단은 꽤 보수적입니다. 대용량 브라우저 전송에서 빠른 경로를 만드는 일만큼, 실패했을 때 조용히 성공처럼 보이지 않게 만드는 일이 중요했습니다. e589cf2의 Merkle Tree와 파일 서명은 그 보수성의 코어 버전입니다.
좋은 파일 전송 제품은 사용자가 내부 검증 단어를 몰라도 됩니다. 사용자는 CRC32, proof path, root hash, file signature를 보려고 앱을 여는 것이 아닙니다. 사용자는 받은 파일을 열고, 그 파일을 업무나 기록에 써도 된다고 믿고 싶어 합니다. PonsWarp가 Merkle tree와 file signature를 넣은 이유는 바로 그 단순한 문장을 내부적으로 감당하기 위해서였습니다.
PonsWarp commit e589cf2 — 압축, Merkle Tree, 파일 서명 기능 추가PonsWarp commit 21dc9ba — 수신자 저장 완료까지 대기하는 양방향 핸드셰이크PonsWarp commit b185563 — partial file을 성공처럼 저장하지 않고 recover 가능한 전송으로 다루는 후속 판단PonsWarp/src/utils/constants.ts — HEADER_SIZE, FileIndex, ChunkIndex, Offset, DataLen, Checksum 경계pons-core-wasm/src/packet.rs — PacketEncoder CRC32 기록과 PacketDecoder 검증PonsWarp/src/workers/file-receiver.worker.ts — packet length 검증, WASM verification, CRC32 fallback 처리PonsWarp/src/services/directFileWriter.ts — write 완료, writer idle, actualSize, finalize 계층의 저장 완료 경계pons-core-wasm/src/merkle_tree.rs:1-6, 232-245 — 대용량 파일 부분 무결성 검증과 proof verificationcontent/ponswarp-retrospective/series-plan.md:273-281 — Season 3의 Rust/WASM 코어 분리와 post-27 위치'개발 회고' 카테고리의 다른 글
| [PonsWarp] - 암호화와 성능 최적화가 충돌하던 지점 (0) | 2026.06.24 |
|---|---|
| [PonsWarp] - reordering buffer를 WASM으로 옮긴 이유 (2) | 2026.06.24 |
| [PonsWarp] - zero-copy와 메모리 경계 문제 (0) | 2026.06.24 |
| [PonsWarp] - ZIP64가 필요해진 진짜 이유 (0) | 2026.06.24 |
| [PonsWarp] - `pons-core-wasm`를 따로 만든 이유 (0) | 2026.06.24 |




