diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/community/comment/service/CommentService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/community/comment/service/CommentService.java index 41d2d488..0bd03278 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/community/comment/service/CommentService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/community/comment/service/CommentService.java @@ -47,7 +47,7 @@ public CommentPageResponse getComments(Long postId, int page) { Pageable pageable = PageRequest.of( page - 1, - 20, + 10, Sort.by(Sort.Direction.ASC, "createdDate") ); diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/JoinPostController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/JoinPostController.java index 4ad0bda8..82298c8f 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/JoinPostController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/JoinPostController.java @@ -8,11 +8,16 @@ import com.back.web7_9_codecrete_be.global.rq.Rq; import com.back.web7_9_codecrete_be.global.rsData.RsData; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequestMapping("/api/v1/join") @RequiredArgsConstructor @@ -73,4 +78,23 @@ public RsData close( joinPostService.close(postId, user.getId()); return RsData.success("구인글이 마감되었습니다."); } + + @Operation(summary = "구인글 검색", description = "제목 또는 내용에 키워드를 포함하고 있는 구인글을 검색합니다.") + @GetMapping("/search") + public RsData> search( + @Schema(description = """ +

검색어가 되는 Keyword입니다.

+
+ ?keyword={keyword} 로 값을 넘기시면 됩니다.
+ 제목 또는 내용에 해당 문자열을 포함하는 구인글을 + 페이징된 만큼 반환합니다. + """) + @RequestParam String keyword, + @Schema(description = "페이징 처리 또는 무한 스크롤 구현에 사용하는 Pageable 객체입니다.") + @Parameter(hidden = true) Pageable pageable + ) { + return RsData.success( + joinPostService.searchByKeyword(keyword, pageable) + ); + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/ReviewPostController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/ReviewPostController.java index 89af0ca4..7b080bd4 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/ReviewPostController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/ReviewPostController.java @@ -9,12 +9,17 @@ import com.back.web7_9_codecrete_be.global.rq.Rq; import com.back.web7_9_codecrete_be.global.rsData.RsData; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequestMapping("/api/v1/reviews") @RequiredArgsConstructor @@ -86,4 +91,24 @@ public RsData getReviewsByConcert( reviewPostService.getReviewsByConcert(concertId) ); } + + @Operation(summary = "후기 게시글 검색", description = "제목 또는 내용에 키워드를 포함하고 있는 후기 게시글을 검색합니다.") + @GetMapping("/search") + public RsData> search( + @Schema(description = """ +

검색어가 되는 Keyword입니다.

+
+ ?keyword={keyword} 로 값을 넘기시면 됩니다.
+ 제목 또는 내용에 해당 문자열을 포함하는 + 후기 게시글을 페이징된 만큼 반환합니다. + """) + @RequestParam String keyword, + + @Schema(description = "페이징 처리 또는 무한 스크롤 구현에 사용하는 Pageable 객체입니다.") + @Parameter(hidden = true) Pageable pageable + ) { + return RsData.success( + reviewPostService.searchByKeyword(keyword, pageable) + ); + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/JoinPostRepository.java b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/JoinPostRepository.java index ee333913..0f72a468 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/JoinPostRepository.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/JoinPostRepository.java @@ -4,7 +4,29 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; public interface JoinPostRepository extends JpaRepository { Page findByPost_UserId(Long userId, Pageable pageable); + + @Query(""" + SELECT + jp + FROM + JoinPost jp + JOIN FETCH + jp.post p + WHERE + p.title LIKE %:keyword% + OR p.content LIKE %:keyword% + ORDER BY + p.createdDate DESC +""") + List searchByKeyword( + @Param("keyword") String keyword, + Pageable pageable + ); } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/ReviewPostRepository.java b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/ReviewPostRepository.java index 25d047b4..c12af80b 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/ReviewPostRepository.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/ReviewPostRepository.java @@ -4,7 +4,29 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; public interface ReviewPostRepository extends JpaRepository { Page findByPost_UserId(Long userId, Pageable pageable); + + @Query(""" + SELECT + rp + FROM + ReviewPost rp + JOIN FETCH + rp.post p + WHERE + p.title LIKE %:keyword% + OR p.content LIKE %:keyword% + ORDER BY + p.createdDate DESC + """) + List searchByKeyword( + @Param("keyword") String keyword, + Pageable pageable + ); } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/JoinPostService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/JoinPostService.java index ce2eb9c0..f604e242 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/JoinPostService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/JoinPostService.java @@ -14,9 +14,12 @@ import com.back.web7_9_codecrete_be.global.error.code.PostErrorCode; import com.back.web7_9_codecrete_be.global.error.exception.BusinessException; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service @RequiredArgsConstructor public class JoinPostService { @@ -117,4 +120,15 @@ public void close(Long postId, Long userId) { joinPost.close(); // status = CLOSED } + + public List searchByKeyword(String keyword, Pageable pageable) { + if (keyword == null || keyword.isEmpty()) { + throw new BusinessException(PostErrorCode.KEYWORD_IS_NULL); + } + + return joinPostRepository.searchByKeyword(keyword, pageable) + .stream() + .map(JoinPostResponse::from) + .toList(); + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/ReviewPostService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/ReviewPostService.java index b355b54b..cd7cfac8 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/ReviewPostService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/ReviewPostService.java @@ -20,6 +20,7 @@ import com.back.web7_9_codecrete_be.global.storage.ImageFileValidator; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -268,5 +269,23 @@ private ReviewItemResponse toReviewItem(ReviewPost reviewPost) { .createdDate(reviewPost.getPost().getCreatedDate()) .build(); } + + public List searchByKeyword(String keyword, Pageable pageable) { + if (keyword == null || keyword.isBlank()) { + throw new BusinessException(PostErrorCode.KEYWORD_IS_NULL); + } + + return reviewPostRepository.searchByKeyword(keyword, pageable) + .stream() + .map(reviewPost -> { + List imageUrls = reviewPost.getImages() + .stream() + .map(ReviewImage::getImageUrl) + .toList(); + + return ReviewPostResponse.from(reviewPost, imageUrls); + }) + .toList(); + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/global/error/code/PostErrorCode.java b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/PostErrorCode.java index 2bf5869e..4c96c136 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/global/error/code/PostErrorCode.java +++ b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/PostErrorCode.java @@ -40,6 +40,13 @@ public enum PostErrorCode implements ErrorCode { HttpStatus.BAD_REQUEST, "P-130", "이미 삭제된 게시글입니다." + ), + + // 검색 관련 + KEYWORD_IS_NULL( + HttpStatus.BAD_REQUEST, + "P-140", + "검색어는 필수입니다." ); private final HttpStatus status;