S3 Bucket: deleteObjects - MultiObjectDeleteException
발생한 문제
프로젝트에서 s3 버킷에 사진을 업로드하는 기능을 작성하고 Spring boot 스케쥴러를 통해 삭제하는 기능을 구현하였다.
삭제가 되는지 기능 테스트를 해보려고 했는데 AccessDenied 되며 403 에러가 떴다.
처음에 이해가 안되었던 부분은 S3 버킷에 대한 권한을 IAM 으로 AmazonS3FullAccess라는 정책을 모두 주었다고 s3 버킷을 만드신 조원분께서 말씀하셨기에 업로드 기능 되고, 고아객체를 판별하여 삭제하기 위해 s3에서 Object List 조회 기능도 되지만 삭제 기능만 안된다는 것이 이해가 안되었다.
@Scheduled(cron = "1 * * * * *") // 매일 02시 스케쥴
public void deleteOrphanImage() {
List<String> dbImgList = contentsRepository.findAllBy(ImgUrlMapping.class) // url 주소 값만 받아옴.
.stream() // 스트림
.filter(url -> url != null) // url null 제거
.map(url ->
url.getImgUrl() // DBImgUrl 타입을 Spring으로 변경
.split("/")[url.getImgUrl().split("/").length-1]) // url주소 -> 파일명.png 분리
.collect(Collectors.toList()); // Stream 바이트를 List 객체로 collect
List<DeleteObjectsRequest.KeyVersion> keys = s3Service.getImageKeys(); // s3로부터 img list 받아옴.
keys.stream().forEach(key -> {
System.out.println(key.getKey());
if (dbImgList.contains(key.getKey())) { // key를 db에서 가지고 있으면 삭제 List에서 제거
keys.remove(key);
}
});
// S3 삭제요청
s3Service.deleteObjects(keys);
}
해결 및 시도 방법
1. 구글링 할 수 있는 관련된 키워드를 다해본 듯 하다. 대부분 권한에 대한 문제였고, s3 버킷 자체에서도 정책을 관리하고 ACL 활성화 옵션에 대해서 잘못 지정한 부분이 있는지 찾아보았다. 대략 반나절 시간이 지났고, 필수 요구 기능이 아니기 때문에 포기를 생각하며 잠시 시간이 지났다.
2. 관련된 내용을 오픈 카톡방에 올렸고, 한 분께서 도움을 주셨다.
S3FullAccess를 부여해도 버킷별로 액세스 / 삭제 정책을 나눠서 줄 수 있어요.
일단 정책생성하신걸 봐야할 것 같습니다.
라는 조언을 해주셨고, 이제서야 정책을 다시 봐봐야겠다는 생각을 했다.
아니나 다를까 어떤 실수에선지 AmazonS3FullAccess, AWSCompromisedKeyQuarantineV2 두 가지 정책이 걸려있었고 그 중 AWSCompromisedKeyQuarantineV2 정책을 뜯어보니 DeleteObject에 명시적 거부가 되어있었다.
세부사항 변화
기존
수정
결과
결과적으로는 간단하게 해결했다. 중간에 코드가 문젠가 싶어 다시 한 번 공식 문서를 뒤적거리며 찾아봤으나 코드 자체에는 문제가 없는 듯하여 권한 문제로 결론을 내렸다.
회고
. 좀 허무한 결말이었지만 설정이 잘 되었겠지 하며 꼼꼼하게 살펴보지 않아 발생한 이유가 큰 듯했다. 이런 자잘한 실수로 인하여 문제가 지속되고 있는 듯하여 초반 설정을 할 때 서로 피드백을 하면서 확실하게 하나씩 짚어나가는 개발을 하는게 좋을 듯하다.
문제는 본인도 S3와 AWS IAM에 대한 이해도가 낮아 한번에 문제점을 찾고 순서적으로 논리적으로 해법을 마련해 나가지 못한게 이 문제를 악화시켰다고 생각되며 반성하고 AWS 권한과 역할에 대한 공부를 해야겠다.
p.s. 이렇게 간단한 오류로 인하여 딜레이 되는 부분들이 요즘 부쩍 늘어난 듯하여 몸이 안좋아 집중을 못하는 것인지 좀 아쉽다.
'Troubleshooting' 카테고리의 다른 글
InvalidDefinitionException - jackson 직렬화 문제 + UserDto에 대한 고민 (0) | 2022.08.15 |
---|---|
Spring Boot - Controller에서 Dto에 Data와 MultipartFile을 매핑하여 함께 받아보기 (0) | 2022.08.13 |
List 사용 - 동시성 문제 (Synchronized vs Concurrent) (0) | 2022.08.09 |
JWT - expired date issue (0) | 2022.08.09 |
TroubleShooting: H2 Database + Spring Security CSP Issue (0) | 2022.08.03 |