Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -48,15 +49,15 @@ public RsData<PostResponseDto> createPost(

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

/**
Expand All @@ -76,6 +77,7 @@ public RsData<PostResponseDto> getPost(
* 게시글 수정 API
* @param postId 수정할 게시글 ID
* @param reqBody 게시글 수정 요청 DTO
* @param images 첨부 이미지 파일들 (optional)
* @return 수정된 게시글 정보
*/
@PatchMapping(value = "/{postId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Expand Down
Original file line number Diff line number Diff line change
@@ -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
) {
}
15 changes: 15 additions & 0 deletions src/main/java/com/back/domain/post/post/enums/PostSortStatus.java
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@

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

// 이후 페이지 (lastId보다 작은 id들 중 최신순)
// 최신순
List<Post> findTop10ByOrderByIdDesc();
List<Post> findTop10ByIdLessThanOrderByIdDesc(Long lastId);

// 추천순
List<Post> findTop10ByOrderByLikeCountDescIdDesc();
List<Post> findTop10ByLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(
Integer likeCount, Integer likeCount2, Long id);

// 댓글순
List<Post> findTop10ByOrderByCommentCountDescIdDesc();
List<Post> findTop10ByCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(
Integer commentCount, Integer commentCount2, Long id);
}
34 changes: 27 additions & 7 deletions src/main/java/com/back/domain/post/post/service/PostService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -97,15 +98,34 @@ public PostResponseDto createPost(PostCreateRequestDto reqBody, List<MultipartFi

// 게시글 다건 조회 로직
@Transactional(readOnly = true)
public List<PostResponseDto> getAllPosts(Long lastId) {
public List<PostResponseDto> getPosts(PostSortScrollRequestDto reqBody) {
List<Post> 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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -108,7 +110,7 @@ void createPost() throws Exception {

@Test
@DisplayName("게시글 다건 조회 API 테스트")
void getAllPosts() throws Exception {
void getPosts() throws Exception {
// given
List<PostResponseDto> firstPage = new ArrayList<>();
for (long i = 30; i >= 21; i--) {
Expand All @@ -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"))
Expand Down Expand Up @@ -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)
Expand Down