멈췄던 파일을 다시 받는다는 말에는 두 가지 일이 섞여 있었다. 살아 있는 전송을 이어 가는 일과 이미 끝난 전송의 주소로 새 전송을 만드는 일이다. 북극성에서는 재개와 다시 시도를 분리했다. 버튼의 모양보다 지금 유지하고 있는 네이티브 객체가 있는지가 기준이었다.
재개는 살아 있는 객체에 보낸다
ActiveDownloads는 record와 네이티브 item을 함께 보관한다. 진행 중이며 멈춘 상태이거나, interrupted 상태에서 item이 canResume이라고 알려줄 때 재개가 가능하다. 버튼에 남은 canResume 표시만 믿지 않고 perform에서 실제 상태를 다시 갱신한다.
사용자가 재개를 눌렀어도 다른 프로필의 항목이면 제어를 보내지 않는다. 이미 완료·취소된 item은 active 목록에서 빠져 옛 버튼으로 되살릴 수 없다. 여기서 재개는 새 URL을 추측해서 내려받는 동작이 아니라 현재 네이티브 객체에 resume을 호출하는 동작이다. 실제 이어 받기의 방식은 서버와 네이티브 전송 기능의 조건을 따른다.
재시작 후 목록은 살아 있는 전송이 아니다
앱을 닫았다 열면 다운로드 기록을 복원할 수 있지만 네이티브 item까지 같은 상태로 살아나는 것은 아니다. restoredDownloads는 진행 중과 일시정지였던 기록을 중단으로 바꾼다. 저장된 canResume 같은 런타임 제어 표시도 그대로 믿고 복원하지 않는다.
이름·경로·프로필·기록 형식을 검사하고 최근 범위의 정상 항목만 읽는다. 중단 기록을 완료로 바꾸거나 프로그램이 알아서 새 전송을 시작하지 않는다. 사용자에게는 파일을 다시 받을 선택이 남지만 그것은 다음 동작의 문제다. 목록 복원과 실행 복구를 구별하면 재시작한 화면이 무엇을 약속하는지 훨씬 명확해진다.
다시 시도는 종료된 전송에서 새 기록을 만든다
다시 시도는 실패·취소·중단 같은 종료 상태이며 현재 제어 가능한 전송이나 재시도 요청이 남아 있지 않을 때 허용한다. 저장된 원본 HTTP(S) 주소가 필요하다. 같은 item의 일시정지 버튼을 재시도라고 바꿔 부르지 않는다. 원래 탭으로 돌아가 페이지 동작 전체를 재생하는 기능도 아니다.
새로 받은 파일은 별도 record를 갖고 원래 record는 취소나 실패였다는 이력을 유지한다. 기존 결과를 고쳐서 처음부터 성공했던 것처럼 만들지 않는 것이다. 파일이 실제로 내려오면 일반 다운로드의 저장 위치·중복 이름 방지·제어 흐름을 사용한다. 다시 시도 버튼을 눌렀다는 사실만으로 완료를 표시하지 않는다.
주소가 있어도 언제나 다시 받을 수 있지는 않다
blob 주소처럼 페이지 안에서 생성한 자료나 원본 주소를 저장하지 않았던 예전 기록은 이 경로로 다시 요청하지 않는다. URL에 사용자명·비밀번호가 들어간 경우와 HTTP(S)가 아닌 값도 거절한다. 원래 페이지에서 다시 다운로드하라는 안내가 필요한 상황이다.
HTTP 주소가 있어도 만료 링크, 재인증, POST로 생성한 결과를 자동 복구한다고 보장할 수 없다. 원본 문서에도 이 제한을 남겼다. 기능을 넓게 설명하면 사람은 같은 버튼이 모든 상황에서 이어 받기를 해 줄 것으로 기대한다. 나는 동작 가능한 범위를 좁혀 안내하는 쪽이 실제 실패 후 대응에는 더 도움이 된다고 봤다.
시험도 이어 받기와 새 요청을 섞지 않는다
기존 제어 시험은 일시정지·재개·취소의 능력 변화를 보고, 완료가 늦은 버튼보다 우선하는 경우와 재시작한 일시정지 기록의 canResume이 사라지는 경우를 검사한다. 다시 시도 시험은 새 child의 연결과 중복 요청 차단을 따로 본다. 한 기능의 통과를 다른 기능의 보장으로 쓰지 않았다.
이 글을 쓰며 원래 네트워크 시험을 새로 실행하지는 않았다. 소스·단위시험·문서를 바탕으로 구현의 경계를 설명했다. 링크한 합성 모듈도 다운로드 재개기는 아니며 선택과 bytes 영수증을 비교하는 예제다. 서비스에 적용하려면 살아 있는 객체, 영속 기록, 새 요청의 상태를 각기 소유하는 위치부터 정해야 한다.