Spring에서 Naver Cloud Object Storage 사용할 때 에러 사냥하기

henrywoo·2022년 9월 19일
4
post-thumbnail

배경

학교 동아리에서 교내 학생 관리 서비스를 NestJS에서 SpringBoot로 마이그레이션 하던 중, 서버에 직접 저장하던 이미지를 클라우드로 저장해 좀 더 복구/유지보수하기 좋게 만들기로 했다.

하지만 우리 동아리는 "AWS는 외국 서버기 때문에 그곳에 학생들 데이터를 저장할 수 없다"라는 학교의 말도 안되는 주장때문에 Naver Cloud를 쓰고 있었다. 학교의 지원을 받기 위해서는 AWS S3 대신 Naver Cloud가 서비스하고 있는 Object Storage를 사용해야 했다.

에러 사냥 시작

기존 Spring으로 AWS S3를 사용하기 위해 지원하는 디펜던시가 있었다.

implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

이 디펜던시를 이용해 Naver Cloud Object Storage도 Spring 서버와 연동할 수 있을 것 같다는 동아리 선배의 조언에, 이 디펜던시를 사용하기로 했다.

일단 AWS S3를 어떻게 연동하는지 찾아보다가, AmazonS3Client라는 빈을 주입받아 그 빈을 통해 S3 저장소에 업로드한다는 것을 알았다. 또한 그 AmazonS3Client를 생성하기 위해 application.yml 환경변수를 통해 설정하는 법과 @Configuration 설정 파일을 생성해 직접 빈을 생성하는 방법 두가지가 있다는 것을 알았다.

private final AmazonS3Client amazonS3Client;

private String uploadToS3(File uploadFile, String fileName) {
    amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, uploadFile).withCannedAcl(CannedAccessControlList.PublicRead));
    return amazonS3Client.getUrl(bucket, fileName).toString();
}

처음에는 귀찮아서 application.yml 파일에 정보를 집어넣어 AmazonS3Client를 주입받았다.

cloud:
  aws:
    credentials:
      access-key: 액세스키
      secret-key: 시크릿키
    stack:
      auto: false
    region:
      static: ap-northeast-2
    s3:
      bucket: 버킷이름

하지만 이 방법에서는 다른 엔드포인트(AWS S3 외의 다른 클라우드 저장소 서비스)를 명시할 방법이 없었다. 그 말인 즉슨, Naver Cloud의 Object Storage를 사용하려면 다른 Config 방법을 사용해야 한다는 것이다.

그리하여 위에서 언급한 @Configuration 설정 파일을 생성해 직접 빈을 생성하는 방법을 사용했다.

여러 자료를 찾아봤지만, Naver Cloud가 국내 서비스라 그런지 관련 자료가 많이 없었다.
Naver Cloud에서 제공하는 문서가 있었다.
https://guide.ncloud-docs.com/docs/storage-storage-8-1

위의 문서와 다른 AWS S3 연동 블로그를 참고해서 아래 Config 설정 코드를 만들었다.

cloud:
  aws:
    credentials:
      access-key: 액세스키
      secret-key: 시크릿키
    stack:
      auto: false
    region:
      static: kr-standard
    s3:
      endpoint: https://kr.object.ncloudstorage.com
      bucket: 버킷이름
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class S3Config {

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

    @Value("${cloud.aws.credentials.secret-key}")
    private String secretKey;

    @Value("${cloud.aws.region.static}")
    private String region;

    @Value("${cloud.aws.s3.endpoint}")
    private String endPoint;

    @Bean
    public AmazonS3Client amazonS3Client() {
        BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey,secretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, region))
                .build();
    }
}

오류 없이 잘 실행되기를 기도했으나, 역시 실패했다.

위의 Naver Cloud 문서를 따라 region을 kr-standard로 설정했지만, Constructor threw exception; nested exception is java.lang.IllegalArgumentException: The region 'kr-standard' is not a valid region! 오류가 발생했다.

성공

리전 값이 잘못되었다는 오류 메시지에 따라, application.yml에서 다시 AWS S3를 사용할 때 서울을 명시하던 리전인 ap-northeast-2로 바꿨다.

cloud:
  aws:
    credentials:
      access-key: 액세스키
      secret-key: 시크릿키
    stack:
      auto: false
    region:
      static: ap-northeast-2
    s3:
      endpoint: https://kr.object.ncloudstorage.com
      bucket: 버킷이름

그 결과, 업로드 성공!!!

postman
fff

혹시 이해 안되시거나 또 오류나는 부분이 있으면 댓글 달아주세요!
같이 고쳐봅시다 :)

레퍼런스

profile
가보자 가보자

2개의 댓글

comment-user-thumbnail
2024년 2월 6일

안녕하세요. 궁금한 점이 있는데요. 저도 AWS S3 사용중인데 네이버 클라우드의 object storage를 사용하게 되었습니다. 아직 공부중이라 잘 몰라서 이 글을 보고 따라해보려고 하는데요. 이 포스팅처럼 세팅하면 s3는 삭제해도 되는건가요?

1개의 답글