기본적인 AWS S3를 생성 및 권한 설정 후 Spring Boot에 적용하는 것을 정리해보았다.
AWS S3 Bucket 생성
1. 버킷 이름과 리전을 선택하고 모든 퍼블릭 엑세스 차단을 선택 해체해 버킷을 생성한다.
AWS S3 정책 편집
버킷 정책 편집
1. 생성된 bucket의 권한 탭을 클릭 해 버킷 정책을 편집한다.
2. 버킷 ARN을 복사하고 정책 생성기를 클릭
버킷 정책을 생성
- Select Type of Policy → S3 Bucket Policy
- Principal → *
- Actions → Get Object, Put Object
- ARN → 이 전에 복사한 ARN
1. 정보 입력 후 Add Statement 버튼을 클릭
2. 생성하려는 정책을 다시 확인 후 Generate Policy 버튼을 클릭
3. 생성된 정책 JSON Document를 복사
생성된 버킷 정책으로 편집
1. 복사한 정책 JSON Document를 정책에 붙혀넣는다.
2. 변경 사항 저장을 하면 오류가 발생한다.
3. 아래와 같이 Resource에 "/*"를 추가한다.
4. 버킷 정책이 생성된 것을 확인할 수 있다.
IAM 사용자 권한 추가
S3에 접근하기 위해서는 IAM 사용자에게 S3 접근 권한을 주고, 그 사용자의 액세스 키, 비밀 엑세스 키를 사용해야 한다.
1. IAM Console > 사용자 > 사용자 추가 버튼 클릭
2. 사용자 이름을 입력하고 프로그래밍 방식 액세스를 선택
3. 기본 정책 직접 연결을 클릭하고 AmazonS3FullAccess권한을 부여 후 사용자를 생성
4. 엑세스키는 다시 볼 수 없으므로 csv로 다운로드 받아 보관해야한다.
Spring Boot에 적용
AWS 의존성 추가 및 설정
build.gradle
dependencies {
...
// S3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.1.RELEASE'
...
}
application.yml
cloud:
aws:
credentials:
accessKey: Access key ID # IAM 사용자 엑세스 키
secretKey: Secret access key # IAM 사용자 비밀 엑세스 키
s3:
bucket: mys3bucketname # 버킷명
region:
static: ap-northeast-2 # 리전
stack:
auto: false # Spring Cloud는 환경 또는 스택을 기반으로 이를 자동으로 감지
Config 및 Util 클래스 생성
S3 Config Class
@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;
@Bean
public AmazonS3Client amazonS3Client() {
BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build();
}
}
S3 Util Class
@Component
@RequiredArgsConstructor
public class S3UploadUtil {
private final AmazonS3Client amazonS3Client;
@Value("${cloud.aws.s3.bucket}")
public String bucket; // S3 버킷
// S3 파일 업로드
public String upload(MultipartFile multipartFile, String dirName) throws IOException {
// MultipartFile -> File
File convertFile = convert(multipartFile)
.orElseThrow(() -> new IllegalArgumentException("file convert error")); // 파일을 변환할 수 없으면 에러
// S3에 저장할 파일명
String fileName = dirName + "/" + UUID.randomUUID() + "_" + convertFile.getName();
// S3에 파일 업로드
amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, convertFile).withCannedAcl(CannedAccessControlList.PublicRead));
String uploadImageUrl = amazonS3Client.getUrl(bucket, fileName).toString();
// 로컬 파일 삭제
convertFile.delete();
return uploadImageUrl;
}
// S3 파일 삭제
public void delete(String path) {
amazonS3Client.deleteObject(bucket, path);
}
// 파일 convert 후 로컬에 업로드
private Optional<File> convert(MultipartFile file) throws IOException {
File convertFile = new File(System.getProperty("user.dir") + "/" + file.getOriginalFilename());
if (convertFile.createNewFile()) { // 바로 위에서 지정한 경로에 File이 생성됨 (경로가 잘못되었다면 생성 불가능)
try (FileOutputStream fos = new FileOutputStream(convertFile)) { // FileOutputStream 데이터를 파일에 바이트 스트림으로 저장하기 위함
fos.write(file.getBytes());
}
return Optional.of(convertFile);
}
return Optional.empty();
}
}
테스트
1. S3 Controller Class
@RequiredArgsConstructor
@RequestMapping(value = "aws-s3")
@RestController
public class S3TestController {
private final S3UploadUtil s3UploadUtil;
@PostMapping(name = "S3 파일 업로드", value = "/file")
public String fileUpload(@RequestParam("files") MultipartFile multipartFile) throws IOException {
s3UploadUtil.upload(multipartFile, "test"); // test 폴더에 파일 생성
return "success";
}
@DeleteMapping(name = "S3 파일 삭제", value = "/file")
public String fileDelete(@RequestParam("path") String path) {
s3UploadUtil.delete(path);
return "success";
}
}
2. Postman으로 파일 업로드 API 테스트
3. Postman으로 파일 삭제 API 테스트
'AWS' 카테고리의 다른 글
GitHub Action + S3 + CodeDeploy를 이용한 CI/CD (2/2) (2) | 2021.10.08 |
---|---|
GitHub Action + S3 + CodeDeploy를 이용한 CI/CD (1/2) (0) | 2021.10.08 |
AWS RDS + MySQL 구축 (0) | 2021.09.27 |
Amazon EBS(Elastic Block Storage) (0) | 2021.09.16 |
Amazon EC2(Elastic Compute Cloud) (0) | 2021.09.16 |