오늘은 프로젝트에서 Post(게시글)을 수정할 때 기존에 저장되어 있는 이미지 리스트를 변경,삭제 하는 API를 구현했다.
수정의 조건에는 다음과 같은 시나리오가 예상되었다.
- 기존의 이미지에서 변경된 파일을 감지할 수 있는가? -> 현재로서는 불가
- 그렇다면 기존의 이미지를 모두 삭제한다 (DB와 S3모두 삭제한다)
- S3의 파일을 어떻게 찾아서 삭제할것인가?
- S3Service.java에 S3에 등록한 파일을 삭제하는 로직을 구현한다.
우와 같은 순서로 만들 수 있다면 처음으로 구현해야할 메서드는 S3에 있는 데이터를 지워주는 서드이다.
기존 S3Service.java에 추가해줄 수 있다.
여기서 사실 생각보다 파일이 저장되는 이름(url을 저장)을 주의깊게 살펴보아야 했다.
//key네임을 통해 S3에 등록된 파일을 제거
public void deleteFile(String url) {
String key = extractKeyFromUrl(url);
try {
s3Client.deleteObject(bucket, key);
} catch (AmazonServiceException e) {
throw new CustomException(Error.FAIL_S3_DELETE);
}
}
// URL에서 파일 키 추출
private String extractKeyFromUrl(String url) {
String prefix = "https://s3." + region + ".amazonaws.com/" + bucket + "/";
if (!url.startsWith(prefix)) {
throw new CustomException(Error.FAIL_S3_DELETE);
}
return url.substring(prefix.length());
}
중요한 부분은 String prefix = "https://s3." + region + ".amazonaws.com/" + bucket + "/";
이부분 이다.
resion = S3 버킷이 등록된 지역.
bucket = 버킷의 이름.
현재 S3파일이 DB에 저장된되는 이름은 다음과 같다(Service 로직에 따라 다를 수 있음!!!)
https://s3.ap-northeast-2.amazonaws.com/kunon-clean-project/post/image/4cfa2cce-6574-49b0-8e40-1bcb42075a95.jpeg
이런 방식으로 이름이 저장된다.
현재 저장된 파일이름의 구조는
"https://s3." + region + ".amazonaws.com/" + bucket + "/"+저장경로+파일이름 으로 볼 수 있다.
여기서 필요한 부분은 바로 저장경로+파일이름
이다.
extractKeyFromUrl
메서드는 데이터 베이스에 저장된 파일의 이름에서 S3파일의 key를 추출한다.
즉 preFix부분을 파일의 이름에서 제거하게 된다면
-> post/image/4cfa2cce-6574-49b0-8e40-1bcb42075a95.jpeg
이 부분만 남게된다.
이 key를 s3Client.deleteObject(bucket, key)
에 버킷이름과 함께 전달해서 제거하는 방법이다.
이외에도 파일을 제거하는 방법은 여러가지가 있을것으로 생각되나 내가 생각할 수 있던 방법은 이러한 방법이 떠오른것...
처음에 데이터가 저장되는 이름을 자세하게 살펴보지 않고 다른 참조문서를 계속 봤는대
사실상 파일이름이 만들어지는 구조가 조금씩 달랐다.
다른 개발자분들이 구현할 때 만들어지는 파일이름의 순서가 달라 preFix구조가 다르게 만들어졌는데 이를 참조해서 내 코드에 적용하려하니 무한한 예외를 만날 수 밖에 없었다....
즉 파일이름을 만드는 로직에 따라 다르게 설정해 줄 필요가 있었다.
Post를 업데이트 하는 메서드에서
for (PostImage postImage : post.getImage()) {
s3Service.deleteFile(postImage.getImage());
postImageRepository.delete(postImage);
}
이미지는 리스트이므로 iter를 사용해서 하나씩 뽑아서 S3와 DB에서 제거해준다.
S3에서도 말끔히 삭제되고!!
DB에서도 말끔히 삭제한 것을 확인.