목표
- Presigned URL 이해하기
- Aws S3 이미지 업로드 시 서버 부하 줄이기
일반적인 S3 이미지 업로드 처리
1. 서버 애플리케이션을 통한 이미지 업로드
파일 업로드는 권한 인증 때문에, 서버를 경유해서 진행됩니다.
하지만, 용량이 높은 파일의 경우, 서버에 넘겨준 후 서버에서 스토리지에 저장하는 이중 작업은 비효율적일 수 있습니다. (네트워크 I/O or CPU 사용량)
파일의 크기가 크지 않더라도 서버에서 Multipart File을 받아 S3 버킷에 업로드하는 과정에서 서버 쪽에서 파일을 갖고 있어야 하는 리소스 낭비가 발생할 수 있습니다.
2. Aws Lambda를 통한 이미지 업로드
Aws API Gateway와 Lambda를 통해 처리하는 경우 10MB 용량 제한이 있어, 더 높은 용량의 이미지는 업로드할 수 없음
Why, 서버를 거쳐서 이미지 업로드를 수행하는지?
보안 문제, 위에 말했듯이 권한을 가진 사용자만 Aws S3에 이미지 업로드를 가능하게 해야 한다.
이를 서버를 통해 권한 문제를 처리하여 이미지 업로드를 수행한다.
위와 같이 서버를 통해 이미지 업로드를 하는 경우, 리소스 낭비 문제를 해결하기 위해 클라이언트가 직접 업로드할 수 있는 presigned URL에 대해 알아보자.
Presigned URL이란
presigned URL은 미리 서명된 URL로 S3에 바로 이미지를 업로드할 수 있는 URL입니다.
발급받은 presigned URL을 통해 브라우저에서 AWS S3 버킷에 이미지를 업로드할 수 있습니다.
미리 서명된 URL을 사용하여 다른 사람이 Amazon S3 버킷에 객체를 업로드하도록 허용할 수 있습니다. 미리 서명된 URL을 사용하면 상대방에게 AWS 보안 자격 증명이나 권한이 없어도 업로드할 수 있습니다. 미리 서명된 URL은 이를 생성하는 사용자의 권한에 따라 제한됩니다.
즉, 객체를 업로드하기 위해 미리 서명된 URL을 수신하는 경우, URL의 생성자가 해당 객체를 업로드하는 데 필요한 권한을 보유하는 경우에만 객체를 업로드할 수 있습니다.
사용자가 URL을 사용하여 객체를 업로드하는 경우 Amazon S3는 지정된 버킷에 객체를 생성합니다. 미리 서명된 URL에 지정된 것과 동일한 키를 사용하는 객체가 이미 버킷에 있다면 Amazon S3는 업로드된 객체로 기존 객체를 바꿉니다. 업로드 후에는 버킷 소유자가 객체를 소유하게 됩니다.
- Aws API Gateway, Lambda를 통해서 처리할 수도 있고, 자체 서버 애플리케이션에서도 처리할 수 있다.
- 핵심은 Aws S3에 업로드할 수 있는 미리 서명된 URL을 발급받는 것이다.
presigned URL을 활용한 처리 과정
- 서버가 S3 Presigned URL을 생성하여 반환합니다.
- POST : /upload?filname=profile.png
- 클라이언트가 해당 URL로 S3에 직접 이미지 업로드합니다.
- PUT 요청으로 파일 전송
- 서버 측
@Service
@RequiredArgsConstructor
public class S3Service {
private final AmazonS3 amazonS3;
private final String bucketName = "your-s3-bucket";
public String generatePresignedUploadUrl(String objectKey) {
// Presigned URL 만료 시간 (예: 10분 후)
Date expiration = new Date(System.currentTimeMillis() + 1000 * 60 * 10);
// Presigned URL 요청 생성 (업로드용이므로 HttpMethod.PUT 사용)
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(bucketName, objectKey)
.withMethod(HttpMethod.PUT) // 업로드를 위해 PUT 사용
.withExpiration(expiration);
// Presigned URL 생성
URL url = amazonS3.generatePresignedUrl(generatePresignedUrlRequest);
return url.toString();
}
}
- 클라이언트 측
1. 서버에게 Presigned URL 요청
<REQUEST>
GET <https://api.example.com/user/upload-url?filename=profile.jpg>
<RESPONSE>
{
"presignedUrl": "<https://your-s3-bucket.s3.amazonaws.com/uploads/profile.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256>..."
}
2. 클라이언트가 해당 URL을 사용하여 S3에 직접 업로드
PUT <https://your-s3-bucket.s3.amazonaws.com/uploads/profile.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256>...
Content-Type: image/jpeg
# <파일 바이너리 데이터>
기대 효과
- 서버 부하 감소: 서버를 거치지 않고 클라이언트가 직접 S3에 업로드할 수 있다.
- 비용 절감: 서버에서 파일을 중계하지 않으므로 트래픽 비용 절약할 수 있다.
- 보안 강화: Presigned URL은 일정 시간 후 자동 만료되어 노출되어도 만료 기간이 설정되어 있다.
'Aws' 카테고리의 다른 글
AWS CloudFront, Edge Location, CDN 이해하기 - Image Resizing 사전 준비 (0) | 2025.02.04 |
---|---|
AWS Lambda를 사용해 S3에 이미지 업로드하기 (Python & API Gateway) (0) | 2025.01.12 |
Aws Spot Instance란 무엇인가, (0) | 2024.11.26 |