AWS S3 연동을 하기 위해 구글링을 했지만 대부분의 경우 AwsS3Config / AwsS3Service / AwsS3Controller / application-aws.yml 네 가지 파일로 나뉘어 있었다.
하지만 설계를 하면서 2가지의 이유로 구조를 조금 바꾸었다.
우선, 초기 AWS S3를 연동하고자 했던 목적은 프로필 사진 업로드를 위한 것이었지만 이후 게시물에 대한 사진 또한 올리게 될 경우 즉 확장성을 고려하여 따로 utility 패키지로 빼서 관리하기 위함이었다.
두번째이자 마지막은 설계에 있어서의 통일성을 가지고자 패키지 구조를 조금 바꾸어야 했다.
그래서 선택한 구조는 AwsS3Manager / AwsProperties / AwsS3Properties / AppConfig / aws.yml / application.yml이었다.
기존 설계는 구글링을 하면 많이 나오기 때문에 내가 새로 만들게 된 녀석만 올릴거야요.
implementation 'io.awspring.cloud:spring-cloud-starter-aws:2.4.0'
application.yml
spring:
config:
import:
- classpath:properties/aws.yml
# 기본 multipart file의 크기는 1MB로 더 큰 용량을 사용하기 위해 설정
servlet:
multipart:
max-file-size: 5MB
max-request-size: 5MB
aws.yml : 물론, 환경변수 등록은 필요하다.
aws:
access-key: ${AWS_ACCESS_KEY:aws-access-key}
secret-key: ${AWS_SECRET_KEY:aws-secret-key}
s3:
region: ap-northeast-2
bucket: ${AWS_S3_BUCKET:aws-s3-bucket}
AppConfig
@Configuration
public class AppConfig {
@Bean
public AmazonS3 amazonS3(final AwsProperties awsProperties, final AwsS3Properties awsS3Properties) {
final AWSCredentials credentials = new BasicAWSCredentials(awsProperties.getAccessKey(), awsProperties.getSecretKey());
return AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(awsS3Properties.getRegion())
.build();
}
# 기존과는 다르게 AwsS3Manager를 Service로 두지 않았기 때문에 AppConfig에서 AwsS3Manager를 bean으로 등록시켜준다.
@Bean
public AwsS3Manager awsS3Manager(final AmazonS3 amazonS3, final AwsS3Properties awsS3Properties) {
return new AwsS3Manager(amazonS3, awsS3Properties.getBucket());
}
}
AwsProperties : AWS에 대한 properties
@ConfigurationProperties(prefix = "aws")
@ConstructorBinding
@RequiredArgsConstructor
@Getter
public class AwsProperties {
private final String accessKey;
private final String secretKey;
}
AwsS3Properties : AWS 중 S3에 대한 properties
@ConfigurationProperties(prefix = "aws.s3")
@ConstructorBinding
@RequiredArgsConstructor
@Getter
public class AwsS3Properties {
private final String region;
private final String bucket;
}
AwsS3Manager
@RequiredArgsConstructor
public class AwsS3Manager {
private final AmazonS3 amazonS3;
private final String bucket;
public List<String> uploadFiles(final Function<String, String> titleGenerator, final List<MultipartFile> multipartFile) {
final List<String> fileNameList = new ArrayList<>();
multipartFile.forEach(file -> {
final String originalFileName = file.getOriginalFilename();
final String fileName = titleGenerator.apply(originalFileName);
final ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(file.getSize());
objectMetadata.setContentType(file.getContentType());
try (final InputStream inputStream = file.getInputStream()) {
amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
} catch (final IOException e) {
throw new IllegalArgumentException();
}
fileNameList.add(fileName);
});
return fileNameList;
}
}