
백엔드 개발자를 준비하며 생기는 의문들을 정리한 포스트입니다.
프로젝트의 작업을 하던 어느날 디자인팀의 피그마를 보고 있는데
사용자의 프로필 이미지를 업로드하고 관리해야하는 일이 생겼을 때
나는 이미지를 어디에 저장하고 사용할 수 있을까?
이 때 온라인 객체 스토리지 서비스를 생각한
나는 AWS의 S3 버킷을 이용하여 이미지를 업로드할 생각이 들었습니다.
이에 S3가 업로드되는 방식에 대해 알아보려고 합니다.
온라인 객체 스토리지는 구글 드라이브와 같이 데이터를 객체 형태로 저장하는 서비스입니다. 데이터 조작에 HTTP/HTTPS를 통한 API가 사용되며, 사용자는 UI 인터페이스를 통해 어디서나 쉽게 데이터를 저장하고 불러올 수 있습니다.

AWS S3에는
버킷(Bucket)과객체(Object)라는 단위가 있습니다.
객체(Object): 데이터와 메타데이터로 구성된 저장 단위로, 파일의 개념과 유사합니다.
버킷(Bucket): 객체를 저장하고 관리하는 역할을 하며, 디렉토리나 폴더의 개념과 비슷합니다.
S3에 객체를 저장하면 특정 URL이 생성됩니다.

예를 들어, User라는 버킷에 profile.png라는 객체 파일을 저장하면 http://[BucketName].[Region].[amazonaws.com]/object.key.file과 같은 형식의 URL이 만들어집니다.
S3 업로드 방식에는 크게 3가지가 있습니다.

1회 API 호출에 1개의 파일을 업로드할 수 있습니다.
대용량 파일 업로드에 적합하며 메모리에 큰 영향을 주지 않습니다.
하지만 파일 용량이 커질수록 업로드 속도에 주의해야 합니다.

여러 종류의 데이터를 한 번에 묶어서 HTTP 요청에 담는 방식입니다.
Spring에서 파일 부분을 다루기 쉽게 만든 객체입니다.
동시에 여러 요청을 보낼 수 있지만, 파일 전체를 메모리나 임시 디스크에 저장하므로
수많은 요청이 올 경우 메모리가 부족해질 수 있습니다.
Stream방식은 HTTP 본문의 1개 파일에 대해 그대로 전송합니다.
따라서 한 번의 API 호출로 1개의 파일만 업로드할 수 있습니다. 이는 본문 바이너리에서 여러 데이터를 구분할 기준이 없기 때문입니다. 또한 파일을 메모리에 한 번에 저장하지 않고 데이터 흐름(스트림)을 통해 처리하기 때문에 메모리 사용에 큰 영향이 없어 대용량 파일 업로드에 적합합니다. 하지만 파일 요량이 클수록 업로드 속도가 느려질 수 있기 때문에 UX 관점에서 좋지 않을 수 있습니다.
MultipartFile은 여러 부분(part)으로 나눈 데이터를 한 요청에 담아 전송하게 됩니다.
따라서 한 번의 APU 호출에 여러 데이터를 보내기 가능하죠.
하지만 메모리 사용부분에서 아무래도 MultipartFile은 서버가 요청을 받으면 파일 전체를 메모리나 임시 디스크에 저장합니다. 이 때문에 동시에 여러 요청을 보낼 수 있지만, 요청이 많아지면 메모리 부족 현상이 발생할 가능성이 있습니다.
따라서 여러 개의 작은 파일을 한 번에 전송하거나, 파일과 다른 데이터를 함께 보낼 때 유용합니다.
정리해보면
Stream방식은 대용량 파일을 한번에 업로드할 때
MultipartFile방식은 여러 개의 작은 파일을 한 번에 전송할 때 유리합니다.

AWS 멀티파트 업로드는 대용량 파일을 S3에 효율적으로 업로드하기 위한 방식입니다. 이 방식은 파일을 여러 개의 작은 부분(part)으로 나누어 병렬로 업로드합니다. 이는 단일 연결로 전체 파일을 업로드하는 것보다 더 빠르고 안정적이며, 네트워크 오류가 발생하더라도 실패한 부분만 다시 전송하면 되기 때문에 처음부터 다시 업로드할 필요가 없습니다.
Multipart 업로드 시작
업로드를 시작하겠다는 요청을 보냅니다.
그러면 S3는 해당 업로드에 대한 고유한 ID를 응답으로 반환합니다.PresignedURL 발급
클라이언트가 업로드할 각 파일 부분(part)에 대한 URL을 요청합니다.
S3는 유효 기간이 있는 resignedURL을 응답으로 제공합니다.
이 URL을 통해 인증 정보 없이도 S3에 직접 파일을 업로드할 수 있습니다.PresignedURL part 업로드
클라이언트는 발급받은 PresignedURL을 사용하여 각 파일 부분을 S3에 직접 업로드합니다.
이 과정은 여러 개의 part를 동시에 병렬로 업로드할 수 있습니다.
각 part가 성공적으로 업로드되면 S3는 ETag (엔티티 태그)를 응답으로 반환합니다.Multipart 업로드 완료
모든 part의 업로드가 완료되면, 클라이언트는 S3에 업로드 완료 요청을 보냅니다.
이때 S3는 각 part의 ETag 정보를 포함하여 모든 part를 하나의 완전한 파일로 재구성하고, 최종적으로 완료 응답을 반환합니다.
AWS S3의 프리 티어(Free Tier)는 5GB의 스토리지를 무료로 제공합니다.
또한, 20,000건의 GET 요청과 2,000건의 PUT/POST 요청이 무료입니다.
하지만 사용하지 않는 데이터를 S3에 올려두는 일이 없도록 관리해야 과금이 일어나지 않습니다.
[AWS] 📚 S3 개념 & 버킷 · 권한 설정 방법
Spring Boot에서 S3에 파일을 업로드하는 세 가지 방법