From 4fdc8ac68abc2c09910258ae85b25d71d455da3a Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 22 Dec 2025 01:46:21 +0900 Subject: [PATCH] =?UTF-8?q?feat/#152:=20=EB=A6=AC=EB=B7=B0=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20=EB=8B=B5=EB=B3=80?= =?UTF-8?q?=20=EC=99=84=EB=A3=8C=20=EC=97=AC=EB=B6=80=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nexus/app/review/dto/ReviewResponse.java | 2 ++ .../repository/ReviewReplyRepository.java | 3 ++ .../app/review/service/ReviewService.java | 34 ++++++++++++++++--- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/nexus/app/review/dto/ReviewResponse.java b/src/main/java/com/example/nexus/app/review/dto/ReviewResponse.java index c480cac5..3075ea3f 100644 --- a/src/main/java/com/example/nexus/app/review/dto/ReviewResponse.java +++ b/src/main/java/com/example/nexus/app/review/dto/ReviewResponse.java @@ -17,6 +17,8 @@ public class ReviewResponse { private String content; private LocalDateTime createdAt; private LocalDateTime updatedAt; + // 답변 완료 여부 + private Boolean hasReply; // 작성자 정보 (내부 클래스로 구성) private WriterInfo writer; diff --git a/src/main/java/com/example/nexus/app/review/repository/ReviewReplyRepository.java b/src/main/java/com/example/nexus/app/review/repository/ReviewReplyRepository.java index a0fe8f34..33c5dc69 100644 --- a/src/main/java/com/example/nexus/app/review/repository/ReviewReplyRepository.java +++ b/src/main/java/com/example/nexus/app/review/repository/ReviewReplyRepository.java @@ -32,5 +32,8 @@ public interface ReviewReplyRepository extends JpaRepository Page findByCreatedByOrderByCreatedAtDesc(@Param("userId") Long userId, Pageable pageable); Long countByReviewId(Long reviewId); + + @Query("SELECT rr.review.id, COUNT(rr) FROM ReviewReply rr WHERE rr.review.id IN :reviewIds GROUP BY rr.review.id") + List countByReviewIds(@Param("reviewIds") List reviewIds); } diff --git a/src/main/java/com/example/nexus/app/review/service/ReviewService.java b/src/main/java/com/example/nexus/app/review/service/ReviewService.java index bda25440..4f5a316c 100644 --- a/src/main/java/com/example/nexus/app/review/service/ReviewService.java +++ b/src/main/java/com/example/nexus/app/review/service/ReviewService.java @@ -104,10 +104,31 @@ public ReviewResponse getReview(Long reviewId) { @Transactional(readOnly = true) public List getReviewsByPostId(Long postId) { - return reviewRepository - .findByPostId(postId) - .stream() - .map(this::toReviewResponse) + List reviews = reviewRepository.findByPostId(postId); + + List reviewIds = reviews.stream() + .map(Review::getId) + .collect(Collectors.toList()); + + // 리뷰 ID별 답글 개수 Map 생성 + java.util.Map replyCountMap = java.util.Collections.emptyMap(); + if (!reviewIds.isEmpty()) { + replyCountMap = reviewReplyRepository.countByReviewIds(reviewIds) + .stream() + .collect(Collectors.toMap( + result -> ((Number) result[0]).longValue(), + result -> ((Number) result[1]).longValue() + )); + } + + final java.util.Map finalReplyCountMap = replyCountMap; + + return reviews.stream() + .map(review -> { + boolean hasReply = finalReplyCountMap.containsKey(review.getId()) + && finalReplyCountMap.get(review.getId()) > 0; + return toReviewResponse(review, hasReply); + }) .collect(Collectors.toList()); } @@ -239,6 +260,10 @@ public ReviewStatusResponse getReviewStatus(Long userId, Long postId) { } private ReviewResponse toReviewResponse(Review review) { + return toReviewResponse(review, false); + } + + private ReviewResponse toReviewResponse(Review review, boolean hasReply) { User createdBy = review.getCreatedBy(); return ReviewResponse.builder() @@ -248,6 +273,7 @@ private ReviewResponse toReviewResponse(Review review) { .content(review.getContent()) .createdAt(review.getCreatedAt()) .updatedAt(review.getUpdatedAt()) + .hasReply(hasReply) .writer(ReviewResponse.WriterInfo.builder() .id(createdBy.getId()) .nickname(createdBy.getNickname() != null ? createdBy.getNickname() : "")