MinIO Object Storage II - JAVA Sample

업데이트:

개요

지난 번 MinIO를 설명하면서 S3와 완벽히 호환한다고 이야기 하였으므로, 이에 대해 AWS S3 JAVA SDK v2를 이용한 샘플 코드를 설명한다.

설정

  • S3의 CredentialsProvider는 여러 가지가 존재하지만 application.properties를 활용한 설정을 사용하는 방법과 DefaultProvider 사용하는 방법을 유연하게 전환할 수 있는 샘플 코드를 설명한다.

S3Properties.java

@Data
@Configuration
@ConfigurationProperties(prefix = "s3")
public class S3Properties {

  private String endpointUrl;
  private String accessKeyId;
  private String secretAccessKey;
  private String region;

}
  • ConfigurationProperties를 이용하여 “application.properties”에 설정한 아래의 설정들을 가져와 설정한다.
    • s3.endpoint-url : S3 API URL을 설정한다.
    • s3.access-key-id : S3에서 발급한 Access Key를 설정한다.
    • s3.secret-access-key : 위의 Access key의 Secrey Key를 설정한다.
    • s3.region : S3 연결 리전 명칭을 설정한다.

S3Config.java

private AwsCredentialsProvider getAwsCredentialsProvider() {
  if (StringUtils.isNotBlank(this.s3Properties.getAccessKeyId()) && StringUtils.isNotBlank(this.s3Properties.getSecretAccessKey())) {
    return StaticCredentialsProvider.create(
        AwsBasicCredentials.create(this.s3Properties.getAccessKeyId(), this.s3Properties.getSecretAccessKey()));
  } else {
    return DefaultCredentialsProvider.create();
  }
}
  • S3Properties에서 설정한 정보를 이용하여 CredentialsProvider를 동적으로 설정한다.
    • “AccessKeyId”와 “SecretAccessKey”를 설정한 경우, AwsBasicCredentials를 이용한 설정을 사용하도록한다.
  • DefaultCredentialsProvider는 SDK 내에서 동적으로 어떤 CredentialsProvider를 사용할지 아래의 순서대로 확인하여 인증 가능하도록 한다.
    • SystemPropertyCredentialsProvider : JAVA 시스템 설정 내 “aws.accessKeyId”와 “aws.secretAccessKey”를 이용한다.
    • EnvironmentVariableCredentialsProvider : 환경 변수로 설정된 “AWS_ACCESS_KEY_ID”와 “AWS_SECRET_ACCESS_KEY”를 사용한다.
    • WebIdentityTokenFileCredentialsProvider : JAVA 시스템 설정 내 혹은 환경 변수에 존재하는 Web ID 토큰을 사용한다.
    • ProfileCredentialsProvider : AWS 인증 정보를 저장하는 기본 파일인 ‘~/.aws/credentials’를 이용해 AWS SDK와 CLI와 설정을 공유한다.
    • ContainerCredentialsProvider : security manager가 해당 변수에 접근할 권한을 가진 경우, Amazon EC2 컨테이너 서비스에 “AWS_CONTAINER_CREDENTIALS_RELATIVE_URI” 환경 변수가 설정하여 사용한다.
    • InstanceProfileCredentialsProvider : Amazon EC2 메타 서비스를 이용하여 인스턴스 프로필을 가져온다.
public S3Client s3Client() {
  S3ClientBuilder s3ClientBuilder = S3Client.builder().credentialsProvider(this.getAwsCredentialsProvider());
  if (StringUtils.isNotBlank(this.s3Properties.getEndpointUrl())) {
    s3ClientBuilder.endpointOverride(URI.create(this.s3Properties.getEndpointUrl()));
  }
  if (StringUtils.isNotBlank(this.s3Properties.getRegion())) {
    s3ClientBuilder.region(Region.of(this.s3Properties.getRegion()));
  }
  return s3ClientBuilder.build();
}
  • S3ClientBuilder를 이용하여 위에서 사용된 기본 방법을 이용하여 CredentialsProvider를 설정한다.
  • “application.properties” 내 “EndpointUrl”, “Region” 정보가 있을 때는 해당 정보를 보도록 하고 없으면 위에서 설명한 DefaultCredentialsProvider에서 제공하는 방법으로 주입 받도록 처리한다.
    • “EndpointUrl”을 설정하지 않으면 “Region” 내 “EndpointUrl” 사용하기 때문에 “Region”은 반드시 설정해야 하며, 설정되지 않은 경우 오류가 발생한다.

