-
[AWS S3] deleteObject 메서드를 통해 삭제 시 버킷에서 삭제되지 않는 오류 해결ERROR 2025. 1. 30. 17:47
개발 중인 프로젝트에서 이미지 저장이 필요해서 AWS S3 버킷을 만들어서 연동 중이었다.
업로드 기능은 문제 없이 잘 되어서 이미지 업로드 이후 S3를 새로고침하면 버킷의 수가 업로드 한 이미지 수 만큼 잘 늘어나는 것을 확인할 수 있었는데,삭제 기능의 경우 DB에 따로 저장해 둔 이미지 url은 잘 삭제 되었으나 버킷을 새로고침해도 버킷에 존재 하는 객체의 수가 계속 그대로였다.
분명히 콘솔에서는 아무런 에러없이 잘 동작해서 에러의 원인을 열심히 찾아보았다.
1. 버전 관리 문제버전 관리가 활성화되어있으면 deleteObject()가 즉시 삭제하지 않고 "삭제 마커(Deletion Marker)"만 추가하므로 파일이 실제 삭제된 것이 아니라 "숨김 처리"된 것일 가능성이 있다고 한다.
그래서 버전 관리를 활성화해서 한번 시도해보고 비활성화해서 한번 시도해봤는데
아무런 변화가 없었다,,,,,

2. 파일명이 제대로 SubString 되지 않았을 경우파일명이 버킷내의 객체명과 일치하지 않으면 S3에서는 일치하는 객체를 찾을 수가 없어 객체가 잘 삭제되지 않는다.
private String extractFileNameFromUrl(String imageUrl) { try { URL url = new URL(imageUrl); String filePath = url.getPath(); // 경로 추출 return filePath.substring(filePath.lastIndexOf("/") + 1); // 파일명만 추출 } catch (MalformedURLException e) { throw new IllegalArgumentException("Invalid S3 URL format: " + imageUrl); } }당시에 나는 파일명을 추출하는 위의 함수를 하나 정의해서 호출해서 사용하고 있었는데,
이 파일명이 아닐 수도 있을거라고 생각해서 substring도 조정해보고, 아니면 아예 https://버킷명.s3.ap-northeast-2~으로 시작하도록 해서도 시도해봤는데, 실패했다..
파일명은 위처럼 추출하는 것이 맞다.,,
3. 파일명 인코딩 문제
그래서 추가적으로 열심히 찾아본 결과 파일명 인코딩 디코딩 문제일수도 있다고 해서 다시한번 파일명을 유심히 찾아봤는데, 자세히 보니 버킷 내 객체의 파일명과 DB에 저장된 객체의 파일명과 달랐다....!

DB에 저장되어있는 파일명 
버킷에 저장되어있는 파일명 그래서 지금까지 객체 삭제에 실패했던 원인은 파일명이 URL 인코딩된 형태로 삭제 요청이 보내졌기 때문이었다!!
따라서 URLDecoder.decode()를 사용하여 원본 파일명으로 변환해주어야 한다
📌 URL 인코딩이란?
- 특수 문자(공백, 한글, 특수기호 등)를 안전하게 웹에서 전송하기 위해 변환하는 과정
- 웹 브라우저나 네트워크에서 안전하게 전달하기 위해 사용하는 표준 인코딩 방식
- 일반적으로 ASCII 문자만 안전하게 사용 가능
- 안전한 문자: A-Z, a-z, 0-9, -, _, .
- 인코딩해야 하는 문자: 공백, 한글, 특수문자 (%20, %EC%95%88%EB%85%95 등)
📌 인코딩된 파일과 디코딩된 파일의 차이
- 파일 자체에는 차이가 없음!
- 하지만 S3에서 파일을 저장할 때 키(Key)는 URL 인코딩된 상태일 가능성이 높음
- 삭제할 때는 반드시 디코딩해서 원래 파일명으로 전달해야 함
따라서 S3 URL에서 파일명 추출하는 extractFileNameFromUrl 메서드를 아래와 같이 수정해주니 정상적으로 객체가 잘 삭제되는 것을 확인할 수 있었다.
// S3 URL에서 파일명 추출 private String extractFileNameFromUrl(String imageUrl) { try { URL url = new URL(imageUrl); String filePath = url.getPath(); String fileName = filePath.substring(filePath.lastIndexOf("/") + 1); return URLDecoder.decode(fileName, StandardCharsets.UTF_8.name()); } catch (MalformedURLException | UnsupportedEncodingException e) { throw new ImageUploadException(ImageUploadErrorCode.S3_DELETE_FAILED); } }'ERROR' 카테고리의 다른 글