콘텐츠로 건너뛰기

AWS S3·CloudFront 파일 업로드 상한 정리|멀티파트·서명된 URL

카테고리: 클라우드·AWS
이 기사는 현재 일본어로만 제공됩니다. 번역본은 순차적으로 공개될 예정입니다.

AWS를 사용한 파일 업로드 기능을 구축할 때 S3, CloudFront, API Gateway, Lambda는 각각 다른 크기 제한이 있으며, 어느 계층이 병목이 될 수 있는지 파악하는 것이 매우 중요합니다. 본 문서에서는 각 서비스의 제한값을 정리하고, 대용량 파일을 처리하기 위한 멀티파트 업로드 및 서명된 URL의 사용 방법, PHP 구현 예제까지 설명합니다.

S3 업로드 방식과 크기 PUT (single) ≤ 5 GB Multipart upload 5 MB ~ 5 TB / object Object size limit (S3) 5 TB max 주의: CloudFront / API Gateway / Lambda는 별도 본문 제한이 있음
그림: S3 업로드 크기 계층 (단일 PUT 5GB / 멀티파트 5TB)

Amazon S3 업로드 제한

S3로의 객체 업로드는 방식에 따라 상한 크기가 다릅니다.

업로드 방식 최대 크기 비고
PUT Object (단일) 5 GB 1요청당 업로드 상한
Multipart Upload 5 TB 1개 객체의 최대 크기
1파트당 최소 5 MB ~ 최대 5 GB 마지막 파트만 5 MB 미만 가능
파트 수 최대 10,000개 파트 멀티파트 시 상한

AWS는 100 MB 이상의 파일에 멀티파트 업로드를 권장하며, 네트워크 장애 시 재전송 효율과 병렬 전송을 통한 처리량 향상 측면에서도 대용량 파일에 적극적으로 사용해야 합니다.

멀티파트 업로드가 필요한 경우

멀티파트 업로드는 하나의 객체를 여러 파트로 나누어 각각 독립적인 요청으로 송신한 후 마지막에 합치는 방식입니다. 다음과 같은 경우에 효과적입니다.

  • <strong>100 MB 이상의 파일</strong>: AWS가 권장하는 멀티파트 전환 라인입니다.
  • <strong>네트워크가 불안정한 환경</strong>: 중간에 오류가 발생해도 실패한 파트만 재전송 가능합니다.
  • <strong>처리량 최대화</strong>: 여러 파트를 병렬로 업로드하여 전송 속도 향상.
  • <strong>업로드 일시 중지·재개</strong>: Upload ID를 저장해두면 세션을 걸쳐 재개 가능합니다.

멀티파트 업로드의 흐름은 크게 3단계입니다.

  1. <strong>시작</strong>(CreateMultipartUpload): Upload ID를 가져옵니다
  2. <strong>파트 전송</strong>(UploadPart): 각 파트를 업로드하고 ETag 기록
  3. <strong>완료</strong>(CompleteMultipartUpload): 파트 번호와 ETag 목록을 전송하여 객체를 확정합니다

<code>AbortMultipartUpload</code>를 호출하지 않고 중단하면 완료되지 않은 파트가 스토리지 요금으로 계속 청구됩니다. S3 버킷의 라이프사이클 정책에서 "완료되지 않은 멀티파트 업로드를 N일 후 삭제"하도록 설정할 것을 강력히 권장합니다.

Presigned URL의 유효 기간 및 크기

서명된 URL (Presigned URL)을 사용하면 S3 접근 권한이 없는 클라이언트 (브라우저·모바일 앱 등)에서 직접 S3로 파일을 업로드할 수 있습니다. 서버를 중계하지 않으므로 대용량 파일도 효율적입니다.

항목 제한・사양
최대 유효 기간 (IAM 사용자 발급) 7일(604,800초)
최대 유효 기간 (IAM 역할 발급) 역할의 세션 시간 내 (최대 12시간)
업로드 가능한 파일 크기 단일 PUT의 경우 최대 5GB
멀티파트 지원 각 부분에 개별 Presigned URL 발급

Presigned URL은 백엔드에서 생성되어 클라이언트에 반환되며, 클라이언트는 해당 URL에 직접 PUT 요청을 보냅니다. URL에는 서명이 포함되어 있으므로 유효 기간 내에 올바른 파일을 업로드할 때만 성공합니다.