실행

S3Service.java

listObjects

public List<S3Object> listObjects(String bucket, int size) {
  try {
    return this.s3Client.listObjects(ListObjectsRequest.builder().bucket(bucket).maxKeys(size).build())
        .contents();
  } catch (Exception e) {
    e.printStackTrace();
    return Collections.emptyList();
  }
}
  • S3의 특정 bucket에 존재하는 Object 정보 size 단위로 페이징 처리하여 가져오는 listObjects를 이용한 샘플 코드이다.

getObject

public ResponseEntity<ByteArrayResource> getObject(String bucket, String key) {
  try {
    ResponseInputStream<GetObjectResponse> responseInputStream = this.s3Client.getObject(GetObjectRequest.builder().bucket(bucket).key(key).build());
    GetObjectResponse getObjectResponse = responseInputStream.response();
    return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + key)
        .contentType(MediaType.valueOf(responseInputStream.response().contentType()))
        .contentLength(getObjectResponse.contentLength())
        .lastModified(getObjectResponse.lastModified())
        .body(new ByteArrayResource(responseInputStream.readAllBytes()));
  } catch (Exception e) {
    e.printStackTrace();
    return ResponseEntity.internalServerError().build();
  }
}
  • S3에 생성된 bucket 내 key에 해당하는 Object 정보를 가져와서 Reponse로 해당 파일을 반환하는 getObject를 활용한 샘플 코드이다.
  • GetObjectResponse를 반환하여 Object 정보를 여러 방법거나, OutputStream을 이용해 파일 생성 등 다양하게 활용 가능하다.

putObject

public boolean putObject(String bucket, String key, String path) {
  try {
    return this.s3Client.putObject(PutObjectRequest.builder().bucket(bucket).key(key).build(), Paths.get(path))
        .sdkHttpResponse()
        .isSuccessful();
  } catch (Exception e) {
    e.printStackTrace();
    return false;
  }
}
  • S3에 생성된 bucket 내 key에 해당하는 Object를 시스템 내 path에 위치한 파일로 덮어쓰는 putObject를 이용한 샘플 코드이다.
  • S3는 기본적으로 key에 Object를 설정하므로, Versioning 설정을 하지 않은 상태라면 기존 파일 정보를 백업하지 않고 덮어써진다.

copyObject

public boolean copyObject(String sourceBucket, String sourceKey, String destinationBucket, String destinationKey) {
  try {
    return this.s3Client
        .copyObject(CopyObjectRequest.builder()
            .sourceBucket(sourceBucket).sourceKey(sourceKey)
            .destinationBucket(destinationBucket).destinationKey(destinationKey).build())
        .sdkHttpResponse()
        .isSuccessful();
  } catch (Exception e) {
    e.printStackTrace();
    return false;
  }
}
  • S3에 생성된 sourceBucket 내 sourceKey에 해당하는 Object를 destinationBucket의 destinationKey로 복사하는 putObject를 이용한 샘플 코드이다.

deleteObject

public boolean deleteObject(String bucket, String key) {
  try {
    return this.s3Client.deleteObject(DeleteObjectRequest.builder().bucket(bucket).key(key).build())
        .sdkHttpResponse()
        .isSuccessful();
  } catch (Exception e) {
    e.printStackTrace();
    return false;
  }
}
  • S3에 생성된 bucket 내 key에 해당하는 Object를 삭제하는 deleteObject를 이용한 샘플 코드이다.

여담

  • Spring Boot 3.2 버전에서는 Spring Framework 6.1 버전을 도입하여 “@RequestMapping”과 관련한 어노테이션들에서 “@PathVariable” 어노테이션을 사용할 때, “name”과 “value”으로 어느 값을 변수에 할당할지 명시하지 않으면 “Ensure that the compiler uses the ‘-parameters’ flag.” 오류가 발생한다.
  • Spring Framework가 5에서 6으로 버전이 올라가면서 “LocalVariableTableParameterNameDiscoverer”가 삭제되어 컴파일 단계에서 매개 변수 이름을 추론하는 기능을 기본적으로 제공하지 않으므로, 사용하고자 하는 경우 컴파일 설정에 Java 8 이상에서는 ‘-parameters’, Kotlin은 ‘-java-parameters’ 플래그를 추가하여 해당 기능을 사용할 수 있도록 변경되었다.

소스

Sample Code는 여기에서 확인 가능합니다.

이전

MinIO Object Storage

참고

댓글남기기