토이 프로젝트를 진행하면서 AWS의 S3를 써야할 일이 생겼습니다.
S3업로드 하기위해 MavenRepository를 보다보니 기존에는 com.amazonaws의 aws-java-sdk-s3
를 사용하였었는데 software.amazon.awssdk s3
를 보게 되었습니다.
뭐가 차이가 있는걸까 궁금해하던 중에 스택오버플로우 글 에서 하나의 글을 확인할 수 있었습니다..
aws-sdk-java-v2 repository는 software.amazon.awssdk 라는 패키지 이름을 사용합니다.
하지만 java-sdk-v1 repository는 com.amazonaws를 사용합니다.
v2는 java1.8 기능들을 염두해두고 개발이 되었으며 v1보다 개발하기 쉽습니다.
저도 번역기로 돌린거라 정확하지 않지만 v2를 사용하여 개발하면좋다는 얘기인듯 합니다.
v2의 다양한 내용들은 aws sdk v2에서확인하시면 됩니다.
aws-sdk-java-v2의 Changelog
https://github.com/aws/aws-sdk-java-v2/blob/master/docs/LaunchChangelog.md
기존의 v2 버전은 기존의 com.amazonaws와 Bean을 생성하는 법 부터 달라졌습니다.
@Configuration
public class AWSS3Config {
private String accessKey;
private String secretKey;
private String region;
// @Value 어노테이션의 값들은 s3관련된 계정IAM의 accessKey, secretKey와 S3의 리전을 넣어주시면됩니다.
public AWSS3Config(@Value("${cloud.aws.s3.accessKey}") String accessKey,
@Value("${cloud.aws.s3.secretKey}") String secretKey,
@Value("${cloud.aws.s3.region}") String region) {
this.accessKey = accessKey;
this.secretKey = secretKey;
this.region = region;
}
@Bean
public AwsCredentials basicAWSCredentials() {
return AwsBasicCredentials.create(accessKey, secretKey);
}
@Bean
public S3Client s3Client(AwsCredentials awsCredentials) {
return S3Client.builder().region(Region.of(region))
.credentialsProvider(StaticCredentialsProvider.create(awsCredentials)).build();
}
}
@Slf4j
@Service
@RequiredArgsConstructor
public class AwsS3Service {
private final S3Client s3Client;
// Upload 하고자 하는 버킷의 이름
@Value("${cloud.aws.s3.bucket}")
private String bucketName;
// 저장하기 위해 사용할 prefix
// 저는 prefix가 필요하여 추가한것입니다 필수옵션은 아닙닏나.
@Value("${cloud.aws.s3.prefix}")
private String prefix;
public String upload(MultipartFile multipartFile, String filename) throws IOException {
return this.putS3(multipartFile, ㅔrefix + "/" + filename);
}
// 파일 업로드를 하기위한 PutObjectRequest를 반환합니다.
// 주의 사항은 com.amazonaws Package가 아닌 software.amazon.awssdk를 사용해야 합니다.
// key는 저장하고자 하는 파일의 이름(?)을 의미합니다.
private PutObjectRequest getPutObjectRequest(String key) {
return PutObjectRequest.builder()
.bucket(bucketName)
.key(key)
.build();
}
// MultipartFile을 업로드 하기위해 RequestBody.fromInputStream에 InputStream과 file의 Size를 넣어줍니다.
private RequestBody getFileRequestBody(MultipartFile file) throws IOException {
return RequestBody.fromInputStream(file.getInputStream(), file.getSize());
}
// S3Utilities를 통해 GetUrlRequest를 파라미터로 넣어 파라미터로 넘어온 key의 접근 경로를 URL로 반환받아 경로를 사용할 수 있다.
private String findUploadKeyUrl (String key) {
S3Utilities s3Utilities = s3Client.utilities();
GetUrlRequest request = GetUrlRequest.builder()
.bucket(bucketName)
.key(key)
.build();
URL url = s3Utilities.getUrl(request);
return url.toString();
}
// 실제 업로드 하는 메소드
private String putS3(MultipartFile file, String key) throws IOException {
PutObjectRequest objectRequest = getPutObjectRequest(key);
RequestBody rb = getFileRequestBody(file);
s3Client.putObject(objectRequest, rb);
return findUploadKeyUrl(key);
}
}
다음과 같이 하고 putS3에 MultipartFile을 업로드 해보면 정상적으로 동작하는 것을 확인할 수 있습니다.
개발하면서 최소한의 실행을위해 퍼블릭액세스 차단을 풀어놓고 테스트 하면 더 수월할듯 합니다.
저도 이글을 쓰는 순간에도 문서를 아직 보지 못하여 정확하게 변경된 부분은 기입하지 못하였습니다.
하지만 기존에 있는 프로젝트들도 유지보수를 할때 기존의 v1인 com.amazonaws.sdk
에서 v2인 software.amazon.awssdk
로 조금식 리펙토링을 해야할 듯 싶습니다.
시간이 되는대로 v2의 수정 내용을 번역기라도 돌려서 확인해보면 좋을듯 합니다.