정리정리

스프링 부트 버전에 따른 io.awspring.cloud s3 연결시 주의점 본문

Spring

스프링 부트 버전에 따른 io.awspring.cloud s3 연결시 주의점

wlsh 2023. 4. 20. 00:11

io.awspring.cloud의 spring-cloud-starter-aws 라이브러리를 이용해 s3를 연결하다가 생긴 문제점에 대해 찾아보고 정리하는 포스팅입니다.

문제 상황 및 해결

스프링 부트 3에서 작성한 s3 연결 예제가 기존의 스프링 부트 2를 사용하는 프로젝트에서 작동하지 않았습니다. 문제 원인은 제가 마음대로 작성한 properties 키 이름 때문이었습니다.

#기존 문제가 발생한 키 이름
#ncp:
#  credentials:
#    accessKey: accessKey
#    secretKey: secretKey
#  s3:
#    bucket: bucketName
#    endpoint: https://kr.object.ncloudstorage.com
#  region:
#    static: kr-standard

#수정한 키 이름
cloud.aws:
  credentials:
    accessKey: accessKey
    secretKey: secretKey
  s3:
    endpoint: https://kr.object.ncloudstorage.com
    region:
      static: kr-standard
    bucket: bucketName

원래는 스프링 부트가 자동으로 AWS 관련 설정들을 세팅해주기 때문에 수정한 것처럼 cloud.aws라는 prefix를 가져야 합니다.

하지만 spring-cloud-starter-aws가 org.springframework.cloud에서 io.awspring.cloud로 분리되었고, 처음부터 스프링 부트 3으로 예제를 작성하느라 패키지의 분리로 인해 더 이상 AmazonS3을 빈으로 등록하지 않는다고 착각을 하게 되었습니다.

그래서 예제에서 NCP를 사용하기 때문에 제 마음대로 키 이름을 바꿨다가 스프링 부트 2를 사용하는 프로젝트에서 설정들이 제대로 세팅되지 않아 예외가 발생했었습니다.

스프링 부트 3에서 AmazonS3가 빈으로 등록되지 않는 이유

원인을 좀 더 자세하게 알고 싶어서 구글링을 하다가 스택오버플로우를 통해 스프링 부트 3에서의 다음과 같은 변화가 있다는 것을 알게 되었습니다.

Spring Boot 2.7 introduced a new META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports file for registering auto-configurations, while maintaining backwards compatibility with registration in spring.factories. With this release, support for registering auto-configurations in spring.factories has been removed in favor of the imports file.
원본 링크

단순히 해석을 해보면 스프링 부트 2.7까지는 레거시 호환을 위한 auto-configuration 기능을 하는 spring.factories가 스프링 부트 3이 되면서 제거되었습니다. 

그런데 spring-cloud-starter-aws 2.4 버전이 spring.factories에 의존하기 때문에 자연스럽게 해당 기능을 사용하지 않은 스프링 부트 3에서는 AmazonS3가 등록이 되지 않게 된 것 같습니다.

실제로 spring-cloud-aws-autoconfigure 라이브러리를 살펴보면 spring.factories라는 파일이 있는 것을 볼 수 있고, 해당 파일에서는 자동으로 우리가 s3에 연결할 때 필요한 값들을 세팅해 주는 Configuration들이 존재합니다.

예를 들어 AccessKey와 SecretKey를 설정해 주는 ContextCredentialsAutoConfiguration 클래스를 확인해 보겠습니다.

해당 클래스에서 cloud.aws.credentials라는 prefix를 통해 accessKey와 secretKey를 등록해 줍니다.

당연히 스프링 부트 3에서는 저 브레이크 포인트에 걸리지 않습니다. 좀 더 직접적으로 확인해 보기 위해 이 클래스가 빈으로 등록이 되는지 테스트를 해보겠습니다.

예상대로 스프링 부트 2와 달리 3에서는 spring.factoies에 있는 클래스들이 빈으로 등록이 되지 않고, 그렇기 때문에 자연스럽게 해당 설정들이 필요한 AmazonS3가 빈으로 등록이 되지 않는다고 판단이 됩니다.

따라서 스프링 부트 3을 사용하게 되면, 따로 설정 값들을 받아와 AmazonS3을 따로 빈으로 등록해 주는 작업이 필요합니다.

@Configuration
public class S3Config {

    @Value("${cloud.aws.credentials.accessKey}")
    private String accessKey;

    @Value("${cloud.aws.credentials.secretKey}")
    private String secretKey;
    
    @Value("${cloud.aws.s3.region}")
    private String region;

    //따로 Bean으로 등록을 해줘야 함
    @Bean
    public AmazonS3 s3Client() {
        AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
        return AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withRegion(region)
                .build();
    }
}

번외

글을 포스팅하는 2023.04.20을 기준으로 새로운 버전의 spring-cloud-aws가 개발 중인 것 같습니다.

여기에서는 어떤 식으로 바뀔지 궁금하네요. (사실 s3 자체를 사용해 본 게 며칠 전이라 뭐가 바뀌었는지 잘 모르겠지만요ㅎㅎ)

참조

https://stackoverflow.com/questions/74852003/which-spring-cloud-aws-version-should-be-used-with-spring-boot-3

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#auto-configuration-files

 

Comments