됩니다. 지금 방식은 웹서버 디스크를 씁니다 — 그걸 없애겠습니다. 핵심 발상 : 브라우저 업로드와 에이전트 다운로드를 동시에 연결 해서 흘려보냅니다. 디스크를 아예 안 씁니다. 파일 생성됨, 명령 실행함 파일 생성됨, 명령 실행함 UI를 스트리밍 방식으로 바꾸고 목록 자동 갱신을 넣겠습니다. Switch the UI to streaming transfer with live progress Switch the UI to streaming transfer with live progress 실제로 디스크를 안 쓰는지 검증하겠습니다. Verify pass-through streaming uses no disk and constant memory Verify pass-through streaming uses no disk and constant memory 600MB를 흘렸는데 메모리 103MB, 디스크 0입니다. 문서화하고 패키징하겠습니다. 명령 실행함, 파일 읽음 명령 실행함, 파일 읽음 됩니다. 웹서버 디스크를 아예 안 씁니다. 구조 브라우저 ──업로드 스트림──┐ ├─ 웹서버(메모리 통과) ──> 노드 노드 ─────GET 요청────────┘ 브라우저 요청 본문을 소비하지 않고 등록해두고, 노드에 virt.iso.fetch 를 보냅니다. 노드가 GET하면 그 자리에서 브라우저 스트림을 응답으로 이어 붙입니다. 중간 버퍼가 없습니다. 진행률이 정확해집니다 백프레셔 덕에 브라우저 전송 속도가 노드 수신 속도에 자동으로 맞춰집니다. 노드가 느리면 브라우저도 느려집니다. 그래서 업로드 진행률이 곧 노드까지의 실제 전송 진행률 입니다. 별도 채널이 필요 없습니다. 전송률(MB/s)도 같이 나오고, 100% 후에는 "노드가 저장하고 검증하는 중"으로 바뀝니다. 검증 — 600MB 전송량 600 MB 소요 6.3초 (96 MB/s) 해시 일치 OK 최대 RSS 103 MB ← 600MB 를 흘렸는데도 일정 디스크 임시 파일 없음 메모리가 파일 크기와 무관합니다. 3GB든 10GB든 같습니다. 목록은 전송 성공 시 자동 갱신됩니다. ⚠ 확인하실 것 — pm2 실행 모드 두 요청이 같은 Node 프로세스 에 들어와야 합니다. sh pm2 describe mihosrc-web | grep -i "exec mode" fork_mode → 그대로 쓰시면 됩니다 cluster_mode → .env.local 에 ISO_STREAM_MODE=disk 필요 cluster면 워커가 갈릴 수 있어서, 그 경우 기존 디스크 경유 방식으로 자동 폴백하도록 스위치를 남겨뒀습니다. 릴레이를 통하지 않은 이유 말씀하신 "relay 연결을 통해서"는 TUNNEL_* 프레임이 필요한데, 에이전트에 타입만 선언돼 있고 구현이 없습니다. 그리고 운영 릴레이( miho_relay )에도 대용량 전송 경로를 넣어야 합니다. 지금 방식은 그 둘을 안 건드리고도 디스크 0, 정확한 진행률 을 얻습니다. 릴레이 경유가 주는 추가 이득은 "웹서버를 아예 안 거침" 하나인데, 노드가 인바운드를 안 여는 구조에서는 어차피 중계자가 필요합니다. TUNNEL_* 을 제대로 구현하면 터미널·VNC까지 같이 얻으니, 그건 별도로 하시는 게 낫습니다.