기존 블로그들을 찾아보면, SpringBoot 2.x 버전으로 AWS 서비스들을 이용하는 방법들을 다루는 내용은 많지만, SpringBoot3.x 버전과 S3 presigned url을 다루는 방법에 대한 내용이 별로 없어서, 따로 포스팅해보고자한다!
AWS 서비스를 사용하기 위한 방법들은 굉장히 많다. HTTP 요청/응답을 통해 이용하는 방법도 있고, SDK 라이브러리를 이용하는 방법, 터미널로 직접 다루는 방법 등 굉장히 많다. 해당 포스팅에선, 라이브러리를 의존성에 추가해서 사용하는 방법을 알아볼 것이다
찾아본 결과, 많이 사용되는 라이브러리는 아래 2가지였다. 난 io.awspring.cloud 그룹의 라이브러리를 선택했다.
이유는 업데이트가 안되고 있어서였다. maven repository 사이트 에 직접 들어가보면, org.springframe... 로 시작하는 라이브러리의 업데이트현황을 보면 2021년에 업데이트되고, 이제 업데이트가 되지 않고 있다. 그래서 현재까지 활발히 업데이트되는 라이브러리를 선택한 것이다.


라이브러리까지 정했으니 이제 설정을 해보자!
# gradle.properties
springCloudAwsVersion=3.0.2
val springCloudAwsVersion: String by project
dependencies {
// spring-cloud-aws 관련 라이브러리 버전 관리
implementation(platform("io.awspring.cloud:spring-cloud-aws-dependencies:$springCloudAwsVersion"))
// aws - autoconfigure & s3
implementation("io.awspring.cloud:spring-cloud-aws-starter-s3")
}
우선 gradle.properties 에 변수들을 담아두고 버전관리를 하면 버전 변경에도 빠르게 대처할 수 있어서 나는 gradle.properties 파일에 버전을 명시해주는 것을 좋아한다.
그리고 라이브러리 버전 관리용도로 Gradle 5.0 이상부터는 dependencyManagement 대신 implementation(platform("io.awsspring....")) 처럼 platform 키워드를 사용할 수 있다고 한다. 공식문서에서도 이와 같은 방식을 소개하고 있으며 나는 개인적으로 dependencyManagement 로 잡아주는 것도 좋지만, platform 이 깔끔해보여서 platform 키워드를 사용했다.
나는 S3의 presigned url을 생성해주는 로직만이 필요해서 S3 관련 라이브러리만 추가해주었다. 다른 서비스가 필요한 사람들은 공식문서를 참고해서 넣어주면 된다.

spring:
cloud:
aws:
credentials:
access-key: {your access key}
secret-key: {your secret key}
region:
static: ap-northeast-2
aws:
s3:
bucket: {your s3 bucket}
저기 위에 보이는 yml 파일들의 spring. 이 prefix로 붙은 property 들은 라이브러리에서 자동으로 조회해서 빈을 만들거나 로직에 사용되는 값들이고, aws.s3.bucket 은 내가 임의로 만든 property이다! (헷갈림 방지 ㅎㅎ)

import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import software.amazon.awssdk.services.s3.model.PutObjectRequest
import software.amazon.awssdk.services.s3.presigner.S3Presigner
import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest
import java.time.Duration
@Service
class AwsS3Service(
@Value("\${aws.s3.bucket}")
private val bucket: String,
private val s3PreSigner: S3Presigner
) {
fun createPreSignedUrlForUpload(path: String): String {
val putObjectRequest = PutObjectRequest.builder()
.bucket(bucket)
.key(path)
.contentType("image/jpeg")
.build()
val preSignRequest = PutObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(5)) // The URL will expire in 5 minutes.
.putObjectRequest(putObjectRequest)
.build()
return s3PreSigner.presignPutObject(preSignRequest).url().toString()
}
}

잘 동작하는 것을 확인할 수 있다. 도움이 되셨기를 바랍니다~ ㅎㅎ