Skip to content

Commit 439bc4a

Browse files
authored
fix: 현재 스토리지에서 관리하지 않는 이미지 삭제 건너뛰기 (#593)
2 parents 6c7f758 + 02937d7 commit 439bc4a

6 files changed

Lines changed: 64 additions & 0 deletions

File tree

server/src/main/java/wap/web2/server/project/service/ProjectService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ public String update(Long projectId, ProjectRequest request, UserPrincipal userP
179179
List<String> removedImageUrls = project.removeImages(getRemovalTargets(request));
180180
for (String imageUrl : removedImageUrls) {
181181
log.info("[프로젝트 수정] 삭제하려는 image url: {}", imageUrl);
182+
if (!objectStorageService.supports(imageUrl)) {
183+
log.info("[프로젝트 수정] 현재 스토리지에서 관리하지 않는 image url 이므로 물리 삭제를 건너뜁니다: {}", imageUrl);
184+
continue;
185+
}
182186
objectStorageService.deleteImage(imageUrl);
183187
}
184188

server/src/main/java/wap/web2/server/storage/ObjectStorageService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ String uploadImage(
2424
MultipartFile imageFile
2525
) throws IOException;
2626

27+
boolean supports(String imageUrl);
28+
2729
void deleteImage(String imageUrl);
2830

2931
}

server/src/main/java/wap/web2/server/storage/impl/AzureStorageService.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ public void deleteImage(String imageUrl) {
7878
blobContainerClient.getBlobClient(blobName).delete();
7979
}
8080

81+
@Override
82+
public boolean supports(String imageUrl) {
83+
try {
84+
extractBlobNameFromUrl(imageUrl);
85+
return true;
86+
} catch (IllegalArgumentException e) {
87+
return false;
88+
}
89+
}
90+
8191
private void validateImage(MultipartFile imageFile) {
8292
if (imageFile.isEmpty()) {
8393
throw new IllegalArgumentException("[ERROR] 파일이 비어있습니다.");

server/src/main/java/wap/web2/server/storage/impl/OracleObjectStorageService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ public void deleteImage(String imageUrl) {
8787
objectStorageClient.deleteObject(deleteObjectRequest);
8888
}
8989

90+
@Override
91+
public boolean supports(String imageUrl) {
92+
try {
93+
extractObjectNameFromUrl(imageUrl);
94+
return imageUrl.contains("objectstorage." + properties.getRegion() + ".oraclecloud.com")
95+
&& imageUrl.contains("/n/" + properties.getNamespace() + "/b/" + properties.getBucketName() + "/o/");
96+
} catch (IllegalArgumentException e) {
97+
return false;
98+
}
99+
}
100+
90101
private String getOriginalFileName(MultipartFile multipartFile) {
91102
String originalFilename = multipartFile.getOriginalFilename();
92103
if (originalFilename == null) {

server/src/main/java/wap/web2/server/storage/impl/S3ObjectStorageService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,17 @@ public void deleteImage(String imageUrl) {
8080
s3Client.deleteObject(deleteRequest);
8181
}
8282

83+
@Override
84+
public boolean supports(String imageUrl) {
85+
try {
86+
URI uri = URI.create(imageUrl);
87+
String host = uri.getHost();
88+
return host != null && host.startsWith(s3Properties.getS3().getBucketName() + ".s3.");
89+
} catch (IllegalArgumentException e) {
90+
return false;
91+
}
92+
}
93+
8394
private String extractKeyFromUrl(String url) {
8495
URI uri = URI.create(url);
8596
String path = uri.getPath();

server/src/test/java/wap/web2/server/project/service/ProjectServiceTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ void setUp() {
119119

120120
when(userRepository.findById(owner.getId())).thenReturn(Optional.of(owner));
121121
when(projectRepository.findById(project.getProjectId())).thenReturn(Optional.of(project));
122+
when(objectStorageService.supports("https://cdn.example.com/a.png")).thenReturn(true);
122123

123124
ProjectRequest request = baseRequestBuilder()
124125
.removal(List.of("https://cdn.example.com/a.png", "https://cdn.example.com/missing.png"))
@@ -135,6 +136,31 @@ void setUp() {
135136
verify(objectStorageService, never()).deleteImage("https://cdn.example.com/missing.png");
136137
}
137138

139+
@Test
140+
void 현재_스토리지에서_관리하지_않는_이미지는_프로젝트_컬렉션에서만_제거한다() throws Exception {
141+
// given
142+
User owner = owner();
143+
UserPrincipal principal = principal(owner.getId());
144+
Project project = project(owner);
145+
String legacyS3Url = "https://waps-bucket.s3.ap-northeast-2.amazonaws.com/projects/2025-2/test/image.png";
146+
project.addAllImage(Image.listOf(List.of(legacyS3Url)));
147+
148+
when(userRepository.findById(owner.getId())).thenReturn(Optional.of(owner));
149+
when(projectRepository.findById(project.getProjectId())).thenReturn(Optional.of(project));
150+
when(objectStorageService.supports(legacyS3Url)).thenReturn(false);
151+
152+
ProjectRequest request = baseRequestBuilder()
153+
.removal(List.of(legacyS3Url))
154+
.build();
155+
156+
// when
157+
projectService.update(project.getProjectId(), request, principal);
158+
159+
// then
160+
assertThat(project.getImages()).isEmpty();
161+
verify(objectStorageService, never()).deleteImage(legacyS3Url);
162+
}
163+
138164
private ProjectRequest.ProjectRequestBuilder baseRequestBuilder() {
139165
return ProjectRequest.builder()
140166
.title("updated title")

0 commit comments

Comments
 (0)