From 2c4711da021edcccd9071b6baf2ccffcbf513d06 Mon Sep 17 00:00:00 2001 From: SeokGeunHo Date: Tue, 14 Oct 2025 17:20:33 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B5=AC=ED=98=84=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/post/dto/request/PostUpdateRequestDto.java | 4 ++-- .../back/domain/post/post/service/PostService.java | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/back/domain/post/post/dto/request/PostUpdateRequestDto.java b/src/main/java/com/back/domain/post/post/dto/request/PostUpdateRequestDto.java index 87c2e11..8550444 100644 --- a/src/main/java/com/back/domain/post/post/dto/request/PostUpdateRequestDto.java +++ b/src/main/java/com/back/domain/post/post/dto/request/PostUpdateRequestDto.java @@ -8,8 +8,8 @@ public record PostUpdateRequestDto( PostStatus status, String title, String content, - // 기존 이미지 중 유지할 이미지 ID 목록 - List keepImageIds, + // 기존 이미지 중 유지할 이미지 URL 목록 + List keepImageUrls, String videoUrl, List tags ) { diff --git a/src/main/java/com/back/domain/post/post/service/PostService.java b/src/main/java/com/back/domain/post/post/service/PostService.java index 83b146f..4970777 100644 --- a/src/main/java/com/back/domain/post/post/service/PostService.java +++ b/src/main/java/com/back/domain/post/post/service/PostService.java @@ -153,8 +153,17 @@ public PostResponseDto updatePost(Long postId, PostUpdateRequestDto reqBody, Lis List uploaded = fileService.uploadFiles(images); List uploadedFileNames = uploaded.stream().map(UploadedFileDto::fileName).toList(); + // 요청 DTO에서 "유지할 이미지 URL 목록" 꺼내기 + List keepImageUrls = Optional.ofNullable(reqBody.keepImageUrls()).orElse(List.of()); + + // URL → ID 매핑 + List keepIds = post.getImages().stream() + .filter(img -> keepImageUrls.contains(img.getUrl())) + .map(PostImage::getId) + .toList(); + // 요청 DTO에서 "유지할 이미지 ID 목록" 꺼내기 - List keepIds = Optional.ofNullable(reqBody.keepImageIds()).orElse(List.of()); +// List keepIds = Optional.ofNullable(reqBody.keepImageIds()).orElse(List.of()); // 현재 게시글의 이미지들을 (id -> 객체) 매핑으로 변환 Map existingById = post.getImages().stream() From f8069a31ea10f7789c1b310775b7a91cb896ef55 Mon Sep 17 00:00:00 2001 From: SeokGeunHo Date: Wed, 15 Oct 2025 09:11:42 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B5=AC=ED=98=84=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/post/post/service/PostService.java | 73 +++++++++++-------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/back/domain/post/post/service/PostService.java b/src/main/java/com/back/domain/post/post/service/PostService.java index 4970777..f56b97a 100644 --- a/src/main/java/com/back/domain/post/post/service/PostService.java +++ b/src/main/java/com/back/domain/post/post/service/PostService.java @@ -24,11 +24,10 @@ import com.back.global.file.dto.UploadedFileDto; import com.back.global.file.service.FileService; import com.back.global.rq.Rq; +import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; -import java.util.function.Function; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -148,30 +147,28 @@ public PostResponseDto updatePost(Long postId, PostUpdateRequestDto reqBody, Lis if (reqBody.content() != null && !reqBody.content().isBlank()) { post.updateContent(reqBody.content()); } + + List addedImgUrls = List.of(); + List uploadedFileNames = List.of(); + if (images != null && !images.isEmpty()) { // 새 이미지 업로드 List uploaded = fileService.uploadFiles(images); - List uploadedFileNames = uploaded.stream().map(UploadedFileDto::fileName).toList(); + addedImgUrls = uploaded.stream().map(UploadedFileDto::url).toList(); + uploadedFileNames = uploaded.stream().map(UploadedFileDto::fileName).toList(); + } // 요청 DTO에서 "유지할 이미지 URL 목록" 꺼내기 - List keepImageUrls = Optional.ofNullable(reqBody.keepImageUrls()).orElse(List.of()); - - // URL → ID 매핑 - List keepIds = post.getImages().stream() - .filter(img -> keepImageUrls.contains(img.getUrl())) - .map(PostImage::getId) - .toList(); - - // 요청 DTO에서 "유지할 이미지 ID 목록" 꺼내기 -// List keepIds = Optional.ofNullable(reqBody.keepImageIds()).orElse(List.of()); + List keepImageUrls = new ArrayList<>( + Optional.ofNullable(reqBody.keepImageUrls()).orElse(List.of())); + keepImageUrls.addAll(addedImgUrls); - // 현재 게시글의 이미지들을 (id -> 객체) 매핑으로 변환 - Map existingById = post.getImages().stream() - .collect(Collectors.toMap(PostImage::getId, Function.identity())); + // 🔹 현재 게시글의 모든 이미지 가져오기 + List existingImages = new ArrayList<>(post.getImages()); // 삭제될 이미지 (DB + S3) List toRemove = post.getImages().stream() - .filter(img -> !keepIds.contains(img.getId())) + .filter(img -> !keepImageUrls.contains(img.getUrl())) .toList(); List deleteKeysAfterCommit = toRemove.stream() @@ -183,33 +180,40 @@ public PostResponseDto updatePost(Long postId, PostUpdateRequestDto reqBody, Lis // 유지할 이미지 정렬 int order = 0; - for (Long keepId : keepIds) { - PostImage img = existingById.get(keepId); - if (img != null) img.updateSortOrder(order++); + for (String url : keepImageUrls) { + // 기존 이미지인지 확인 + PostImage existing = existingImages.stream() + .filter(img -> img.getUrl().equals(url)) + .findFirst() + .orElse(null); + + if (existing != null) { + existing.updateSortOrder(order++); + } else { + // 새로 추가된 이미지 + post.getImages().add(PostImage.builder() + .post(post) + .fileName(extractFileNameFromUrl(url)) // URL에서 파일명 추출 함수 아래 참고 + .url(url) + .sortOrder(order++) + .build()); + } } - // 새 이미지 추가 - for (UploadedFileDto u : uploaded) { - post.getImages().add(PostImage.builder() - .post(post) - .fileName(u.fileName()) - .url(u.url()) - .sortOrder(order++) - .build()); - } + List uploadedNames = new ArrayList<>(uploadedFileNames); // 트랜잭션 완료 후 처리 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCompletion(int status) { if (status == STATUS_ROLLED_BACK) { - uploadedFileNames.forEach(fileService::deleteFile); + uploadedNames.forEach(fileService::deleteFile); } else if (status == STATUS_COMMITTED) { deleteKeysAfterCommit.forEach(fileService::deleteFile); } } }); - } + if (reqBody.videoUrl() != null && !reqBody.videoUrl().isBlank()) { post.updateVideo(reqBody.videoUrl()); } @@ -221,6 +225,13 @@ public void afterCompletion(int status) { return new PostResponseDto(post); } + private String extractFileNameFromUrl(String url) { + if (url == null) return null; + int lastSlash = url.lastIndexOf('/'); + return (lastSlash != -1) ? url.substring(lastSlash + 1) : url; + } + + // 게시글 삭제 로직 @Transactional public void deletePost(Long postId) {