본문 바로가기
👨‍💻 프로그래밍/📦 Backend

S3, AWS SDK 사용해서 Spring Boot로 이미지 업로드 기능 구현하기

by 개발자 진개미 2023. 5. 11.
반응형


SDK란?

SDK는 특정 용도의 소프트웨어를 개발하기 위해 유용한 것들을 (도구, 라이브러리, 문서, 예시 코드, API) 모아 놓은 것입니다.

예를 들어 Android SDK는 안드로이드 앱을 만드는데 필요한 각종 라이브러리나 도구들을 모아 놨고, iOS SDK는 마찬가지로 iOS 앱을 개발하는데 필요한 각종 라이브러리와 도구들을 모아 놨습니다.

 

여기서 AWS SDK는 AWS와 상호작용 하기 위한 API를 제공해서 함수 호출하듯이 사용할 수 있게 해 줍니다.


꼭 AWS SDK를 써서 구현해야 할까?

사실 굳이 SDK를 꼭 쓸 필요는 없습니다. 결국 AWS SDK도 내부에서는 HTTP API를 호출하고 비즈니스 로직을 실행하는 거뿐이니, 대부분의 경우 SDK를 사용하지 않고 직접 구현하는 게 더 이해하기 쉽고 빠른 경우가 많습니다.

하지만 AWS의 경우는 굉장히 많은 기능이 있고, 보안도 신경써야 하고, 실수하기도 쉬워서 SDK를 쓰는 것을 선호합니다.


AWS SDK, Gradle에서 사용하기

AWS SDK도 다른 Gradle 라이브러리와 비슷하게 dependencies에 선언해 주면 됩니다.

dependencies {
    implementation("software.amazon.awssdk:bom:${Version.AWS_SDK}")
    implementation("software.amazon.awssdk:s3:${Version.AWS_SDK}")
}

가장 기본적인 형태: Public으로 공개된 Bucket에 업로드하기

🐜 S3Client Bean으로 등록하기

@Configuration
class AwsS3Config {
    @Bean
    fun s3Client(): S3Client {
        return S3Client.builder()
            .region(Region.AP_NORTHEAST_2)
            .build()
    }
}

 

🐜 업로드 하기

val key = "$directory/$fileName"

val objectRequest = PutObjectRequest.builder()
    .key(key)
    .bucket(bucketName)
    .build()

s3.putObject(objectRequest, RequestBody.fromBytes(file))

 

🐜 접근 URL 만들기

val encodedFileName = URLEncoder.encode(key, StandardCharsets.UTF_8.toString())
return "https://$bucketName.s3.$regionName.amazonaws.com/$encodedFileName"

 

🐜 최종

fun upload(
    fileName: String,
    directory: String,
    file: ByteArray,
): String {
    val key = "$directory/$fileName"

    val objectRequest = PutObjectRequest.builder()
        .key(key)
        .bucket(bucketName)
        .build()

    s3.putObject(objectRequest, RequestBody.fromBytes(file))

    val encodedFileName = URLEncoder.encode(key, StandardCharsets.UTF_8.toString())
    return "https://$bucketName.s3.$regionName.amazonaws.com/$encodedFileName"
}

보안 조금 신경 써서 TTL 있는 URL 사용하기

위의 버전과 업로드까지는 똑같고, 접근 URL을 만들 때 임시로 사용 가능한 URL을 생성하면 됩니다.

val request = GeneratePresignedUrlRequest(bucketName, objectKey)
    .withMethod(HttpMethod.GET)
    .withExpiration(Date().now().plusMinutes(5))
    
 client.generatePresignedUrl(request).toString()

반응형