본문 바로가기
💻 뚝딱뚝딱/북북클럽

[개발일지 #031] 피드 검색 조회

by 뚜루리 2025. 5. 2.
728x90
320x100

🎯 오늘의 목표

  • 피드 검색 조회

⚙️ 진행한 작업

  • 피드 검색 조회

🛠️ 개발내용

📌  QueryDSL 적용법

아래의 포스팅 참고!

 

[JPA/QueryDSL] 적용하기

은근히 적용하기 빡센 쿼리 데셀....정리해놓자 📌 build.gradle 추가dependencies { implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'}def generated = "build/generated"so

ddururiiiiiii.tistory.com

 

 

 

 

📌  FeedRepositoryCustom.java 생성

package ddururi.bookbookclub.domain.feed.repository;

import ddururi.bookbookclub.domain.feed.entity.Feed;

import org.springframework.data.domain.Pageable;
import java.util.List;

/**
 * 피드 QueryDSL 커스텀 레포지토리 인터페이스
 */
public interface FeedRepositoryCustom {

    /** 키워드 검색 기반 피드 조회 */
    List<Feed> searchFeeds(String keyword, Pageable pageable);
}

 

 

📌  FeedRepositoryImpl.java 생성

package ddururi.bookbookclub.domain.feed.repository;

import com.querydsl.jpa.impl.JPAQueryFactory;
import ddururi.bookbookclub.domain.feed.entity.Feed;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import org.springframework.data.domain.Pageable;
import java.util.List;

import static ddururi.bookbookclub.domain.feed.entity.QFeed.feed;

/**
 * 피드 QueryDSL 커스텀 레포지토리 구현체
 */
@Repository
@RequiredArgsConstructor
public class FeedRepositoryImpl implements FeedRepositoryCustom {

    private final JPAQueryFactory queryFactory;


    @Override
    public List<Feed> searchFeeds(String keyword, Pageable pageable) {
        // 블라인드 제외 + content, title, author, publisher 검색 + 최신순 정렬
        return queryFactory
                .selectFrom(feed)
                .leftJoin(feed.book).fetchJoin()
                .where(
                        feed.isBlinded.isFalse()
                                .and(
                                        feed.content.containsIgnoreCase(keyword)
                                                .or(feed.book.title.containsIgnoreCase(keyword))
                                                .or(feed.book.author.containsIgnoreCase(keyword))
                                                .or(feed.book.publisher.containsIgnoreCase(keyword))
                                )
                )
                .orderBy(feed.createdAt.desc())
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();
    }
}
  • 검색은 피드내용, 저자, 책제목, 출판사 통합하여 검색할 수 있도록 함

 

 

📌  FeedRepository.java 수정

package ddururi.bookbookclub.domain.feed.repository;

import ddururi.bookbookclub.domain.feed.entity.Feed;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

/**
 * 피드 JPA 레포지토리
 */
public interface FeedRepository extends JpaRepository<Feed, Long>, FeedRepositoryCustom {

    /** 블라인드 되지 않은 피드 페이징 조회 */
    Page<Feed> findByIsBlindedFalse(Pageable pageable);

    /** 블라인드 되지 않은 피드 다건 조회 (id 리스트 기반) */
    List<Feed> findByIdInAndIsBlindedFalse(List<Long> ids);
}
  • FeedRepositoryCustom을 extends 받음

 

📌  FeedService.java 수정

    /**
     * 피드 목록 조회 (검색기능, 페이징, 좋아요 수, 좋아요 여부 포함)
     * @param pageable 페이징 요청 정보
     * @param userId 현재 사용자 ID
     * @return 피드 목록 (페이지 형태)
     */
    public List<FeedResponse> searchFeeds(String keyword, Pageable pageable, Long userId) {
        List<Feed> feeds = feedRepository.searchFeeds(keyword, pageable);
        return feeds.stream()
                .map(feed -> {
                    long likeCount = likeService.getLikeCount(feed.getId());
                    boolean liked = likeService.hasUserLiked(userId, feed.getId());
                    return new FeedResponse(feed, likeCount, liked);
                })
                .toList();
    }

 

 

📌  FeedController.java 수정

    /**
     * 피드 목록 조회 (검색 기능, 페이징, 좋아요 수, 좋아요 여부 포함)
     * @param pageable 페이징 요청 정보
     * @param userDetails 현재 로그인한 사용자 정보
     * @return 피드 목록 (페이지 포함)
     */
    @GetMapping("/search")
    public ResponseEntity<ApiResponse<List<FeedResponse>>> searchFeeds(
            @RequestParam String keyword,
            Pageable pageable,
            @AuthenticationPrincipal CustomUserDetails userDetails
    ) {
        List<FeedResponse> feeds = feedService.searchFeeds(keyword, pageable, userDetails.getUser().getId());
        return ResponseEntity.ok(ApiResponse.success(feeds));
    }

 

 

 


[포스트맨으로 테스트하기]

GET http://localhost:8080/api/feeds/search?keyword=미움받을&size=10&page=0

 

[테스트 결과 : 성공]

 

검색 결과가 없을땐 이렇게 뜬다

728x90
320x100