CloudFront의 body size 제한

CloudFront를 통해 오리진(S3나 EC2 등)으로 요청을 전달할 때 요청 본문의 크기에 제한이 있습니다.

설정 기본값 최대값
요청 본문 크기 (기본값) 1 MB 배포 설정에서 변경 가능
Lambda@Edge를 통한 경우 1 MB 1 MB (변경 불가)
CloudFront Functions의 경우 요청 본문에 접근할 수 없음

CloudFront 배포 설정에서 「Allow requests with body」를 활성화하고 상한을 높일 수 있지만, Lambda@Edge에서는 1 MB 상한을 변경할 수 없음을 주의하세요. 대용량 파일 업로드의 경우 CloudFront를 거치지 않고 Presigned URL을 사용하여 클라이언트에서 S3로 직접 업로드하는 아키텍처를 채택하기를 권장합니다.

API Gateway의 Payload 제한

API Gateway(REST API / HTTP API 모두)에는 페이로드 크기 상한이 있습니다.

API 유형 최대 페이로드 크기 비고
REST API 10 MB 바이너리 지원을 활성화한 경우도 동일
HTTP API 10 MB
WebSocket API 128 KB (메시지) / 32 KB (프레임)

API Gateway의 10 MB 제한은 AWS 서비스 할당량에 분류되며 완화 신청이 불가능합니다. API Gateway를 통해 10 MB를 초과하는 파일을 업로드하는 것은 설계 오류로 간주되므로, Presigned URL 패턴으로의 마이그레이션을 검토하세요.

Lambda를 통한 파일 제한

Lambda 함수에서 파일을 수신할 때 API Gateway에서 전달되는 이벤트 페이로드에 크기 제한이 있습니다. 또한 Lambda 자체에도 다음과 같은 제약이 있습니다.

제한 항목
동기 호출(Request) 페이로드 6 MB
동기 호출(Response) 페이로드 6 MB
비동기 호출 페이로드 256 KB
<code>/tmp</code> 디렉토리 용량 기본값 512 MB (최대 10 GB)
최대 실행 시간 15분

Lambda에서 파일을 처리할 때 임시 파일은 <code>/tmp</code>에 기록됩니다. 기본값은 512 MB이지만 Lambda 설정을 통해 에머럴 스토리지를 최대 10 GB까지 확장할 수 있습니다 (추가 요금 적용).

PHP에서 S3 멀티파트 업로드 코드 예제

AWS SDK for PHP(v3)를 사용한 멀티파트 업로드의 구현 예제입니다. SDK의 <code>MultipartUploader</code> 클래스를 사용하면, 청크 분할·재시도·완료 처리를 자동으로 처리해줍니다.

use Aws\S3\S3Client;
use Aws\S3\MultipartUploader;
use Aws\Exception\MultipartUploadException;

$s3 = new S3Client([
    'region'  => 'ap-northeast-1',
    'version' => 'latest',
]);

$uploader = new MultipartUploader($s3, '/path/to/large-file.mp4', [
    'bucket'          => 'your-bucket-name',
    'key'             => 'uploads/' . basename('/path/to/large-file.mp4'),
    'before_initiate' => function (\Aws\Command $command) {
        // アップロード開始前のフック
    },
    'before_upload'   => function (\Aws\Command $command) {
        // 各パートアップロード前のフック(プログレス表示など)
    },
    'concurrency'     => 5,    // 並列アップロード数
    'part_size'       => 10 * 1024 * 1024, // 1パート = 10 MiB
]);

try {
    $result = $uploader->upload();
    echo 'アップロード完了: ' . $result['ObjectURL'];
} catch (MultipartUploadException $e) {
    // 失敗したパートから再開する例
    $uploader = new MultipartUploader($s3, '/path/to/large-file.mp4', [
        'state' => $e->getState(),
    ]);
    $result = $uploader->upload();
}

Presigned URL을 발급하여 클라이언트가 직접 S3에 업로드하도록 하는 방법은 다음과 같습니다.

use Aws\S3\S3Client;

$s3 = new S3Client([
    'region'  => 'ap-northeast-1',
    'version' => 'latest',
]);

