Skip to content

Commit 4c030a5

Browse files
authored
Refactor#67 중복 코드 리팩토링 및 N+1 문제 해결 (#77)
* 좋아요 기능 수정(토글처리) * N+1 문제 해결 * 중복 코드 리팩토링 , 가독성 확보
1 parent 4f118c5 commit 4c030a5

File tree

18 files changed

+393
-93
lines changed

18 files changed

+393
-93
lines changed

back/src/main/java/com/back/domain/post/comment/dto/CommentAllResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public static CommentAllResponse from(PostComment comment) {
1616
CommentAllResponse response = new CommentAllResponse();
1717
response.setId(comment.getId());
1818
response.setContent(comment.getContent());
19-
response.setAuthorName(comment.getMember().getName()); // Member에서 이름 가져오기
19+
response.setAuthorName(comment.getAuthorName()); // Member에서 이름 가져오기
2020
response.setCreatedAt(comment.getCreateDate());
2121
return response;
2222
}

back/src/main/java/com/back/domain/post/comment/entity/PostComment.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import lombok.Getter;
1010
import lombok.Setter;
1111

12+
import java.util.Objects;
13+
1214
@Entity
1315
@Getter
1416
@Setter
@@ -23,4 +25,14 @@ public class PostComment extends BaseEntity {
2325

2426
private String role;
2527

28+
public Boolean isAuthor( Member member) {
29+
return Objects.equals(this.member.getId(), member.getId());
30+
}
31+
32+
public String getAuthorName() {
33+
return member.getName();
34+
}
35+
36+
37+
2638
}

back/src/main/java/com/back/domain/post/comment/repository/PostCommentRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@
22

33
import com.back.domain.post.comment.entity.PostComment;
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.List;
10+
711
@Repository
812
public interface PostCommentRepository extends JpaRepository<PostComment, Long> {
13+
14+
@Query("SELECT c FROM PostComment c JOIN FETCH c.member WHERE c.post.id = :postId")
15+
List<PostComment> findCommentsWithMemberByPostId(@Param("postId") Long postId);
916
}

back/src/main/java/com/back/domain/post/comment/service/PostCommentService.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,22 @@ public void createComment(Member member, Long postId, CommentCreateRequest comme
3939

4040
}
4141

42+
@Transactional
4243
public List<CommentAllResponse> getAllPostCommentResponse(Long postId) {
43-
Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다."));
44-
45-
List<PostComment> listPostComment = post.getComments();
44+
validatePostExists(postId);
4645

46+
List<PostComment> listPostComment = postCommentRepository.findCommentsWithMemberByPostId(postId);
4747

4848
return listPostComment.stream()
4949
.map(CommentAllResponse::from)
5050
.toList();
5151
}
5252

