Spring Boot + AWS-SDK-Java-v2 Multipart File Upload

윤들윤들·2021년 2월 22일
4
post-thumbnail

토이 프로젝트를 진행하면서 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의 수정 내용을 번역기라도 돌려서 확인해보면 좋을듯 합니다.

profile
Front&BaackEnd를 재미있게 공부하고싶은 개발자 YundleYundle

0개의 댓글