io.awspring 라이브러리를 활용한 Spring-Amazon S3 연동

2023. 9. 6. 22:43Spring

728x90

개요

최근에 Spring 환경 프로젝트에서 S3로 파일을 업로드를 해야 하는 일이 있었다.

이전에는 org.springframework.cloud 라이브러리를 활용했는데, 상당 기능이 deplicate 되어 있었다.

따라서 io.awspring-s3 라이브러리를 활용했는데, 이전보다 훨씬 S3를 이용하는 것이 쉬웠다 세상 좋아졌네

위 라이브러리를 통한 S3 파일 업로드 구현 과정을 설명하고자 한다

 

전체 샘플 코드는 아래 링크로

https://github.com/phjppo0918/spring-io-awspring-s3-practice

0. 버킷 생성

이름 넣고, 리전 한국으로 설정하고, 퍼블릭 엑세스 차단 해제하고 시작하자

 

1. 라이브러리 추가

    implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.2")
    implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3'

2. properties 설정

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB
  cloud:
    aws:
      credentials:
        access-key: "asdf"
        secret-key: "asdf"
      s3:
        bucket: "asdfasdf"

- multipart 용량 제한을 설정할 수 있다. default는 20MB이다.

- 본인의 지갑에 현금이 갑자기 꼴도 보기 싫다면, aws 키를 그대로 담은 채 push하여 전 세계로 IAM 계정을 널리 알리면 된다.

- S3.bucket는 필자가 직접 제작한 custom properties이다. Repository에서 bucket name 설정 시 사용한다.

3. 예시 Controller & Service

@RestController
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@RequestMapping("images")
public class ImageController {
    ImageService imageService;

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public String create(@RequestPart MultipartFile file) {
        return imageService.create(file);
    }
}


@Service
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@RequiredArgsConstructor
public class ImageService {
    ImageRepository imageRepository;

    public String create(MultipartFile file) {
        return imageRepository.save(file);
    }
}

@RequestPart를 통해서 MultiPartFile를 받아온다. List<MultiPartFile> 로 해서 다수개를 받을 수도 있다. 

 

 

4. Repository 설정

@Repository
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class ImageRepository {
    S3Template s3template;
    String bucketName;

    public ImageRepository(S3Template s3template,
                           @Value("${spring.cloud.aws.s3.bucket}") String bucketName) {
        this.s3template = s3template;
        this.bucketName = bucketName;
    }

    public String save(MultipartFile file) {
        final S3Resource result = s3template.upload(bucketName, file.getOriginalFilename(), getInputStream(file));
        return getUrl(result);
    }

    private InputStream getInputStream(MultipartFile file) {
        try {
            return file.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException();
        }
    }

    private String getUrl(S3Resource s3Resource) {
        try {
            return s3Resource.getURL().toString();
        } catch (IOException e) {
            throw new RuntimeException();
        }
    }
}

별도 설정 없이 간단하게 S3Template를 사용할 수 있다. 나때는 Client 직접 설정하고 별 난리를 다 했는데 세상 좋아졌다.

upload 시 file name에 확장자를 붙여서 저장하도록 하자. 안그러면 아래와 같이 쓰레기가 만들어진다.

 

참고로 파일 외에 store & read를 이용해서 json 형태로 객체 저장도 되는듯 하다(아래 참고 참조)

 

5. 엑세스 권한 설정

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1405592139000",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::버킷이름/*",
                "arn:aws:s3:::버킷이름"
            ]
        }
    ]
}

버킷 정책에 추가하면 된다.

6. 확인

파일 클릭하면 이미지가 나올 것이다.

참고

https://docs.awspring.io/spring-cloud-aws/docs/3.0.0-M1/reference/html/index.html

728x90