From 690756b9335d09113b089d0849d7cecd6b7d7e59 Mon Sep 17 00:00:00 2001 From: SeokGeunHo Date: Tue, 14 Oct 2025 15:25:44 +0900 Subject: [PATCH] =?UTF-8?q?[feat]=20=EC=82=AC=EC=9A=A9=EC=9E=90=EA=B0=80?= =?UTF-8?q?=20=ED=95=B4=EB=8B=B9=20=EA=B2=8C=EC=8B=9C=EA=B8=80=EC=97=90=20?= =?UTF-8?q?=EC=B6=94=EC=B2=9C=EC=9D=84=20=ED=96=88=EB=8A=94=EC=A7=80=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20api?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/post/controller/PostController.java | 13 +++++ .../post/repository/PostLikeRepository.java | 2 + .../domain/post/post/service/PostService.java | 55 +++++++++++-------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/back/domain/post/post/controller/PostController.java b/src/main/java/com/back/domain/post/post/controller/PostController.java index 2198d147..864437f8 100644 --- a/src/main/java/com/back/domain/post/post/controller/PostController.java +++ b/src/main/java/com/back/domain/post/post/controller/PostController.java @@ -120,4 +120,17 @@ public RsData toggleLike( ) { return RsData.successOf(postService.toggleLike(postId)); // code=200, message="success" } + + /** + * 사용자가 해당 게시글을 추천(좋아요)했는지 여부 확인 API + * @param postId 확인할 게시글 ID + * @return 사용자의 추천 여부 (true/false) + */ + @GetMapping("/{postId}/like") + @Operation(summary = "사용자가 해당 게시글 추천 여부 확인") + public RsData getLike( + @PathVariable Long postId + ) { + return RsData.successOf(postService.getLike(postId)); // code=200, message="success" + } } diff --git a/src/main/java/com/back/domain/post/post/repository/PostLikeRepository.java b/src/main/java/com/back/domain/post/post/repository/PostLikeRepository.java index f0a8bd41..8cc1ae10 100644 --- a/src/main/java/com/back/domain/post/post/repository/PostLikeRepository.java +++ b/src/main/java/com/back/domain/post/post/repository/PostLikeRepository.java @@ -7,5 +7,7 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface PostLikeRepository extends JpaRepository { + Boolean existsByPostAndUser(Post post, User user); + Optional findByPostAndUser(Post post, User user); } 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 603016f2..83b146f5 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,6 +24,12 @@ import com.back.global.file.dto.UploadedFileDto; import com.back.global.file.service.FileService; import com.back.global.rq.Rq; +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; import org.springframework.transaction.annotation.Transactional; @@ -31,10 +37,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.web.multipart.MultipartFile; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - @Service @RequiredArgsConstructor public class PostService { @@ -158,39 +160,35 @@ public PostResponseDto updatePost(Long postId, PostUpdateRequestDto reqBody, Lis Map existingById = post.getImages().stream() .collect(Collectors.toMap(PostImage::getId, Function.identity())); - // 삭제할 이미지 찾기 - List toDelete = post.getImages().stream() + // 삭제될 이미지 (DB + S3) + List toRemove = post.getImages().stream() .filter(img -> !keepIds.contains(img.getId())) .toList(); - // 최종 이미지 리스트 구성 - List finalImages = new ArrayList<>(); + List deleteKeysAfterCommit = toRemove.stream() + .map(PostImage::getFileName) + .toList(); + + toRemove.forEach(img -> img.updatePost(null)); // 관계 해제 + post.getImages().removeAll(toRemove); // orphanRemoval 트리거 + + // 유지할 이미지 정렬 int order = 0; for (Long keepId : keepIds) { PostImage img = existingById.get(keepId); - if (img != null) { - img.updateSortOrder(order++); - finalImages.add(img); - } + if (img != null) img.updateSortOrder(order++); } + + // 새 이미지 추가 for (UploadedFileDto u : uploaded) { - finalImages.add(PostImage.builder() + post.getImages().add(PostImage.builder() .post(post) .fileName(u.fileName()) .url(u.url()) .sortOrder(order++) - .build() - ); + .build()); } - // 삭제 예정 key 모음 - List deleteKeysAfterCommit = toDelete.stream() - .map(PostImage::getFileName) - .toList(); - - // DB에 반영 - post.updateImages(finalImages); - // 트랜잭션 완료 후 처리 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override @@ -272,6 +270,17 @@ public PostLikeResponseDto toggleLike(Long postId) { } } + // 사용자가 해당 게시글 여부 확인 로직 + @Transactional(readOnly = true) + public Boolean getLike(Long postId) { + User user = rq.getActor(); + + Post post = postRepository.findById(postId) + .orElseThrow(() -> new NoSuchElementException("해당 게시글을 찾을 수 없습니다. ID: " + postId)); + + return postLikeRepository.existsByPostAndUser(post, user); + } + // 태그 추가 메서드 private void addTag(List tagNames, Post post) { for (String tagName : tagNames) {