
내가 수강하는 온라인 강의가 수백 개 있는데, 재생이 자주 버벅여서 내 자료를 로컬에 보존해두고 싶었다. 수백 개를 하나씩 받는 건 말이 안 되고, 그렇다고 대충 스크립트를 돌리면 중간에 끊기거나 같은 걸 또 받거나 용량이 터진다. 그래서 "끊겨도 이어받고, 이미 받은 건 건너뛰고, 끝났는지 한눈에 아는" 파이프라인을 설계했다. 특정 사이트 얘기가 아니라 대용량 배치 다운로드를 어떻게 견고하게 만드는가에 대한 기록이다.
시작은 "무엇을 받을 것인가"의 완전한 목록이다. 나는 강의 목록 페이지의 정적 HTML을 파싱해서 각 항목의 식별자를 뽑았다. 여기서 하나 배운 건, 페이지가 아코디언처럼 접혀 있어도 DOM에는 전체 항목이 이미 다 들어있는 경우가 많다는 거다. 굳이 펼치는 클릭을 흉내 내지 않아도, 정적으로 로드된 목록만 긁으면 전량을 얻을 수 있었다. 개수가 사이트가 보여주는 통계와 정확히 맞는지 대조해서 파싱이 빠짐없이 됐는지 검증했다.
실제 파일 정보는 목록에 다 없어서, 항목별로 메타데이터를 한 번씩 조회했다. 이건 동시성을 적당히 걸어서 배치로 처리했다. 조회 실패가 0건인지 확인하고 다음 단계로 넘어갔다.
대용량 작업에서 제일 위험한 건 용량 추정을 대충 하는 거다. 나도 처음엔 샘플 하나의 재생시간과 비트레이트로 전체를 어림했다가 크게 틀렸다. 화면 움직임이 많은 영상은 파일당 2GB에 달할 정도로 편차가 컸기 때문이다.
그래서 추정 대신 실측을 했다. 모든 항목에 대해 Range: bytes=0-0 헤더로 딱 첫 바이트만 요청하면, 서버가 응답 헤더에 Content-Range: bytes 0-0/TOTAL 형태로 전체 크기를 알려준다. 이 TOTAL만 파싱해서 다 더하면 실제 전체 용량이 나온다. 이렇게 계산한 값이 실제 다운로드 후 디스크 사용량과 거의 정확히 맞았다. 미리 정확한 총량을 알면 받을 디스크에 여유가 있는지, 얼마나 걸릴지 판단할 수 있다.
다운로드는 집에 있는 리눅스 박스에서 돌렸다. 샌드박스나 노트북보다 홈 네트워크가 훨씬 빨라서, SSH로 붙어 백그라운드로 굴리는 게 효율적이었다. URL과 저장 경로를 담은 매니페스트를 만들어 서버로 전송하고, 목록을 여덟 조각으로 나눠서(split -n l/8) 각 조각을 백그라운드 서브셸에서 순차적으로 받게 했다. 즉 8개가 동시에 돌면서 각자 자기 몫을 처리하는 구조다.
각 파일 다운로드에는 재시도와 이어받기를 넣었다. curl의 resume(-C -) 옵션을 쓰면 중간에 끊긴 파일을 처음부터 다시 받지 않고 이어서 받는다. 공식 문서에 나오듯 -C -는 curl이 스스로 어디까지 받았는지 알아내게 하고, -C 400처럼 정확한 바이트를 지정할 수도 있다. 이 옵션은 --range와 동시에 쓸 수 없다는 점도 문서에서 확인했다.
curl -C - -o "$dest" "$url"
그리고 이미 받아둔 파일이 일정 크기 이상이면 스킵하게 했다. 이 스킵 로직 덕분에 스크립트를 중간에 다시 돌려도 안전했다. 실제로 한 번은 실행 명령이 로컬에서 중단된 것처럼 보였는데, 서버 프로세스는 이미 돌고 있어서 재실행했더니 이미 받은 수백 개를 SKIP으로 건너뛰고 나머지만 받았다.
장시간 배치의 마지막 조각은 "지금 어디까지 됐나"를 빨리 아는 장치다. 청크별로 OK/FAIL을 로그에 쌓고, 전체가 끝나면 상태 파일에 완료 표시를 남기게 했다.
printf 'ALL_DONE %s\n' "$(date -Is)" > status.txt
돌아왔을 때 이 마커 파일 하나만 확인하면 끝났는지 아닌지 즉시 알 수 있고, 진행 중이면 로그의 OK 카운트와 누적 용량을 보면 된다. 다운받은 파일은 랜덤 샘플을 골라 file 명령으로 실제 정상 미디어인지 검증했다.
정리하면 대용량 배치 다운로드의 견고함은 화려한 기술이 아니라 몇 가지 방어에서 나온다. 목록을 완전하게 확보하고, 용량을 추정이 아닌 실측으로 잡고, 이어받기와 스킵으로 재실행에 안전하게 만들고, 완료 마커로 상태를 빨리 읽게 하는 것. 이 네 가지를 갖추니 "걸어두고 나중에 결과만 확인하는" 작업이 됐다.
참고로 이런 자동화는 내가 정당하게 접근 권한을 가진 내 자료를 개인적으로 보존하는 용도에 한정해서 썼다. 남의 콘텐츠나 접근 권한이 없는 자료에 이 방식을 적용하는 건 다른 문제다.
| 흩어진 AI 대화 수백 개를 검색 가능한 개인 지식베이스로 묶기 (0) | 2026.07.28 |
|---|---|
| 가민 Fenix 7에 KBO 실시간 점수 띄우는 워치페이스 만들기 (0) | 2026.07.27 |
| 바이브코딩으로 만든 중고거래 서비스를 제출 가능한 수준까지 보안 강화하기 (0) | 2026.07.27 |
| AI 에이전트 4종을 한 화면에서 보려고 로컬 관제 대시보드를 만들었다 (0) | 2026.07.27 |
| ChatGPT Plus, GitHub Copilot, Google Colab Pro 뭐가 달라? (0) | 2026.07.25 |