Skip to content

Commit 575ac32

Browse files
authored
Merge branch 'dev' into Refactor/223
2 parents 9b10f1c + 5a6f6ae commit 575ac32

32 files changed

+358
-99
lines changed

src/main/java/com/back/domain/board/comment/controller/CommentController.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ public ResponseEntity<RsData<CommentResponse>> createComment(
4444
@GetMapping
4545
public ResponseEntity<RsData<PageResponse<CommentListResponse>>> getComments(
4646
@PathVariable Long postId,
47+
@AuthenticationPrincipal CustomUserDetails user,
4748
@PageableDefault(sort = "createdAt", direction = Sort.Direction.ASC) Pageable pageable
4849
) {
49-
PageResponse<CommentListResponse> response = commentService.getComments(postId, pageable);
50+
Long userId = (user != null) ? user.getUserId() : null;
51+
PageResponse<CommentListResponse> response = commentService.getComments(postId, userId, pageable);
5052
return ResponseEntity
5153
.status(HttpStatus.OK)
5254
.body(RsData.success(

src/main/java/com/back/domain/board/comment/controller/CommentControllerDocs.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public interface CommentControllerDocs {
4141
"postId": 101,
4242
"author": {
4343
"id": 5,
44-
"nickname": "홍길동"
44+
"nickname": "홍길동",
45+
"profileImageUrl": null
4546
},
4647
"content": "좋은 글 감사합니다!",
4748
"createdAt": "2025-09-22T11:30:00",
@@ -170,10 +171,12 @@ ResponseEntity<RsData<CommentResponse>> createComment(
170171
"parentId": null,
171172
"author": {
172173
"id": 5,
173-
"nickname": "홍길동"
174+
"nickname": "홍길동",
175+
"profileImageUrl": null
174176
},
175177
"content": "부모 댓글",
176178
"likeCount": 2,
179+
"likedByMe": true,
177180
"createdAt": "2025-09-22T11:30:00",
178181
"updatedAt": "2025-09-22T11:30:00",
179182
"children": [
@@ -183,10 +186,12 @@ ResponseEntity<RsData<CommentResponse>> createComment(
183186
"parentId": 1,
184187
"author": {
185188
"id": 5,
186-
"nickname": "홍길동"
189+
"nickname": "홍길동",
190+
"profileImageUrl": null
187191
},
188192
"content": "자식 댓글",
189193
"likeCount": 0,
194+
"likedByMe": false,
190195
"createdAt": "2025-09-22T11:35:00",
191196
"updatedAt": "2025-09-22T11:35:00",
192197
"children": []
@@ -252,6 +257,7 @@ ResponseEntity<RsData<CommentResponse>> createComment(
252257
})
253258
ResponseEntity<RsData<PageResponse<CommentListResponse>>> getComments(
254259
@PathVariable Long postId,
260+
@AuthenticationPrincipal CustomUserDetails user,
255261
Pageable pageable
256262
);
257263

@@ -275,7 +281,8 @@ ResponseEntity<RsData<PageResponse<CommentListResponse>>> getComments(
275281
"postId": 101,
276282
"author": {
277283
"id": 5,
278-
"nickname": "홍길동"
284+
"nickname": "홍길동",
285+
"profileImageUrl": null
279286
},
280287
"content": "수정된 댓글 내용입니다.",
281288
"createdAt": "2025-09-22T11:30:00",
@@ -532,7 +539,8 @@ ResponseEntity<RsData<Void>> deleteComment(
532539
"parentId": 25,
533540
"author": {
534541
"id": 7,
535-
"nickname": "이몽룡"
542+
"nickname": "이몽룡",
543+
"profileImageUrl": null
536544
},
537545
"content": "저도 동의합니다!",
538546
"createdAt": "2025-09-22T13:30:00",

src/main/java/com/back/domain/board/comment/dto/CommentListResponse.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public class CommentListResponse {
2222
@Setter
2323
private long likeCount;
2424

25+
@Setter
26+
private Boolean likedByMe;
27+
2528
private final LocalDateTime createdAt;
2629
private final LocalDateTime updatedAt;
2730

@@ -35,6 +38,7 @@ public CommentListResponse(Long commentId,
3538
AuthorResponse author,
3639
String content,
3740
long likeCount,
41+
Boolean likedByMe,
3842
LocalDateTime createdAt,
3943
LocalDateTime updatedAt,
4044
List<CommentListResponse> children) {
@@ -43,6 +47,7 @@ public CommentListResponse(Long commentId,
4347
this.parentId = parentId;
4448
this.author = author;
4549
this.content = content;
50+
this.likedByMe = likedByMe;
4651
this.likeCount = likeCount;
4752
this.createdAt = createdAt;
4853
this.updatedAt = updatedAt;

src/main/java/com/back/domain/board/comment/repository/CommentLikeRepository.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22

33
import com.back.domain.board.comment.entity.CommentLike;
44
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
6+
import org.springframework.data.repository.query.Param;
57
import org.springframework.stereotype.Repository;
68

9+
import java.util.Collection;
10+
import java.util.List;
711
import java.util.Optional;
812

913
@Repository
10-
public interface CommentLikeRepository extends JpaRepository<CommentLike, Long> {
14+
public interface CommentLikeRepository extends JpaRepository<CommentLike, Long>, CommentLikeRepositoryCustom {
1115
boolean existsByUserIdAndCommentId(Long userId, Long commentId);
1216
Optional<CommentLike> findByUserIdAndCommentId(Long userId, Long commentId);
1317
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.back.domain.board.comment.repository;
2+
3+
import java.util.Collection;
4+
import java.util.List;
5+
6+
public interface CommentLikeRepositoryCustom {
7+
List<Long> findLikedCommentIdsIn(Long userId, Collection<Long> commentIds);
8+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.back.domain.board.comment.repository;
2+
3+
import com.back.domain.board.comment.entity.QCommentLike;
4+
import com.querydsl.jpa.impl.JPAQueryFactory;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.stereotype.Repository;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
11+
12+
@Repository
13+
@RequiredArgsConstructor
14+
public class CommentLikeRepositoryImpl implements CommentLikeRepositoryCustom {
15+
16+
private final JPAQueryFactory queryFactory;
17+
18+
@Override
19+
public List<Long> findLikedCommentIdsIn(Long userId, Collection<Long> commentIds) {
20+
QCommentLike commentLike = QCommentLike.commentLike;
21+
22+
return queryFactory
23+
.select(commentLike.comment.id)
24+
.from(commentLike)
25+
.where(
26+
commentLike.user.id.eq(userId),
27+
commentLike.comment.id.in(commentIds)
28+
)
29+
.fetch();
30+
}
31+
}

src/main/java/com/back/domain/board/comment/repository/CommentRepositoryImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,10 @@ private List<CommentListResponse> fetchComments(
112112
comment.id,
113113
comment.post.id,
114114
comment.parent.id,
115-
new QAuthorResponse(user.id, profile.nickname),
115+
new QAuthorResponse(user.id, profile.nickname, profile.profileImageUrl),
116116
comment.content,
117117
Expressions.constant(0L), // likeCount는 별도 주입
118+
Expressions.constant(false),
118119
comment.createdAt,
119120
comment.updatedAt,
120121
Expressions.constant(Collections.emptyList()) // children은 별도 주입

src/main/java/com/back/domain/board/comment/service/CommentService.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import com.back.domain.board.comment.dto.CommentRequest;
55
import com.back.domain.board.comment.dto.CommentResponse;
66
import com.back.domain.board.comment.dto.ReplyResponse;
7+
import com.back.domain.board.comment.entity.CommentLike;
8+
import com.back.domain.board.comment.repository.CommentLikeRepository;
79
import com.back.domain.board.common.dto.PageResponse;
810
import com.back.domain.board.comment.entity.Comment;
911
import com.back.domain.board.post.entity.Post;
@@ -22,11 +24,16 @@
2224
import org.springframework.stereotype.Service;
2325
import org.springframework.transaction.annotation.Transactional;
2426

27+
import java.util.HashSet;
28+
import java.util.List;
29+
import java.util.Set;
30+
2531
@Service
2632
@RequiredArgsConstructor
2733
@Transactional
2834
public class CommentService {
2935
private final CommentRepository commentRepository;
36+
private final CommentLikeRepository commentLikeRepository;
3037
private final UserRepository userRepository;
3138
private final PostRepository postRepository;
3239
private final ApplicationEventPublisher eventPublisher;
@@ -85,6 +92,41 @@ public PageResponse<CommentListResponse> getComments(Long postId, Pageable pagea
8592
return PageResponse.from(comments);
8693
}
8794

95+
// TODO: 추후 메서드 통합 및 리팩토링
96+
@Transactional(readOnly = true)
97+
public PageResponse<CommentListResponse> getComments(Long postId, Long userId, Pageable pageable) {
98+
// 기본 댓글 목록
99+
PageResponse<CommentListResponse> response = getComments(postId, pageable);
100+
101+
// 로그인 사용자용 로직
102+
if (userId != null) {
103+
// 댓글 ID 수집
104+
List<Long> commentIds = response.items().stream()
105+
.map(CommentListResponse::getCommentId)
106+
.toList();
107+
108+
if (commentIds.isEmpty()) return response;
109+
110+
// QueryDSL 기반 좋아요 ID 조회 (단일 쿼리)
111+
List<Long> likedIds = commentLikeRepository.findLikedCommentIdsIn(userId, commentIds);
112+
Set<Long> likedSet = new HashSet<>(likedIds);
113+
114+
// likedByMe 세팅
115+
response.items().forEach(c -> c.setLikedByMe(likedSet.contains(c.getCommentId())));
116+
117+
// 자식 댓글에도 동일 적용
118+
response.items().forEach(parent -> {
119+
if (parent.getChildren() != null) {
120+
parent.getChildren().forEach(child ->
121+
child.setLikedByMe(likedSet.contains(child.getCommentId()))
122+
);
123+
}
124+
});
125+
}
126+
127+
return response;
128+
}
129+
88130
/**
89131
* 댓글 수정 서비스
90132
* 1. Post 조회

src/main/java/com/back/domain/board/common/dto/AuthorResponse.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,23 @@
66
/**
77
* 작성자 응답 DTO
88
*
9-
* @param id 작성자 ID
10-
* @param nickname 작성자 닉네임
9+
* @param id 작성자 ID
10+
* @param nickname 작성자 닉네임
11+
* @param profileImageUrl 작성자 프로필 이미지
1112
*/
1213
public record AuthorResponse(
1314
Long id,
14-
String nickname
15+
String nickname,
16+
String profileImageUrl
1517
) {
1618
@QueryProjection
1719
public AuthorResponse {}
1820

1921
public static AuthorResponse from(User user) {
2022
return new AuthorResponse(
2123
user.getId(),
22-
user.getUserProfile().getNickname()
24+
user.getUserProfile().getNickname(),
25+
user.getProfileImageUrl()
2326
);
2427
}
2528
}

src/main/java/com/back/domain/board/post/controller/PostController.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ public ResponseEntity<RsData<PageResponse<PostListResponse>>> getPosts(
5959
// 게시글 단건 조회
6060
@GetMapping("/{postId}")
6161
public ResponseEntity<RsData<PostDetailResponse>> getPost(
62-
@PathVariable Long postId
62+
@PathVariable Long postId,
63+
@AuthenticationPrincipal CustomUserDetails user
6364
) {
64-
PostDetailResponse response = postService.getPost(postId);
65+
PostDetailResponse response = (user != null)
66+
? postService.getPostWithUser(postId, user.getUserId())
67+
: postService.getPost(postId);
6568
return ResponseEntity
6669
.status(HttpStatus.OK)
6770
.body(RsData.success(

0 commit comments

Comments
 (0)