diff --git a/src/main/java/com/back/domain/post/post/controller/PostController.java b/src/main/java/com/back/domain/post/post/controller/PostController.java index e464ca3..8d87486 100644 --- a/src/main/java/com/back/domain/post/post/controller/PostController.java +++ b/src/main/java/com/back/domain/post/post/controller/PostController.java @@ -1,6 +1,7 @@ package com.back.domain.post.post.controller; import com.back.domain.post.post.dto.request.PostCreateRequestDto; +import com.back.domain.post.post.dto.request.PostSortScrollRequestDto; import com.back.domain.post.post.dto.request.PostUpdateRequestDto; import com.back.domain.post.post.dto.response.PostResponseDto; import com.back.domain.post.post.service.PostService; @@ -13,11 +14,11 @@ import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @@ -48,15 +49,15 @@ public RsData createPost( /** * 게시글 다건 조회 API - * @param lastId 마지막으로 조회한 게시글 ID (페이징 처리용, optional) + * @param reqBody 게시글 정렬 및 스크롤 요청 DTO * @return 게시글 목록 */ @GetMapping @Operation(summary = "게시글 다건 조회") - public RsData> getAllPosts( - @RequestParam(required = false) Long lastId + public RsData> getPosts( + @ModelAttribute PostSortScrollRequestDto reqBody ) { - return RsData.successOf(postService.getAllPosts(lastId)); // code=200, message="success" + return RsData.successOf(postService.getPosts(reqBody)); // code=200, message="success" } /** @@ -76,6 +77,7 @@ public RsData getPost( * 게시글 수정 API * @param postId 수정할 게시글 ID * @param reqBody 게시글 수정 요청 DTO + * @param images 첨부 이미지 파일들 (optional) * @return 수정된 게시글 정보 */ @PatchMapping(value = "/{postId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) diff --git a/src/main/java/com/back/domain/post/post/dto/request/PostSortScrollRequestDto.java b/src/main/java/com/back/domain/post/post/dto/request/PostSortScrollRequestDto.java new file mode 100644 index 0000000..f4bec59 --- /dev/null +++ b/src/main/java/com/back/domain/post/post/dto/request/PostSortScrollRequestDto.java @@ -0,0 +1,11 @@ +package com.back.domain.post.post.dto.request; + +import com.back.domain.post.post.enums.PostSortStatus; + +public record PostSortScrollRequestDto( + Long lastId, + Integer lastLikeCount, + Integer lastCommentCount, + PostSortStatus postSortStatus +) { +} \ No newline at end of file diff --git a/src/main/java/com/back/domain/post/post/enums/PostSortStatus.java b/src/main/java/com/back/domain/post/post/enums/PostSortStatus.java new file mode 100644 index 0000000..1768405 --- /dev/null +++ b/src/main/java/com/back/domain/post/post/enums/PostSortStatus.java @@ -0,0 +1,15 @@ +package com.back.domain.post.post.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum PostSortStatus { + LATEST("최신순", "작성 날짜가 가장 최신인 게시글 순서부터"), + COMMENTS("댓글순", "게시글에 달린 댓글이 많은 순서부터"), + POPULAR("인기순", "추천수가 많은 순서부터"); + + private final String title; + private final String description; +} diff --git a/src/main/java/com/back/domain/post/post/repository/PostRepository.java b/src/main/java/com/back/domain/post/post/repository/PostRepository.java index ad956f6..f315672 100644 --- a/src/main/java/com/back/domain/post/post/repository/PostRepository.java +++ b/src/main/java/com/back/domain/post/post/repository/PostRepository.java @@ -7,9 +7,18 @@ @Repository public interface PostRepository extends JpaRepository { - // 첫 페이지 (최신순, id 기준) - List findTop10ByOrderByIdDesc(); - // 이후 페이지 (lastId보다 작은 id들 중 최신순) + // 최신순 + List findTop10ByOrderByIdDesc(); List findTop10ByIdLessThanOrderByIdDesc(Long lastId); + + // 추천순 + List findTop10ByOrderByLikeCountDescIdDesc(); + List findTop10ByLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc( + Integer likeCount, Integer likeCount2, Long id); + + // 댓글순 + List findTop10ByOrderByCommentCountDescIdDesc(); + List findTop10ByCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc( + Integer commentCount, Integer commentCount2, Long id); } diff --git a/src/main/java/com/back/domain/post/post/service/PostService.java b/src/main/java/com/back/domain/post/post/service/PostService.java index 07d11bf..0ed5c2f 100644 --- a/src/main/java/com/back/domain/post/post/service/PostService.java +++ b/src/main/java/com/back/domain/post/post/service/PostService.java @@ -5,6 +5,7 @@ import com.back.domain.post.category.entity.Category; import com.back.domain.post.category.repository.CategoryRepository; import com.back.domain.post.post.dto.request.PostCreateRequestDto; +import com.back.domain.post.post.dto.request.PostSortScrollRequestDto; import com.back.domain.post.post.dto.request.PostUpdateRequestDto; import com.back.domain.post.post.dto.response.PostResponseDto; import com.back.domain.post.post.entity.Post; @@ -97,15 +98,34 @@ public PostResponseDto createPost(PostCreateRequestDto reqBody, List getAllPosts(Long lastId) { + public List getPosts(PostSortScrollRequestDto reqBody) { List posts; - if (lastId == null) { - // 첫 페이지 요청 - posts = postRepository.findTop10ByOrderByIdDesc(); - } else { - // 이후 페이지 요청 - posts = postRepository.findTop10ByIdLessThanOrderByIdDesc(lastId); + switch (reqBody.postSortStatus()) { + case POPULAR -> { + if (reqBody.lastId() == null || reqBody.lastLikeCount() == null) { + posts = postRepository.findTop10ByOrderByLikeCountDescIdDesc(); + } else { + posts = postRepository.findTop10ByLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(reqBody.lastLikeCount(), reqBody.lastLikeCount(), reqBody.lastId()); + } + } + case COMMENTS -> { + if (reqBody.lastId() == null || reqBody.lastCommentCount() == null) { + posts = postRepository.findTop10ByOrderByCommentCountDescIdDesc(); + } else { + posts = postRepository.findTop10ByCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(reqBody.lastCommentCount(), reqBody.lastCommentCount(), reqBody.lastId()); + } + } + case LATEST -> { + if (reqBody.lastId() == null) { + // 첫 페이지 요청 + posts = postRepository.findTop10ByOrderByIdDesc(); + } else { + // 이후 페이지 요청 + posts = postRepository.findTop10ByIdLessThanOrderByIdDesc(reqBody.lastId()); + } + } + default -> throw new IllegalArgumentException("지원하지 않는 정렬 기준: " + reqBody.postSortStatus()); } return posts.stream() diff --git a/src/test/java/com/back/domain/post/post/controller/PostControllerTest.java b/src/test/java/com/back/domain/post/post/controller/PostControllerTest.java index 41d0928..e6d4957 100644 --- a/src/test/java/com/back/domain/post/post/controller/PostControllerTest.java +++ b/src/test/java/com/back/domain/post/post/controller/PostControllerTest.java @@ -15,8 +15,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.back.domain.post.post.dto.request.PostCreateRequestDto; +import com.back.domain.post.post.dto.request.PostSortScrollRequestDto; import com.back.domain.post.post.dto.request.PostUpdateRequestDto; import com.back.domain.post.post.dto.response.PostResponseDto; +import com.back.domain.post.post.enums.PostSortStatus; import com.back.domain.post.post.enums.PostStatus; import com.back.domain.post.post.service.PostService; import com.back.global.jwt.JwtUtil; @@ -108,7 +110,7 @@ void createPost() throws Exception { @Test @DisplayName("게시글 다건 조회 API 테스트") - void getAllPosts() throws Exception { + void getPosts() throws Exception { // given List firstPage = new ArrayList<>(); for (long i = 30; i >= 21; i--) { @@ -120,8 +122,8 @@ void getAllPosts() throws Exception { secondPage.add(createSampleResponseDto(i)); } - given(postService.getAllPosts(null)).willReturn(firstPage); // 첫 호출(lastId 없음) - given(postService.getAllPosts(21L)).willReturn(secondPage); + given(postService.getPosts(new PostSortScrollRequestDto(null, 0, 0, PostSortStatus.LATEST))).willReturn(firstPage); // 첫 호출(lastId 없음) + given(postService.getPosts(new PostSortScrollRequestDto(21L, 0, 0, PostSortStatus.LATEST))).willReturn(secondPage); // when & then mockMvc.perform(get("/posts")) @@ -221,7 +223,7 @@ void updatePost() throws Exception { 0, // commentCount 0 // viewCount ); - given(postService.updatePost(eq(1L), any(PostUpdateRequestDto.class), any(null))).willReturn(responseDto); + given(postService.updatePost(eq(1L), any(PostUpdateRequestDto.class), List.of())).willReturn(responseDto); // when & then mockMvc.perform(patch("/posts/{postId}", postId)