// 署名付きURLを生成(有効期限: 15分)
$cmd = $s3->getCommand('PutObject', [
    'Bucket'       => 'your-bucket-name',
    'Key'          => 'uploads/' . uniqid('', true) . '.jpg',
    'ContentType'  => 'image/jpeg',
]);

$request = $s3->createPresignedRequest($cmd, '+15 minutes');
$presignedUrl = (string) $request->getUri();

// このURLをクライアントに返す
// クライアントはこのURLに PUT リクエストでファイルを直接送信する
echo json_encode(['upload_url' => $presignedUrl]);

아키텍처 선택 가이드라인

  • <strong>~10 MB</strong>: API Gateway → Lambda → S3로 간단하게 구현 가능
  • <strong>10 MB~100 MB</strong>: Presigned URL로 클라이언트에서 S3로 직접 업로드를 권장합니다.
  • <strong>100 MB~5 GB</strong>: Presigned URL + 멀티파트 업로드로 안정적인 전송 구현
  • <strong>5 GB 초과</strong>: 멀티파트 업로드 필수 (단독 PUT 불가)

DevLab 임계값 파일을 사용한 테스트 절차

실제로 <code>S3</code> 업로드 설정을 검증하려면 정확한 크기의 테스트 파일이 필요합니다. DevLab의 경계값 테스트 파일을 사용하면 특정 크기 전후의 동작을 효율적으로 확인할 수 있습니다.

  1. DevLab의 <a href="/ja/files/threshold/">경계값 테스트 파일 목록</a>에서 테스트하려는 크기의 파일을 다운로드합니다.
  2. 멀티파트 전환 기준을 검증할 때는 <a href="/ja/files/images/png/">PNG 테스트 이미지</a>의 대형 버전도 활용할 수 있습니다.
  3. <code>aws s3 cp</code> 명령어 또는 SDK의 <code>PutObject</code> / <code>MultipartUploader</code>를 사용하여 다운로드한 파일을 업로드하고, 크기 제한 전후의 파일에서 성공 여부를 확인합니다.

이 기사에서 사용할 수 있는 테스트 파일

  • <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">경계값 테스트 파일 목록</a> — S3, API Gateway, Lambda 각 상한 검증용
  • <a href="/ja/files/threshold/10mb/" class="text-primary-600 dark:text-primary-400 hover:underline">10MB 경계값 테스트 세트</a> — API Gateway 10MB 상한 직전·직후 확인
  • <a href="/ja/files/threshold/25mb/" class="text-primary-600 dark:text-primary-400 hover:underline">25MB 경계값 테스트 세트</a> — 멀티파트 권장 라인 전후의 동작 확인용
  • <a href="/ja/files/images/png/" class="text-primary-600 dark:text-primary-400 hover:underline">PNG 테스트 이미지 목록</a> — 이미지 업로드 파이프라인 동작 확인용

관련 기사

  • <a href="/ja/blog/how-to-test-upload-limit/" class="text-primary-600 dark:text-primary-400 hover:underline">파일 업로드 크기 제한을 올바르게 테스트하는 방법</a>
  • <a href="/ja/blog/php-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">PHP에서 파일 업로드를 구현하는 방법|검증·저장·보안 완벽 가이드</a>
  • <a href="/ja/blog/multipart-form-data-overhead/" class="text-primary-600 dark:text-primary-400 hover:underline">multipart/form-data 오버헤드를 정확하게 계산하기</a>
  • <a href="/ja/blog/mb-vs-mib-file-size/" class="text-primary-600 dark:text-primary-400 hover:underline">MB와 MiB는 다르다! 파일 크기 단위의 함정</a>

자주 묻는 질문

S3의 1회 PUT 요청으로 업로드할 수 있는 최대 크기는?

단일 PUT 작업은 최대 5GB입니다. 더 큰 파일의 경우 멀티파트 업로드를 사용하면 최대 5TB까지 지원합니다.

S3의 서명된 URL(Presigned URL) 유효 기간은?

기본값은 15분이며, 최대 7일(604800초)까지 설정 가능합니다. 이것은 IAM 사용자 자격증명으로 생성한 경우의 상한선입니다.

CloudFront를 경유할 때 업로드 크기 제한은 어떻게 되나요?

CloudFront의 요청 body 크기 제한은 기본값으로 GET이 0, POST/PUT이 최대 20MB입니다. 대용량 파일을 S3에 직접 업로드하는 설계가 권장됩니다.