Skip to content

Feat: [FN-151] 카드셋 목록 조회시 좋아요순 정렬 기능#44

Merged
dungbik merged 4 commits into
developfrom
feat/cardset-search
Sep 15, 2025
Merged

Feat: [FN-151] 카드셋 목록 조회시 좋아요순 정렬 기능#44
dungbik merged 4 commits into
developfrom
feat/cardset-search

Conversation

@dungbik
Copy link
Copy Markdown
Contributor

@dungbik dungbik commented Sep 9, 2025

📝 변경 내용


✅ 체크리스트

  • 코드가 정상적으로 동작함
  • 테스트 코드 통과함
  • 문서(README 등)를 최신화함
  • 코드 스타일 가이드 준수

💬 기타 참고 사항

Summary by CodeRabbit

  • 신규 기능

    • 카드세트 목록에서 좋아요 수 기준 정렬 지원이 추가되었습니다.
    • 검색 시 동적 정렬과 페이지네이션 동작이 개선되었습니다.
  • 리팩터링

    • 정렬 가능한 필드 관리가 중앙화되어 일관성이 높아졌습니다.
    • 기본 정렬 규칙이 명확해져 잘못된 정렬 요청에도 안정적으로 동작합니다.
    • 검색 처리 로직이 개선되어 가독성과 유지보수성이 향상되었습니다.

@dungbik dungbik self-assigned this Sep 9, 2025
@dungbik dungbik added the enhancement New feature or request label Sep 9, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Sep 9, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

카드셋 검색/정렬 로직을 리팩토링: 정렬 허용 필드를 enum으로 외부화하고 페이징 정렬 파싱을 PagingRequest로 이동. 기존 JPQL 기반 검색을 커스텀 리포지토리로 이전하고 QueryDSL 구현을 추가해 LIKE(좋아요) 정렬, ID 기본 정렬 및 publicVisible 필터를 적용함.

Changes

Cohort / File(s) Summary
Paging/Sort 인프라 정비
src/main/java/project/flipnote/common/model/request/PagingRequest.java, src/main/java/project/flipnote/cardset/model/CardSetSearchRequest.java, src/main/java/project/flipnote/cardset/model/CardSetSortField.java
PagingRequest에 getOrder()/getSortBy() 추가 및 getPageRequest 단순화. CardSetSearchRequest가 허용 정렬 필드로 CardSetSortField.getFieldNames() 사용하도록 변경(기본값 대문자 "ID"). 신규 enum CardSetSortField(ID, LIKE) 추가.
리포지토리 인터페이스 변경
src/main/java/project/flipnote/cardset/repository/CardSetRepository.java, src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustom.java
CardSetRepositoryCardSetRepositoryCustom 확장하도록 수정. 기존 JPQL findByNameContainingAndCategory(...) 제거. 커스텀 인터페이스에 searchByNameContainingAndCategory(String, Category, Pageable) 선언 추가. findPrivateIdsByGroupId 쿼리 추가.
QueryDSL 커스텀 구현 추가
src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustomImpl.java
QueryDSL 기반 검색 구현 추가: 이름 포함/카테고리 필터 및 publicVisible=true, Pageable의 Sort를 OrderSpecifier로 변환. LIKE 정렬 시 metadata 조인 처리, id 정렬 기본 보강, 별도 content/count 쿼리 수행.
Service 호출 경로 변경 및 주석 정리
src/main/java/project/flipnote/cardset/service/CardSetService.java
repository 호출을 searchByNameContainingAndCategory(...)로 변경하고 TODO 주석 축약. 응답 매핑과 시그니처는 유지.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as 클라이언트
  participant S as CardSetService
  participant R as CardSetRepository (Custom)
  participant Q as JPAQueryFactory
  participant DB as DB

  C->>S: getCardSets(request)
  S->>R: searchByNameContainingAndCategory(name, category, pageable)
  Note over R: where: name?, category?, publicVisible=true
  R->>R: pageable.sort 해석\n(LIKE -> likeCount 메타조인 필요)
  alt LIKE 정렬 포함
    R->>Q: select CardSet join CardSetMetadata with orders
  else ID 정렬 또는 기본
    R->>Q: select CardSet with id order (기본 id.desc 추가 가능)
  end
  Q->>DB: 실행 (offset/limit + order)
  DB-->>Q: 결과 목록
  R->>Q: count query (동일 필터)
  Q->>DB: count(*)
  DB-->>Q: 총개수
  Q-->>R: content + total
  R-->>S: Page<CardSet>
  S-->>C: PagingResponse
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • stoneTiger0912

Poem

좋아요로 춤추는 정렬밤, 나는 토끼
id는 기본, LIKE는 향기로운 당근 맛
조인 살짝, 카운트는 따로 떼어
페이지가 오면 깡충 한 바퀴
리뷰에 당근 한 조각 드릴게요 🥕🐇

