AWS

[AWS] S3 Presigned URL 활용 정리

zamezzz 2025. 6. 11. 15:36

오늘은 S3의 presigned URL에 대해 정리해보겠습니다.

 

예전 글에서 S3에 대해서 조금은 다루었으니, 기본 개념은 건너띄고 바로 Presigned URL에 대해 설명하겠습니다.

(참고 : S3 Bucket 생성하기 https://zamezzz.tistory.com/298)

(참고 : S3 객체 업로드 및 액세스 설정 https://zamezzz.tistory.com/299)

 

Presigned URL ?

Presigned URL은 S3에 접근할 수 있는 일회성 링크입니다.
IAM 권한 없이도 이 URL을 통해 업로드나 다운로드가 가능합니다.

 

사용 예시

  • 클라이언트가 직접 이미지 업로드 (ex. 모바일, 프론트)
  • 대용량 파일을 서버 거치지 않고 다운로드 처리

(참고 : https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/using-presigned-url.html)

 

서버 대신 Presigned URL을 쓰면 좋은 경우

 

[서버를 통하는 방식]
클라이언트 요청 → 서버가 S3에서 직접 파일 다운로드/업로드 → 클라이언트에 응답
- 메모리 점유 심하고 동시 접속에 취약

[Presigned URL 방식]
서버가 S3 Presigned URL 발급 → 클라이언트가 직접 S3로 접근
- 서버 부하 없음

- 안전하고 빠름

- 서버는 Presigned URL 발급만 해줌

 

 

서버에서 직접 파일을 다루면 메모리 문제가 발생할 수 있습니다.
특히 대용량 파일 다운로드 시 OOM(Out Of Memory) 이슈가 날 수 있습니다.

 

Presigned URL 발급 예제

// 업로드용 Presigned URL 생성
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey)
        .withMethod(HttpMethod.PUT)
        .withExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 5)); // 5분 유효

URL presignedUrl = s3Client.generatePresignedUrl(request);

 

업로드 URL에는 메타데이터나 Content-Type도 추가할 수 있습니다.

 

 Presigned URL 사용 중 겪을 수 있는 몇 가지 문제

  • 업로드한 이미지가 열리지 않고 다운로드됨
    • 원인 : 업로드 시 Content-Type이 지정되지 않아 S3에서 기본값인 application/octet-stream으로 저장된 게 원인이었습니다. 이럴 경우, 브라우저는 해당 파일을 '표시'가 아닌 '다운로드' 대상으로 처리하게 됩니다.
    • 해결 방법 : Presigned URL을 생성할 때 Content-Type을 명시하고, 클라이언트에서도 같은 헤더를 포함하여 업로드해야 합니다.
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, key)
    .withMethod(HttpMethod.PUT)
    .withExpiration(expireDate);

request.addRequestParameter("Content-Type", "image/png");

 

  • Presigned URL 링크 만료 오류
    • 원인 : URL 유효 시간이 너무 짧게 설정됨
    • 해결 방법 : URL 생성 시 expiration 시간을 충분히 길게 설정
  • Forbidden (403)
    • 원인 : S3 버킷 또는 IAM 권한 부족
    • 해결 방법 : S3 버킷 정책 또는 IAM Role 정책에서 권한 확인 및 수정
  • CORS 오류
    • 원인 : S3 버킷이 이에 대한 허용 정책을 가지고 있지 않음
    • 해결 방법 : S3 콘솔에서 버킷의 CORS 설정을 추가
Access to fetch at 'https://your-bucket.s3.amazonaws.com/...' from origin 'https://yourdomain.com' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

 

몇 가지 유의사항만 잘 인지한다면, 아주 편하게 파일 업로드/다운로드 관리를 안전하게 할 수 있습니다.

그럼 정리를 마치겠습니다.