53+
@Transactional
5354
public void removePostComment(Long postId, CommentDeleteRequest commentDeleteRequest, Member member) {
54-
Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다."));
55+
validatePostExists(postId);
5556

56-
PostComment postComment = postCommentRepository.findById(commentDeleteRequest.getCommentId()).orElseThrow(() -> new ServiceException("400", "해당 Id의 댓글이 없습니다."));
57+
PostComment postComment = getPostCommentById(commentDeleteRequest.getCommentId());
5758
Member author = postComment.getMember();
5859

5960

@@ -67,9 +68,9 @@ public void removePostComment(Long postId, CommentDeleteRequest commentDeleteReq
6768

6869
@Transactional
6970
public void updatePostComment(Long postId, CommentModifyRequest commentModifyRequest, Member member) {
70-
Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다."));
71+
validatePostExists(postId);
7172

72-
PostComment postComment = postCommentRepository.findById(commentModifyRequest.getCommentId()).orElseThrow(() -> new ServiceException("400", "해당 Id의 댓글이 없습니다."));
73+
PostComment postComment = getPostCommentById(commentModifyRequest.getCommentId());
7374
Member author = postComment.getMember();
7475

7576

@@ -79,4 +80,19 @@ public void updatePostComment(Long postId, CommentModifyRequest commentModifyReq
7980

8081
postComment.setContent(commentModifyRequest.getContent());
8182
}
83+
84+
85+
86+
private void validatePostExists(Long postId) {
87+
if (!postRepository.existsById(postId)) {
88+
throw new ServiceException("400", "해당 Id의 게시글이 없습니다.");
89+
}
90+
}
91+
92+
private PostComment getPostCommentById(Long commentId) {
93+
return postCommentRepository.findById(commentId).orElseThrow(() -> new ServiceException("400", "해당 Id의 댓글이 없습니다."));
94+
}
95+
96+
97+
8298
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.back.domain.post.like.entity;
2+
3+
import com.back.domain.member.member.entity.Member;
4+
import com.back.domain.post.post.entity.Post;
5+
import com.back.global.jpa.BaseEntity;
6+
import jakarta.persistence.Entity;
7+
import jakarta.persistence.EnumType;
8+
import jakarta.persistence.Enumerated;
9+
import jakarta.persistence.FetchType;
10+
import jakarta.persistence.ManyToOne;
11+
import jakarta.persistence.Table;
12+
import jakarta.persistence.UniqueConstraint;
13+
import lombok.AccessLevel;
14+
import lombok.Builder;
15+
import lombok.Getter;
16+
import lombok.NoArgsConstructor;
17+
18+
@Getter
19+
@Entity
20+
@Table(name = "post_like", uniqueConstraints = {
21+
@UniqueConstraint(columnNames = {"member_id", "post_id"})
22+
})
23+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
24+
public class PostLike extends BaseEntity {
25+
26+
@ManyToOne(fetch = FetchType.LAZY)
27+
private Member member;
28+
29+
@ManyToOne(fetch = FetchType.LAZY)
30+
private Post post;
31+
32+
@Enumerated(EnumType.STRING)
33+
private LikeStatus status;
34+
35+
public enum LikeStatus {
36+
LIKE, DISLIKE
37+
}
38+
39+
@Builder(access = AccessLevel.PRIVATE)
40+
private PostLike(Member member, Post post, LikeStatus status) {
41+
this.member = member;
42+
this.post = post;
43+
this.status = status;
44+
}
45+
46+
public static PostLike create(Member member, Post post, LikeStatus status) {
47+
if (member == null) {
48+
throw new IllegalArgumentException("Member cannot be null");
49+
}
50+
if (post == null) {
51+
throw new IllegalArgumentException("Post cannot be null");
52+
}
53+
if (status == null) {
54+
throw new IllegalArgumentException("Status cannot be null");
55+
}
56+
return PostLike.builder()
57+
.member(member)
58+
.post(post)
59+
.status(status)
60+
.build();
61+
}
62+
63+
public void updateStatus(LikeStatus status) {
64+
this.status = status;
65+
}
66+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.back.domain.post.like.repository;
2+
3+
import com.back.domain.member.member.entity.Member;
4+
import com.back.domain.post.like.entity.PostLike;
5+
import com.back.domain.post.post.entity.Post;
6+
import org.springframework.data.jpa.repository.JpaRepository;
7+
import org.springframework.data.jpa.repository.Query;
8+
import org.springframework.data.repository.query.Param;
9+
import org.springframework.stereotype.Repository;
10+
11+
import java.util.Optional;
12+
13+
@Repository
14+
public interface PostLikeRepository extends JpaRepository<PostLike, Long> {
15+
16+
Optional<PostLike> findByMemberAndPost(Member member, Post post);
17+
18+
@Query("SELECT COUNT(pl) FROM PostLike pl WHERE pl.post.id = :postId AND pl.status = 'LIKE'")
19+
int countLikesByPostId(@Param("postId") Long postId);
20+
21+
@Query("SELECT COUNT(pl) FROM PostLike pl WHERE pl.post.id = :postId AND pl.status = 'DISLIKE'")
22+
int countDislikesByPostId(@Param("postId") Long postId);
23+
24+
boolean existsByMemberAndPost(Member member, Post post);
25+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.back.domain.post.like.service;
2+
3+
import com.back.domain.member.member.entity.Member;
4+
import com.back.domain.post.like.entity.PostLike;
5+
import com.back.domain.post.like.repository.PostLikeRepository;
6+
import com.back.domain.post.post.entity.Post;
7+
import com.back.domain.post.post.service.PostService;
8+
import com.back.global.rq.Rq;
9+
import jakarta.transaction.Transactional;
10+
import lombok.RequiredArgsConstructor;
11+
import org.springframework.stereotype.Service;
12+
13+
import java.util.Optional;
14+
@Service
15+
@RequiredArgsConstructor
16+
public class PostLikeService {
17+
private final Rq rq;
18+
private final PostLikeRepository postLikeRepository;
19+
private final PostService postService;
20+
21+
22+
@Transactional
23+
public void likePost(long postId) {
24+
Member member = rq.getActor();
25+
Post post = postService.findById(postId);
26+
27+
// 기존 좋아요/싫어요 기록 조회
28+
Optional<PostLike> existingLike = postLikeRepository.findByMemberAndPost(member, post);
29+
30+
if (existingLike.isPresent()) {
31+
PostLike postLike = existingLike.get();
32+
33+
if (postLike.getStatus() == PostLike.LikeStatus.LIKE) {
34+
// 이미 좋아요 상태 -> 좋아요 취소
35+
postLikeRepository.delete(postLike);
36+
} else {
37+
// 싫어요 상태 -> 좋아요로 변경
38+
postLike.updateStatus(PostLike.LikeStatus.LIKE);
39+
}
40+
} else {
41+
// 처음 좋아요
42+
PostLike newLike = PostLike.create(member, post, PostLike.LikeStatus.LIKE);
43+
postLikeRepository.save(newLike);
44+
45+
}
46+
}
47+
48+
@Transactional
49+
public void disLikePost(long postId) {
50+
Member member = rq.getActor();
51+
Post post = postService.findById(postId);
52+
53+
// 기존 좋아요/싫어요 기록 조회
54+
Optional<PostLike> existingLike = postLikeRepository.findByMemberAndPost(member, post);
55+
56+
if (existingLike.isPresent()) {
57+
PostLike postLike = existingLike.get();
58+
59+
if (postLike.getStatus() == PostLike.LikeStatus.DISLIKE) {
60+
// 이미 싫어요 상태 -> 싫어요 취소
61+
postLikeRepository.delete(postLike);
62+
} else {
63+
// 좋아요 상태 -> 싫어요로 변경
64+
postLike.updateStatus(PostLike.LikeStatus.DISLIKE);
65+
}
66+
} else {
67+
// 처음 싫어요
68+
PostLike newDislike = PostLike.create(member, post, PostLike.LikeStatus.DISLIKE);
69+
postLikeRepository.save(newDislike);
70+
}
71+
}
72+
73+
public int showDisLikeCount(Long postId) {
74+
return postLikeRepository.countDislikesByPostId(postId);
75+
}
76+
77+
public int showLikeCount(Long postId) {
78+
return postLikeRepository.countLikesByPostId(postId);
79+
}
80+
}

back/src/main/java/com/back/domain/post/post/controller/InformationPostController.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.back.domain.post.post.controller;
22

33
import com.back.domain.member.member.entity.Member;
4+
import com.back.domain.post.like.service.PostLikeService;
45
import com.back.domain.post.post.dto.*;
56
import com.back.domain.post.post.entity.Post;
67
import com.back.domain.post.post.service.PostService;
@@ -22,6 +23,7 @@
2223
@RequestMapping("post/infor")
2324
@RequiredArgsConstructor
2425
public class InformationPostController {
26+
private final PostLikeService postLikeService;
2527
private final PostService postService;
2628
private final Rq rq;
2729

@@ -90,27 +92,36 @@ public RsData<Void> updatePost(@PathVariable Long post_id
9092
return new RsData<>("200", "게시글 수정 성공", null);
9193
}
9294

93-
@Operation(summary = "게시글 좋아요 + ")
95+
@Operation(summary = "게시글 좋아요")
9496
@PostMapping("/{post_id}/liked")
9597
public RsData<Void> likePost(@PathVariable Long post_id) {
96-
postService.likePost(post_id);
98+
postLikeService.likePost(post_id);
9799

98100
return new RsData<>("200", "게시글 좋아요 성공", null);
99101
}
100102

101103
@Operation(summary = "게시글 좋아요 (Show)")
102104
@GetMapping("/{post_id}/liked")
103-
public RsData<PostLikedResponse> getlike(@PathVariable Long post_id) {
104-
int likeCount = postService.showLikeCount(post_id);
105+
public RsData<PostLikedResponse> getLike(@PathVariable Long post_id) {
106+
int likeCount = postLikeService.showLikeCount(post_id);
105107
PostLikedResponse postLikedResponse = new PostLikedResponse(likeCount);
106108

107109
return new RsData<>("200", "게시글 좋아요 조회 성공", postLikedResponse);
108110
}
109111

112+
@Operation(summary = "게시글 싫어요 (Show)")
113+
@GetMapping("/{post_id}/Disliked")
114+
public RsData<PostLikedResponse> getDisLike(@PathVariable Long post_id) {
115+
int likeCount = postLikeService.showDisLikeCount(post_id);
116+
PostLikedResponse postLikedResponse = new PostLikedResponse(likeCount);
117+
118+
return new RsData<>("200", "게시글 싫어요 조회 성공", postLikedResponse);
119+
}
120+
110121
@Operation(summary = "게시글 싫어요")
111122
@PostMapping("/{post_id}/disliked")
112123
public RsData<PostLikedResponse> disLikePost(@PathVariable Long post_id) {
113-
postService.disLikePost(post_id);
124+
postLikeService.disLikePost(post_id);
114125

115126
return new RsData<>("200", "게시글 싫어요 성공", null);
116127
}

back/src/main/java/com/back/domain/post/post/dto/PostAllResponse.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@ public class PostAllResponse {
1212
private String authorName;
1313
private LocalDateTime createdAt;
1414
private int viewCount;
15-
private int like;
1615

1716
public PostAllResponse(Post post) {
1817
this.id = post.getId();
1918
this.title = post.getTitle();
2019
this.authorName = post.getAuthorName();
2120
this.createdAt = post.getCreateDate();
2221
this.viewCount = post.getViewCount();
23-
this.like = post.getLiked();
2422
}
2523

2624
}
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.back.domain.post.post.dto;
22

3+
import lombok.Data;
4+
5+
@Data
36
public class PostLikedResponse {
4-
int liked;
7+
private int likeCount;
58

6-
public PostLikedResponse(int liked) {
7-
this.liked= liked;
9+
public PostLikedResponse(int likeCount) {
10+
this.likeCount = likeCount;
811
}
912
}

0 commit comments

Comments
 (0)