Pre-merge checks (1 passed, 1 warning, 1 inconclusive)

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ❓ Inconclusive 현재 PR 설명은 변경 내용 섹션과 기타 참고 사항이 모두 비어 있어 실제로 어떤 기능이 어떻게 구현되었는지 알기 어려워 매우 일반적인 템플릿 형태에 머물러 있습니다. ‘## 📝 변경 내용’에 구체적인 구현 세부사항을 작성하고 체크리스트 항목을 실제로 완료한 내용을 반영하여 설명을 보강해 주세요.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed PR 제목 ‘Feat: FN-151 카드셋 목록 조회시 좋아요순 정렬 기능’은 변경 사항의 핵심인 카드셋 목록 조회 시 좋아요순 정렬 기능 추가를 명확하게 요약하고 있어 적절합니다.

Poem

좋아요로 춤추는 정렬밤, 나는 토끼
id는 기본, LIKE는 향기로운 당근 맛
조인 살짜쿵, 카운트는 따로 떼어
페이지가 오면 깡충 한 바퀴
리뷰에 당근 한 조각 드릴게요 🥕🐇

Pre-merge checks (1 passed, 1 warning, 1 inconclusive)

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ❓ Inconclusive 현재 PR 설명은 변경 내용 섹션과 기타 참고 사항이 모두 비어 있어 실제로 어떤 기능이 어떻게 구현되었는지 알기 어려워 매우 일반적인 템플릿 형태에 머물러 있습니다. ‘## 📝 변경 내용’에 구체적인 구현 세부사항을 작성하고 체크리스트 항목을 실제로 완료한 내용을 반영하여 설명을 보강해 주세요.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed PR 제목 ‘Feat: FN-151 카드셋 목록 조회시 좋아요순 정렬 기능’은 변경 사항의 핵심인 카드셋 목록 조회 시 좋아요순 정렬 기능 추가를 명확하게 요약하고 있어 적절합니다.

Poem

봄빛 같은 정렬, 톡-톡 LIKE와 ID
토끼는 수염을 정리하고 쿼리를 다듬지
이름은 살짝, 카테고리는 딱!
조인은 살며시, 카운트는 분리딱
페이지가 착— 하고 오면
나는 깡총! 리뷰 준비 완료 🐇✨

Pre-merge checks (1 passed, 1 warning, 1 inconclusive)

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ❓ Inconclusive 현재 PR 설명은 변경 내용 섹션과 기타 참고 사항이 모두 비어 있어 실제로 어떤 기능이 어떻게 구현되었는지 알기 어려워 매우 일반적인 템플릿 형태에 머물러 있습니다. ‘## 📝 변경 내용’에 구체적인 구현 세부사항을 작성하고 체크리스트 항목을 실제로 완료한 내용을 반영하여 설명을 보강해 주세요.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed PR 제목 ‘Feat: FN-151 카드셋 목록 조회시 좋아요순 정렬 기능’은 변경 사항의 핵심인 카드셋 목록 조회 시 좋아요순 정렬 기능 추가를 명확하게 요약하고 있어 적절합니다.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between beaf0b1 and e52bf50.

📒 Files selected for processing (5)
  • src/main/java/project/flipnote/cardset/repository/CardSetRepository.java (1 hunks)
  • src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustom.java (1 hunks)
  • src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustomImpl.java (1 hunks)
  • src/main/java/project/flipnote/cardset/service/CardSetService.java (1 hunks)
  • src/main/java/project/flipnote/common/model/request/PagingRequest.java (1 hunks)

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/main/java/project/flipnote/cardset/model/CardSetSortField.java (1)

10-14: EnumSet 사용을 고려해보세요

getFieldNames() 메서드는 매번 호출될 때마다 새로운 Set을 생성합니다. 성능 최적화를 위해 결과를 캐싱하거나 EnumSet을 활용하는 것이 더 효율적일 수 있습니다.

다음과 같이 개선할 수 있습니다:

+import java.util.EnumSet;
 import java.util.Arrays;
 import java.util.Set;
 import java.util.stream.Collectors;

 public enum CardSetSortField {
 	ID, LIKE;
+
+	private static final Set<String> FIELD_NAMES = EnumSet.allOf(CardSetSortField.class)
+		.stream()
+		.map(Enum::name)
+		.collect(Collectors.toUnmodifiableSet());

 	public static Set<String> getFieldNames() {
-		return Arrays.stream(values())
-			.map(CardSetSortField::name)
-			.collect(Collectors.toSet());
+		return FIELD_NAMES;
 	}
 }
src/main/java/project/flipnote/cardset/model/CardSetSearchRequest.java (1)

26-34: 좋은 검증 로직입니다

허용된 정렬 필드를 검증하고 기본값을 제공하는 로직이 잘 구현되었습니다. 다만, 부모 클래스의 getSortBy()가 이미 대문자로 변환하므로 중복 변환이 일어날 수 있습니다.

