Skip to content

Commit 31cb3ce

Browse files
committed
[feat] 커뮤니티 최신순, 인기순, 댓글순 정렬 구현
1 parent 950a9dd commit 31cb3ce

File tree

6 files changed

+78
-19
lines changed

6 files changed

+78
-19
lines changed

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

Lines changed: 7 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.post.post.dto.request.PostCreateRequestDto;
4+
import com.back.domain.post.post.dto.request.PostSortScrollRequestDto;
45
import com.back.domain.post.post.dto.request.PostUpdateRequestDto;
56
import com.back.domain.post.post.dto.response.PostResponseDto;
67
import com.back.domain.post.post.service.PostService;
@@ -13,11 +14,11 @@
1314
import org.springframework.http.MediaType;
1415
import org.springframework.web.bind.annotation.DeleteMapping;
1516
import org.springframework.web.bind.annotation.GetMapping;
17+
import org.springframework.web.bind.annotation.ModelAttribute;
1618
import org.springframework.web.bind.annotation.PatchMapping;
1719
import org.springframework.web.bind.annotation.PathVariable;
1820
import org.springframework.web.bind.annotation.PostMapping;
1921
import org.springframework.web.bind.annotation.RequestMapping;
20-
import org.springframework.web.bind.annotation.RequestParam;
2122
import org.springframework.web.bind.annotation.RequestPart;
2223
import org.springframework.web.bind.annotation.RestController;
2324
import org.springframework.web.multipart.MultipartFile;
@@ -48,15 +49,15 @@ public RsData<PostResponseDto> createPost(
4849

4950
/**
5051
* 게시글 다건 조회 API
51-
* @param lastId 마지막으로 조회한 게시글 ID (페이징 처리용, optional)
52+
* @param reqBody 게시글 정렬 및 스크롤 요청 DTO
5253
* @return 게시글 목록
5354
*/
5455
@GetMapping
5556
@Operation(summary = "게시글 다건 조회")
56-
public RsData<List<PostResponseDto>> getAllPosts(
57-
@RequestParam(required = false) Long lastId
57+
public RsData<List<PostResponseDto>> getPosts(
58+
@ModelAttribute PostSortScrollRequestDto reqBody
5859
) {
59-
return RsData.successOf(postService.getAllPosts(lastId)); // code=200, message="success"
60+
return RsData.successOf(postService.getPosts(reqBody)); // code=200, message="success"
6061
}
6162

6263
/**
@@ -76,6 +77,7 @@ public RsData<PostResponseDto> getPost(
7677
* 게시글 수정 API
7778
* @param postId 수정할 게시글 ID
7879
* @param reqBody 게시글 수정 요청 DTO
80+
* @param images 첨부 이미지 파일들 (optional)
7981
* @return 수정된 게시글 정보
8082
*/
8183
@PatchMapping(value = "/{postId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.back.domain.post.post.dto.request;
2+
3+
import com.back.domain.post.post.enums.PostSortStatus;
4+
5+
public record PostSortScrollRequestDto(
6+
Long lastId,
7+
Integer lastLikeCount,
8+
Integer lastCommentCount,
9+
PostSortStatus postSortStatus
10+
) {
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.back.domain.post.post.enums;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
@Getter
7+
@RequiredArgsConstructor
8+
public enum PostSortStatus {
9+
LATEST("최신순", "작성 날짜가 가장 최신인 게시글 순서부터"),
10+
COMMENTS("댓글순", "게시글에 달린 댓글이 많은 순서부터"),
11+
POPULAR("인기순", "추천수가 많은 순서부터");
12+
13+
private final String title;
14+
private final String description;
15+
}

src/main/java/com/back/domain/post/post/repository/PostRepository.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,18 @@
77

88
@Repository
99
public interface PostRepository extends JpaRepository<Post, Long> {
10-
// 첫 페이지 (최신순, id 기준)
11-
List<Post> findTop10ByOrderByIdDesc();
1210

13-
// 이후 페이지 (lastId보다 작은 id들 중 최신순)
11+
// 최신순
12+
List<Post> findTop10ByOrderByIdDesc();
1413
List<Post> findTop10ByIdLessThanOrderByIdDesc(Long lastId);
14+
15+
// 추천순
16+
List<Post> findTop10ByOrderByLikeCountDescIdDesc();
17+
List<Post> findTop10ByLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(
18+
Integer likeCount, Integer likeCount2, Long id);
19+
20+
// 댓글순
21+
List<Post> findTop10ByOrderByCommentCountDescIdDesc();
22+
List<Post> findTop10ByCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(
23+
Integer commentCount, Integer commentCount2, Long id);
1524
}

src/main/java/com/back/domain/post/post/service/PostService.java

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.back.domain.post.category.entity.Category;
66
import com.back.domain.post.category.repository.CategoryRepository;
77
import com.back.domain.post.post.dto.request.PostCreateRequestDto;
8+
import com.back.domain.post.post.dto.request.PostSortScrollRequestDto;
89
import com.back.domain.post.post.dto.request.PostUpdateRequestDto;
910
import com.back.domain.post.post.dto.response.PostResponseDto;
1011
import com.back.domain.post.post.entity.Post;
@@ -97,15 +98,34 @@ public PostResponseDto createPost(PostCreateRequestDto reqBody, List<MultipartFi
9798

9899
// 게시글 다건 조회 로직
99100
@Transactional(readOnly = true)
100-
public List<PostResponseDto> getAllPosts(Long lastId) {
101+
public List<PostResponseDto> getPosts(PostSortScrollRequestDto reqBody) {
101102
List<Post> posts;
102103

103-
if (lastId == null) {
104-
// 첫 페이지 요청
105-
posts = postRepository.findTop10ByOrderByIdDesc();
106-
} else {
107-
// 이후 페이지 요청
108-
posts = postRepository.findTop10ByIdLessThanOrderByIdDesc(lastId);
104+
switch (reqBody.postSortStatus()) {
105+
case POPULAR -> {
106+
if (reqBody.lastId() == null || reqBody.lastLikeCount() == null) {
107+
posts = postRepository.findTop10ByOrderByLikeCountDescIdDesc();
108+
} else {
109+
posts = postRepository.findTop10ByLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(reqBody.lastLikeCount(), reqBody.lastLikeCount(), reqBody.lastId());
110+
}
111+
}
112+
case COMMENTS -> {
113+
if (reqBody.lastId() == null || reqBody.lastCommentCount() == null) {
114+
posts = postRepository.findTop10ByOrderByCommentCountDescIdDesc();
115+
} else {
116+
posts = postRepository.findTop10ByCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(reqBody.lastCommentCount(), reqBody.lastCommentCount(), reqBody.lastId());
117+
}
118+
}
119+
case LATEST -> {
120+
if (reqBody.lastId() == null) {
121+
// 첫 페이지 요청
122+
posts = postRepository.findTop10ByOrderByIdDesc();
123+
} else {
124+
// 이후 페이지 요청
125+
posts = postRepository.findTop10ByIdLessThanOrderByIdDesc(reqBody.lastId());
126+
}
127+
}
128+
default -> throw new IllegalArgumentException("지원하지 않는 정렬 기준: " + reqBody.postSortStatus());
109129
}
110130

111131
return posts.stream()

src/test/java/com/back/domain/post/post/controller/PostControllerTest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
1616

1717
import com.back.domain.post.post.dto.request.PostCreateRequestDto;
18+
import com.back.domain.post.post.dto.request.PostSortScrollRequestDto;
1819
import com.back.domain.post.post.dto.request.PostUpdateRequestDto;
1920
import com.back.domain.post.post.dto.response.PostResponseDto;
21+
import com.back.domain.post.post.enums.PostSortStatus;
2022
import com.back.domain.post.post.enums.PostStatus;
2123
import com.back.domain.post.post.service.PostService;
2224
import com.back.global.jwt.JwtUtil;
@@ -108,7 +110,7 @@ void createPost() throws Exception {
108110

109111
@Test
110112
@DisplayName("게시글 다건 조회 API 테스트")
111-
void getAllPosts() throws Exception {
113+
void getPosts() throws Exception {
112114
// given
113115
List<PostResponseDto> firstPage = new ArrayList<>();
114116
for (long i = 30; i >= 21; i--) {
@@ -120,8 +122,8 @@ void getAllPosts() throws Exception {
120122
secondPage.add(createSampleResponseDto(i));
121123
}
122124

123-
given(postService.getAllPosts(null)).willReturn(firstPage); // 첫 호출(lastId 없음)
124-
given(postService.getAllPosts(21L)).willReturn(secondPage);
125+
given(postService.getPosts(new PostSortScrollRequestDto(null, 0, 0, PostSortStatus.LATEST))).willReturn(firstPage); // 첫 호출(lastId 없음)
126+
given(postService.getPosts(new PostSortScrollRequestDto(21L, 0, 0, PostSortStatus.LATEST))).willReturn(secondPage);
125127

126128
// when & then
127129
mockMvc.perform(get("/posts"))
@@ -221,7 +223,7 @@ void updatePost() throws Exception {
221223
0, // commentCount
222224
0 // viewCount
223225
);
224-
given(postService.updatePost(eq(1L), any(PostUpdateRequestDto.class), any(null))).willReturn(responseDto);
226+
given(postService.updatePost(eq(1L), any(PostUpdateRequestDto.class), List.of())).willReturn(responseDto);
225227

226228
// when & then
227229
mockMvc.perform(patch("/posts/{postId}", postId)

0 commit comments

Comments
 (0)