From 82219098bafb6f7927bc4281d1ac76c976b1cc41 Mon Sep 17 00:00:00 2001 From: kkw610 Date: Wed, 27 May 2026 23:59:01 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=A7=88=EB=AC=B8=20=EB=AA=A9=EB=A1=9D?= =?UTF-8?q?=20=EC=9D=91=EB=8B=B5=EC=97=90=20isLiked=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 --- .../controller/QuestionController.java | 5 +++-- .../domain/question/dto/QuestionResDTO.java | 1 + .../question/service/QuestionService.java | 20 +++++++++++-------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/com/example/Piroin/project/domain/question/controller/QuestionController.java b/backend/src/main/java/com/example/Piroin/project/domain/question/controller/QuestionController.java index ea15efc..ad60114 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/question/controller/QuestionController.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/question/controller/QuestionController.java @@ -23,10 +23,11 @@ public class QuestionController { @GetMapping("/api/sessions/{sessionId}/questions") public ResponseEntity> getQuestionRoom( @PathVariable Long sessionId, - @RequestParam(defaultValue = "0") int understandingIndex + @RequestParam(defaultValue = "0") int understandingIndex, + @AuthenticationPrincipal Long userId ) { return ResponseUtil.success(QuestionSuccessCode.QUESTION_ROOM_OK, - questionService.getQuestionRoom(sessionId, understandingIndex)); + questionService.getQuestionRoom(sessionId, understandingIndex, userId)); // ← userId 추가 } // 질문 목록 실시간 이벤트 구독 diff --git a/backend/src/main/java/com/example/Piroin/project/domain/question/dto/QuestionResDTO.java b/backend/src/main/java/com/example/Piroin/project/domain/question/dto/QuestionResDTO.java index 0e006dc..d215530 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/question/dto/QuestionResDTO.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/question/dto/QuestionResDTO.java @@ -143,6 +143,7 @@ public record QuestionSummaryResponse( String imageUrl, Boolean isResolved, Boolean isPopular, + Boolean isLiked, Integer likeCount, Integer commentCount, // 댓글이 없으면 빈 배열로 내려가며, 프론트는 빈 배열일 때 미리보기 영역을 숨긴다. diff --git a/backend/src/main/java/com/example/Piroin/project/domain/question/service/QuestionService.java b/backend/src/main/java/com/example/Piroin/project/domain/question/service/QuestionService.java index 4b22adc..4955b19 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/question/service/QuestionService.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/question/service/QuestionService.java @@ -47,15 +47,16 @@ public class QuestionService { // 질문 방 조회 @Transactional(readOnly = true) - public QuestionResDTO.QuestionRoomResponse getQuestionRoom(Long sessionId, int understandingIndex) { + public QuestionResDTO.QuestionRoomResponse getQuestionRoom(Long sessionId, int understandingIndex, Long userId) { if (understandingIndex < 0) { throw new IllegalArgumentException("이해도 조회 인덱스는 0 이상이어야 합니다."); } StudySession session = findSession(sessionId); + User loginUser = findLoginUser(userId); return new QuestionResDTO.QuestionRoomResponse( toSessionResponse(session), getUnderstandingSlice(session, understandingIndex), - getQuestionGroups(session) + getQuestionGroups(session, loginUser) ); } @@ -464,7 +465,7 @@ private QuestionResDTO.UnderstandingCheckResponse toUnderstandingCheckResponse(U ); } - private QuestionResDTO.QuestionGroupsResponse getQuestionGroups(StudySession session) { + private QuestionResDTO.QuestionGroupsResponse getQuestionGroups(StudySession session, User loginUser) { List questions = questionRepository.findBySessionAndDeletedAtIsNull(session); QuestionSummaryContext summaryContext = getQuestionSummaryContext(questions); @@ -472,30 +473,33 @@ private QuestionResDTO.QuestionGroupsResponse getQuestionGroups(StudySession ses .filter(q -> !q.getIsResolved() && q.getLikeCount() >= POPULAR_LIKE_THRESHOLD) .sorted(Comparator.comparing(Question::getLikeCount, Comparator.reverseOrder()) .thenComparing(Question::getCreatedAt, Comparator.reverseOrder())) - .map(question -> toQuestionSummaryResponse(question, summaryContext)).toList(); + .map(q -> toQuestionSummaryResponse(q, summaryContext, loginUser)).toList(); List unresolvedQuestions = questions.stream() .filter(q -> !q.getIsResolved() && q.getLikeCount() < POPULAR_LIKE_THRESHOLD) .sorted(Comparator.comparing(Question::getCreatedAt, Comparator.reverseOrder())) - .map(question -> toQuestionSummaryResponse(question, summaryContext)).toList(); + .map(q -> toQuestionSummaryResponse(q, summaryContext, loginUser)).toList(); List resolvedQuestions = questions.stream() .filter(Question::getIsResolved) .sorted(Comparator.comparing(Question::getCreatedAt, Comparator.reverseOrder())) - .map(question -> toQuestionSummaryResponse(question, summaryContext)).toList(); + .map(q -> toQuestionSummaryResponse(q, summaryContext, loginUser)).toList(); return new QuestionResDTO.QuestionGroupsResponse(popularQuestions, unresolvedQuestions, resolvedQuestions); } - private QuestionResDTO.QuestionSummaryResponse toQuestionSummaryResponse( + private QuestionResDTO.QuestionSummaryResponse toQuestionSummaryResponse ( Question question, - QuestionSummaryContext summaryContext + QuestionSummaryContext summaryContext, + User loginUser ) { Long questionId = question.getId(); + boolean isLiked = questionLikeRepository.existsByQuestionAndUser(question, loginUser); return new QuestionResDTO.QuestionSummaryResponse( questionId, question.getContent(), question.getImageUrl(), question.getIsResolved(), !question.getIsResolved() && question.getLikeCount() >= POPULAR_LIKE_THRESHOLD, + isLiked, question.getLikeCount(), summaryContext.commentCounts().getOrDefault(questionId, 0), // 목록 화면은 최상위 댓글 중 먼저 달린 3개만 미리보기로 보여준다.