부모 클래스가 이미 대문자로 변환하는 경우를 고려하여:

 @Override
 public String getSortBy() {
 	String sortBy = super.getSortBy();
-	if (sortBy != null && ALLOWED_SORT_FIELDS.contains(sortBy)) {
+	// super.getSortBy()는 이미 대문자로 변환됨
+	if (sortBy != null && ALLOWED_SORT_FIELDS.contains(sortBy)) {
 		return sortBy;
 	}
 
 	return "ID";
 }
src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustomImpl.java (1)

68-70: 메타데이터 누락 카드셋 포함 검증

CardSetMetadata는 CardSetService에서 생성돼 신규 카드셋엔 항상 존재하지만, 과거 데이터에 메타데이터가 없으면 INNER JOIN(join()) 사용 시 해당 카드셋이 제외됩니다.

  • 기존 카드셋에 metadata가 누락되지 않았는지(마이그레이션/초기화 여부) 확인하세요.
  • 누락 가능성이 있다면 join()을 leftJoin(m).on(c.id.eq(m.id))으로 변경하거나, 메타데이터를 이관하는 스크립트를 추가 실행하세요.

File: src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustomImpl.java Lines 68–70

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f55c3e8 and beaf0b1.

📒 Files selected for processing (7)
  • src/main/java/project/flipnote/cardset/model/CardSetSearchRequest.java (1 hunks)
  • src/main/java/project/flipnote/cardset/model/CardSetSortField.java (1 hunks)
  • src/main/java/project/flipnote/cardset/repository/CardSetRepository.java (1 hunks)
  • src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustom.java (1 hunks)
  • src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustomImpl.java (1 hunks)
  • src/main/java/project/flipnote/cardset/service/CardSetService.java (1 hunks)
  • src/main/java/project/flipnote/common/model/request/PagingRequest.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustom.java (1)
src/main/java/project/flipnote/cardset/entity/CardSet.java (1)
  • Getter (22-69)
src/main/java/project/flipnote/cardset/service/CardSetService.java (1)
src/main/java/project/flipnote/cardset/entity/CardSet.java (1)
  • Getter (22-69)
src/main/java/project/flipnote/cardset/repository/CardSetRepository.java (3)
src/main/java/project/flipnote/group/repository/GroupRepository.java (1)
  • Repository (14-27)
src/main/java/project/flipnote/cardset/entity/CardSet.java (1)
  • Getter (22-69)
src/main/java/project/flipnote/group/repository/GroupMemberRepository.java (1)
  • Repository (14-29)
src/main/java/project/flipnote/common/model/request/PagingRequest.java (3)
src/main/java/project/flipnote/bookmark/model/BookmarkSearchRequest.java (2)
  • Getter (10-18)
  • Override (14-17)
src/main/java/project/flipnote/common/model/request/CursorPagingRequest.java (2)
  • Getter (13-60)
  • Schema (45-59)
src/main/java/project/flipnote/group/model/GroupInvitationListRequest.java (2)
  • Override (10-13)
  • GroupInvitationListRequest (8-14)
src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustomImpl.java (2)
src/main/java/project/flipnote/cardset/repository/CardSetMetadataRepository.java (2)
  • CardSetMetadataRepository (10-23)
  • Modifying (12-14)
src/main/java/project/flipnote/cardset/entity/CardSet.java (1)
  • Getter (22-69)
src/main/java/project/flipnote/cardset/model/CardSetSearchRequest.java (3)
src/main/java/project/flipnote/bookmark/model/BookmarkSearchRequest.java (2)
  • Getter (10-18)
  • Override (14-17)
src/main/java/project/flipnote/common/model/request/CursorPagingRequest.java (2)
  • Getter (13-60)
  • Schema (45-59)
src/main/java/project/flipnote/cardset/entity/CardSet.java (1)
  • Getter (22-69)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (4)
src/main/java/project/flipnote/cardset/service/CardSetService.java (1)

123-123: TODO 주석이 단순화되었습니다

TODO 주석이 이전의 자세한 내용에서 "Projection 튜닝 필요"로 단순화되었습니다. 중요한 정보가 손실되지 않았는지 확인이 필요합니다.

src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustom.java (1)

11-15: 인터페이스 메서드 정의가 명확합니다

카드셋 검색 메서드의 시그니처가 명확하게 정의되어 있습니다.

src/main/java/project/flipnote/cardset/repository/CardSetRepository.java (1)

11-11: Custom Repository 통합이 잘 되었습니다

JPA Repository와 Custom Repository를 적절히 결합하여 확장성 있는 구조를 만들었습니다.

src/main/java/project/flipnote/cardset/repository/CardSetRepositoryCustomImpl.java (1)

78-86: count 쿼리와 select 쿼리의 조건이 일치합니다

count 쿼리의 WHERE 조건이 select 쿼리와 동일하게 유지되고 있어 정확한 페이징이 가능합니다. 좋은 구현입니다.

@dungbik dungbik merged commit 81daaa7 into develop Sep 15, 2025
2 checks passed
@dungbik dungbik deleted the feat/cardset-search branch September 15, 2025 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants