SpringBoot 백엔드에서 AWS S3로 파일 업로드 하는 방법을 알아본다.
1. AWS 설정(S3버킷 생성 및 IAM 설정)
테스트용 S3 버킷을 간단히 생성한다.
IAM에서 S3 접근을 위한 계정 및 AccessKey 설정을 한다. 먼저 계정의 권한은 AmazonS3FullAccess를 부여한다.
다음으로 S3업로드 시 사용할 AccessKey를 생성한다.
2. SpringBoot 어플리케이션 설정
'spring-cloud-starter-aws' gradle 의존성을 추가한다.
implementation org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE
application.yml에서 S3관련 설정 정보를 추가한다.
cloud:
aws:
s3:
bucket: myapp-bucket
uploadPath: test/ # upload prefix
stack:
auto: false # CloudFormation 비활성화
region:
static: ap-northeast-2
credentials:
accessKey: ENC(xxxxxxxxxx)
secretKey: ENC(xxxxxxxxxx)
cloudfront: https://xxxxxxx.cloudfront.net/ # CloudFront연계용
필자는 S3에 이미지를 업로드하고 AWS CloudFront URL을 통해서 이미지 호출할 것이라서 coudfront URL정보까지 application.yml에 추가했다. 참고로 CloudFront와 S3연계는 본 내용과 별개임으로 여기서는 생략한다.
AmazonS3Config 클래스를 작성한다.
@Configuration
public class AmazonS3Config {
@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;
@Bean
public AmazonS3Client amazonS3Client() {
BasicAWSCredentials awsCredentials= new BasicAWSCredentials(accessKey, secretKey);
return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}
}
3. S3 업로드 샘플코드 작성 및 테스트
이제 업로드 샘플코드를 작성해본다. 먼저 아래와 같이 Upload Controller메소드를 작성한다.
@PostMapping(value = "/uploadImage")
public ResponseEntity uploadImage(@RequestParam("file") MultipartFile file) throws Exception{
String url = uploadService.uploadImage(file);
return new ResponseEntity<>(url, HttpStatus.OK);
}
다음으로 UploadService 클래스를 작성해준다.
@Value("${cloud.aws.s3.bucket}")
private String bucket;
@Value("${cloud.aws.cloudfront}")
private String cfUrl;
@Value("${cloud.aws.s3.uploadPath}")
private String uploadPath;
@Autowired
private AmazonS3Client amazonS3Client;
....
public String uploadImage(MultipartFile file) throws Exception{
String originfileName = file.getOriginalFilename();
String filePath = uploadPath + UUID.randomUUID() + originfileName.substring(originfileName.lastIndexOf("."));;
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(file.getContentType());
metadata.setContentLength(file.getSize());
metadata.addUserMetadata("originfilename", URLEncoder.encode(originfileName, StandardCharsets.UTF_8));
PutObjectResult result = amazonS3Client.putObject(bucket, filePath, file.getInputStream(), metadata);
return cfUrl + filePath;
}
Postman 등을 통해 테스해보면 S3에 잘 업로드 된다.
4. AmazonS3Client Credentials 추가 내용
위에서 AmazonS3Client 빈 설정에서 credentials 설정 시 accessKey와 secretKey를 직접 제공해주는 AWSStaticCredentialsProvider()를 사용했다. 어플리케이션 소스에서 키 값들을 관리하는 것이 보안적으로 괜찮은 방법인가 싶어서 다른 방법들을 찾아보다 DefaultAWSCredentialsProviderChain 클래스를 찾았는데 상황에 따라서 좀 더 유연하게 사용이 가능할 것 같아서 추가적으로 정리해본다.
DefaultAWSCredentialsProviderChain 클래스 내부를 보면 아래와 같이 여러개의 CredentialsProvider가 설정되어 있는 것을 확인할 수 있다.
public class DefaultAWSCredentialsProviderChain extends AWSCredentialsProviderChain {
private static final DefaultAWSCredentialsProviderChain INSTANCE
= new DefaultAWSCredentialsProviderChain();
public DefaultAWSCredentialsProviderChain() {
super(new EnvironmentVariableCredentialsProvider(),
new SystemPropertiesCredentialsProvider(),
WebIdentityTokenCredentialsProvider.create(),
new ProfileCredentialsProvider(),
new EC2ContainerCredentialsProviderWrapper());
}
public static DefaultAWSCredentialsProviderChain getInstance() {
return INSTANCE;
}
}
그리고 주석을 보면 적용되는 우선순위는 아래와 같다.
1. 환경변수: 환경변수에 설정된 다음 키 값들을 가져운다. AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (RECOMMENDED since they are recognized by all the AWS SDKs and CLI except for .NET),
or AWS_ACCESS_KEY and AWS_SECRET_KEY (only recognized by Java SDK)
2. Java System Properties : aws.accessKeyId and aws.secretKey
3. Credential profiles file : at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI 4.
4. Amazon EC2 Container Credentials: 환경변수 AWS_CONTAINER_CREDENTIALS_RELATIVE_URI가 설정 시 Amazone ECS에서 로드
5. 인스턴스 Profile Credentials: the Amazon EC2 metadata service Web Identity Token credentials from the environment or container.
빈설정은 아래와 같이 변경 해주면 될것이다.
@Bean
public AmazonS3Client amazonS3Client() {
return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(DefaultAWSCredentialsProviderChain.getInstance())
.build();
}
'개발 > SpringBoot' 카테고리의 다른 글
springdoc swagger ui disable Petstore(swagger-ui enabled false not working) (0) | 2023.06.19 |
---|---|
SpringBoot3(SpringBatch5) 동일(or 이전) 파라미터 재사용 해결 (0) | 2023.06.05 |
SpringBoot OpenFeign(FeignClient) 사용하기 (1) | 2023.05.31 |
SpringBoot cannot deserialize from Object value 에러 (0) | 2023.05.27 |
Kafka 구성 및 SpringBoot 연동 (0) | 2023.03.13 |
댓글