청크 기반 업로드 아키텍처 설계 가이드
견고한 청크 기반 업로드 시스템을 설계하세요. 청킹 전략, 재개 가능한 업로드, 병렬 전송 최적화를 배웁니다.
청크 기반 업로드 아키텍처는 파일을 고정 크기 또는 가변 크기 조각으로 분할하여 독립적으로 전송하므로, 네트워크 장애가 발생해도 10 GB 전송을 처음부터 다시 시작할 필요가 없습니다. 두 가지 지배적인 개방형 표준은 AWS S3 멀티파트 업로드(최소 파트 5 MB, 최대 10,000 파트)와 tus.io 재개 가능 프로토콜(광범위하게 구현된 RFC 초안)입니다. 올바르게 구현하면 청크 업로드는 고지연 링크에서 5~10배 더 높은 처리량을 제공하고, 짧은 연결 끊김을 허용하며, 수신 측 병렬 복호화를 지원합니다.
단일 업로드가 규모에서 실패하는 이유
5 GB 파일의 단일 HTTP PUT은 수십 가지 실패 방식이 있습니다. TCP 혼잡 창이 고지연 경로에서 링크 용량 훨씬 아래로 처리량을 제한하는 데 오랜 시간이 걸립니다. 브라우저는 출처당 동시 연결을 6개로 제한하여 대부분의 대역폭을 유휴 상태로 남깁니다. 서버 측 요청 타임아웃(nginx 기본값 60초, CloudFront 비스트리밍 30초)이 긴 업로드를 종료합니다. 모바일 네트워크는 몇 분마다 셀 타워를 전환하며 연결을 끊습니다. 단 하나의 비트 플립도 전체 전송을 재시작하게 만듭니다. 청크 업로드는 작업 단위를 작고, 독립적으로 재시도 가능하고, 병렬 친화적으로 만들어 이 모든 문제를 해결합니다.
청크 크기 선택
청크 크기는 트레이드오프입니다. 작은 청크는 장애에서 더 빠르게 복구하고 더 세밀한 진행 세분성을 제공하지만 HTTP 오버헤드가 더 많습니다. 큰 청크는 핸드셰이크와 TLS 비용을 분산시키지만 청크가 실패하여 재전송해야 할 때 대역폭을 낭비합니다. 일반적인 범위: 손실이 있는 네트워크의 모바일 업로드에는 1~5 MB, 데스크탑 웹 업로드에는 5~16 MB, 안정적인 링크의 서버간 전송에는 16~64 MB, 1 TB 파일에서 10,000 파트 한도가 더 큰 청크를 강제하는 S3 멀티파트에는 100 MB 이상. 일부 시스템은 동적으로 적응하여 작게 시작하고 연결이 안정적으로 증명되면 크기를 늘립니다.
고정 크기 대 콘텐츠 정의 청킹
고정 크기 청킹(예: 매 8 MB)은 구현이 간단하고 병렬 친화적이며 정확한 재개 오프셋을 지원합니다. rsync와 restic에서 사용되는 콘텐츠 정의 청킹은 Rabin 지문 같은 롤링 해시를 기반으로 경계를 선택하므로 파일 중간의 삽입이 모든 후속 청크 경계를 이동시키지 않습니다. CDC는 백업 도구에서 중복 제거에 탁월하지만 순수 파일 전송에서는 보상 없는 복잡성과 CPU 비용이 추가됩니다. 업로드 아키텍처에서는 단순성에서 고정 크기가 우세하며 S3 멀티파트 파트 또는 tus.io 오프셋에 깔끔하게 매핑됩니다.
재개 가능 업로드 프로토콜
tusd(Go), tus-js-client, Uppy, 많은 서버 프레임워크에 구현된 tus.io 프로토콜은 청크를 추가하기 위해 Upload-Offset 헤더가 있는 HTTP PATCH를 사용합니다. HEAD 요청은 서버의 현재 오프셋을 반환하므로 클라이언트는 네트워크 중단 후 어디서 재개할지 알 수 있습니다. S3 멀티파트 업로드는 다른 모델을 사용합니다. UploadId를 얻기 위해 업로드를 시작하고, 각 파트를 업로드하고(1부터 인덱싱), ETag 목록과 함께 CompleteMultipartUpload 요청을 보냅니다. 클라이언트는 ListParts를 쿼리하여 무엇이 업로드되었는지 확인할 수 있습니다. 두 프로토콜 모두 클라이언트 재시작과 연결 끊김을 우아하게 처리합니다.
병렬 업로드 동시성
청크를 병렬로 업로드하면 고지연 링크에서 처리량이 극적으로 향상됩니다. HTTP/1.1은 브라우저에서 출처당 6개의 동시 연결로 제한되고, HTTP/2는 단일 연결을 통해 많은 스트림을 다중화하지만 여전히 흐름 제어 창의 영향을 받습니다. 일반적인 업로드 스케줄러는 청크를 큐에 넣고 4~8개를 병렬로 디스패치하며, 서버가 429 또는 503을 신호할 때 배압을 적용합니다. 너무 많은 병렬성은 ISP 조정과 미들박스 연결 한도를 유발하고, 너무 적으면 대역폭이 낭비됩니다.
클라이언트 측 상태와 재개 메타데이터
재개 가능한 업로드는 클라이언트가 브라우저 충돌이나 노트북 종료 후 재개하기 위한 충분한 상태를 기억해야 합니다. Web Storage 표준의 일부인 IndexedDB는 파일의 해시, 청크 수, 성공한 청크를 포함하는 업로드 매니페스트를 저장합니다. 매니페스트를 파일의 SHA-256 해시로 키잉하면 동일한 파일을 다시 추가할 때 중단된 곳에서 재개됩니다. 7일이 지난 오래된 매니페스트를 정리하여 팽창을 방지하세요. 모바일에서는 WKWebView(iOS)와 Chrome Custom Tabs(Android)가 메모리 압박 시 IndexedDB를 퇴거시킬 수 있으므로, 가능하면 중요한 상태를 네이티브 스토리지에 유지하세요.
서버 측 청크 처리
서버는 청크를 완전한 파일로 재조립하거나, S3 멀티파트의 경우 재조립을 S3에 위임해야 합니다. 최소 아키텍처: 각 청크 PATCH를 수락하고, 업로드 ID와 청크 인덱스로 키잉된 임시 블롭에 쓰고, Redis 또는 PostgreSQL 같은 메타데이터 스토어에 오프셋을 기록하고, CompletePart 시 조립하거나 완료로 표시합니다. 청크 블롭에는 로컬 디스크가 아닌 오브젝트 스토리지(S3, Cloudflare R2, Backblaze B2)를 사용하세요. 로드 밸런싱된 백엔드는 로컬 상태를 공유할 수 없습니다. 24~72시간 후 포기된 업로드를 가비지 컬렉션하여 스토리지를 회수하세요.
청크별 및 종단간 무결성 검증
업로드 시 각 청크를 해시로 검증하세요. S3 멀티파트의 ETag는 파트당 MD5 해시(또는 전체 오브젝트의 복합 해시)입니다. 더 강력한 무결성을 위해 클라이언트 측에서 청크당 SHA-256을 계산하여 헤더로 전송하면, 서버가 청크 옆에 저장하고 재읽기 시 검증할 수 있습니다. 모든 청크가 업로드된 후 재조립된 파일의 Merkle 트리 루트 또는 스트리밍 해시를 계산하여 클라이언트에 반환하세요. 클라이언트는 이를 원본 파일의 자체 해시와 비교합니다. 불일치는 문제가 있는 청크의 재업로드를 트리거합니다.
청킹과의 암호화 상호 작용
종단간 암호화는 청킹을 약간 복잡하게 만듭니다. 각 청크는 AES-GCM에서 IV 재사용을 피하기 위한 자체 논스가 필요하며, 청크 경계는 인증 체계의 일부여야 합니다. 일반적인 접근: 루트 파일 암호화 키에서 HKDF-SHA256을 통해 청크 인덱스를 컨텍스트 정보로 사용하여 청크별 키를 파생하고, 각 청크를 AES-256-GCM과 0 또는 증분 논스로 암호화하세요. AAD에 청크 인덱스와 총 청크 수를 포함하여 공격자가 청크를 이어 붙이거나 재정렬할 수 없게 하세요. HexaTransfer는 이 패턴으로 클라이언트 측 청크 암호화를 구현하여 10 GB 파일을 불안정한 연결에서 안정적으로 처리합니다.
https://hexatransfer.com 에서 무료로 시작하세요. 계정 불필요, 최대 10 GB.
엔드투엔드 암호화로 대용량 파일을 안전하게 전송
엔드투엔드 암호화로 최대 10GB의 파일을 무료로 전송하세요. 계정이 필요하지 않습니다. 업로드 전에 브라우저에서 파일이 암호화되어 다른 사람은 읽을 수 없습니다.
파일 보내기