FileSharer 개발 노트 4 — 끊긴 다운로드를 이어받는 Range의 경계값

English version

FileSharer 개발 노트 · 04 / 10

세 개발자가 긴 파일 조각의 위치를 맞추며 이어받기 범위를 살펴봅니다.
AI 일러스트 · 세 개발자가 긴 파일 조각의 위치를 맞추며 이어받기 범위를 살펴봅니다.

파일을 거의 다 받았는데 연결이 끊기면, 처음부터 다시 받는 비용이 크게 느껴집니다. HTTP의 Range 요청은 필요한 바이트 구간을 지정하는 방법입니다. FileSharer는 단일 파일뿐 아니라 만들어 둔 ZIP에도 같은 전송 함수를 사용해 부분 요청을 처리합니다.

원본 TryParseRange 함수의 실제 반환값을 정리한 리포트. 파일 크기 1,000바이트를 가정한 함수 시험이며 실제 전송 속도 측정은 아닙니다.
원본 TryParseRange 함수의 실제 반환값을 정리한 리포트. 파일 크기 1,000바이트를 가정한 함수 시험이며 실제 전송 속도 측정은 아닙니다.

이어받기에서 먼저 확인할 것은 “Range를 지원한다”는 문구보다 구간 계산입니다. 시작과 끝을 하나씩 잘못 계산하면 파일 한 바이트가 빠지거나 중복될 수 있습니다.

끝 위치를 포함해 센다

1,000바이트 파일의 위치는 0부터 999까지입니다. bytes=100-199가 요청하는 길이는 99가 아니라 100바이트입니다.

전송 길이 = 끝 위치 - 시작 위치 + 1
100 = 199 - 100 + 1

원본 ServeFile도 end - start + 1로 길이를 계산하고, 시작 위치가 0보다 크면 파일 스트림에서 Seek합니다. 유효한 부분 응답은 206과 Content-Range, 만족시킬 수 없는 요청은 416을 구성합니다. 이 응답 의미는 RFC 9110의 Range 규정에 설명돼 있습니다.

실제 파서에 넣은 입력

TryParseRange를 원본 그대로 추출해 실행했습니다. 아래 결과는 전체 파일 크기 1,000바이트일 때입니다. 유효하지 않은 경우의 출력 변수는 사용하지 않습니다.

Range 입력 결과 선택된 구간
bytes=0-99 허용 0–99
bytes=100- 허용 100–999
bytes=-50 허용 950–999
bytes=900-1200 허용 900–999
bytes=1000- 거절 없음
bytes=100-99 거절 없음
bytes=-0 거절 없음
bytes=0-9,20-29 허용 첫 구간 0–9만

추가로 잘못된 단위 items, 공백이 있는 bytes = 10-19, 크기 0인 파일을 확인해 총 11개 입력을 실행했습니다. 잘못된 단위와 빈 파일의 요청은 false, 공백을 허용하는 입력은 true였습니다. 이 결과는 해당 구현의 동작이며 모든 문법을 포괄한 적합성 시험은 아닙니다.

여러 구간과 여러 연결은 다른 기능이다

현재 파서는 쉼표가 있으면 첫 번째 구간만 취합니다. 한 요청에 여러 구간을 담아 multipart 응답으로 모두 받는 구현과는 구분해야 합니다.

서버는 여러 클라이언트 연결을 처리할 수 있으므로 다운로드 도구가 별도 요청으로 구간을 나누는 방식은 또 다른 문제입니다. 하지만 내장 암호화 페이지의 pump는 구간을 순차적으로 가져오고 실패하면 재시도합니다. 이 페이지가 자동으로 여러 구간을 동시에 받는다고 설명하면 실제 코드와 다릅니다.

처리량 향상을 주장하려면 연결 수, 회선, 파일 크기, 암호화 여부를 함께 고정한 별도 측정이 필요합니다. 이번 시험은 파서의 반환값을 확인했으며 속도 배수는 측정하지 않았습니다.

위치가 맞아도 파일이 바뀌면 이어받기에 실패한다

첫 요청에서 받은 앞부분이 버전 A이고, 재시도에서 받은 뒷부분이 버전 B라면 각 구간은 정상이어도 합쳐진 파일은 잘못됩니다. 이어받기는 바이트 위치뿐 아니라 동일한 파일 표현을 계속 받고 있는지 확인해야 합니다.

현재 응답에는 수정 시각과 크기로 만든 ETag가 있습니다. 그러나 ETag를 보내는 것과 조건부 요청을 실제로 비교하는 것은 다릅니다. 해당 전송 경로에서는 If-Range 검증을 확인하지 못했습니다. 브라우저 재시도도 파일 변경을 끝까지 검증하는 형태라고 단정할 수 없습니다.

개선한다면 공유 시점의 파일 버전을 고정하거나, 전송 세션에 버전 식별자를 연결하고 변경 시 재개를 중단하는 방법을 검토할 수 있습니다. 수신 후 해시 비교는 완성된 결과의 동일성을 확인하는 별도 단계가 됩니다.

파서 다음에 확인할 것

이번 실행으로 경계 계산은 눈으로 확인할 수 있게 됐습니다. 다음 단계의 통합 시험에서는 중간 연결 종료 후 재개, 전송 도중 원본 변경, HEAD 요청, 빈 파일을 실제 HTTP 응답과 함께 확인해야 합니다. “이어받기 지원”이라는 한 문장을 여러 작은 계약으로 나누면 실패한 위치도 훨씬 선명해집니다.

소스 근거
FileSharer.cs:5154–5197 TryParseRange · FileSharer.cs:5250–5322 ServeFile 헤더 처리 · FileSharer.cs:5343–5367 위치 이동과 전송 · FileSharer.cs:5800–5878 브라우저 pump
본문의 개선안은 현재 구현된 기능과 구분합니다.

댓글