Skip to content

Conversation

@Kimminu7
Copy link
Collaborator

@Kimminu7 Kimminu7 commented Jun 30, 2025

작업 내용

  • QueryDSL을 활용해 조회 성능 최적화 작업
  • 카테고리 필터링 재적용
  • imageUrl 필드 Eager로 변경

변경 사항


트러블 슈팅


해결해야 할 문제


참고 사항


코드 리뷰 전 확인 체크리스트

  • 불필요한 콘솔 로그, 주석 제거
  • 커밋 메시지 컨벤션 준수 (type : )
  • 기능 정상 동작 확인

Summary by CodeRabbit

  • 버그 수정

    • 문제 검색 시 카테고리 필터링이 더 정확하게 동작하도록 개선되었습니다.
  • 리팩터

    • 문제와 카테고리 간의 조회 방식이 명확하게 개선되어, 검색 결과의 일관성이 향상되었습니다.

@Kimminu7 Kimminu7 self-assigned this Jun 30, 2025
@Kimminu7 Kimminu7 added the documentation Improvements or additions to documentation label Jun 30, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 30, 2025

Walkthrough

Problem 엔티티의 imageUrl 컬렉션의 fetch 타입이 LAZY에서 EAGER로 변경되었습니다. 또한, ProblemQueryRepositoryImpl에서 문제와 카테고리 간의 조인 및 카테고리 필터링 로직이 명시적 left join과 조건문을 활용하는 방식으로 리팩터링되었습니다.

Changes

파일/경로 변경 요약
src/main/java/org/ezcode/codetest/domain/problem/model/entity/Problem.java imageUrl 컬렉션의 fetch 타입을 LAZY에서 EAGER로 변경
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemQueryRepositoryImpl.java 문제-카테고리 조인 및 카테고리 필터링 로직을 명시적 left join 및 조건문으로 리팩터링, 카테고리 코드 또는 한글명 일치 조건 추가, total count 쿼리 일관성 확보

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ProblemQueryRepositoryImpl
    participant Database

    Client->>ProblemQueryRepositoryImpl: searchProblems(condition)
    ProblemQueryRepositoryImpl->>Database: SELECT DISTINCT Problem LEFT JOIN ProblemCategory LEFT JOIN Category WHERE category 조건 AND difficulty 조건
    Database-->>ProblemQueryRepositoryImpl: 문제 목록 반환
    ProblemQueryRepositoryImpl-->>Client: 결과 반환
Loading

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • minjee2758
  • NCookies
  • pokerbearkr
  • chat26666
  • thezz9

Poem

🐇
문제와 카테고리, 조인 춤을 추네
이미지도 한 번에, EAGER하게
쿼리도 정교해져, 조건 따라 척척
토끼는 기뻐서 귀를 쫑긋 세웠네
코드의 숲에 봄바람 불어오네!


📜 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 7ba9ee0 and 5ba27a6.

📒 Files selected for processing (2)
  • src/main/java/org/ezcode/codetest/domain/problem/model/entity/Problem.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemQueryRepositoryImpl.java (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: thezz9
PR: ezcode-my/backend#114
File: src/main/java/org/ezcode/codetest/infrastructure/github/GitHubApiClient.java:159-165
Timestamp: 2025-06-28T02:03:38.654Z
Learning: User thezz9's service (ezcode) targets Korean users exclusively ("찐 한국인밖에 안 옴"), so Korean language hardcoding in commit messages and UI elements is intentional and appropriate for their use case.
Learnt from: Kimminu7
PR: ezcode-my/backend#63
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemQueryRepositoryImpl.java:24-40
Timestamp: 2025-06-14T14:33:58.372Z
Learning: ProblemController에서 ProblemSearchCondition 객체는 항상 new ProblemSearchCondition(category, difficulty)로 유효한 인스턴스를 생성해서 전달하므로, ProblemQueryRepositoryImpl의 searchByCondition 메서드에서 searchCondition 파라미터 자체에 대한 null 체크는 불필요하다. category와 difficulty 필드만 각각 null일 수 있다.
Learnt from: chat26666
PR: ezcode-my/backend#31
File: src/main/java/org/ezcode/codetest/domain/problem/model/entity/ProblemSearchDocument.java:49-56
Timestamp: 2025-06-05T00:52:54.460Z
Learning: ProblemSearchDocument.from() 메서드는 트랜잭션 내에서 DB에서 실제로 조회한 Problem 엔티티만 사용하므로 null 체크가 불필요함. 이 컨텍스트에서는 null Problem이 있을 경우 이미 이전 단계에서 예외가 발생함.
Learnt from: Kimminu7
PR: ezcode-my/backend#63
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/problem/ProblemController.java:39-44
Timestamp: 2025-06-14T14:55:06.361Z
Learning: ProblemQueryRepositoryImpl에서 String 타입의 difficulty를 Difficulty enum과 비교할 때는 Difficulty.getDifficultyFromKor() 메서드를 사용해서 String을 enum으로 변환한 후 비교해야 한다. 컨트롤러에서 검증 로직을 추가하지 않고 레포지토리 계층에서 타입 변환을 처리하는 것이 관심사 분리 원칙에 적합하다.
Learnt from: chat26666
PR: ezcode-my/backend#67
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/skill/GameCharacterSkillJpaRepository.java:15-17
Timestamp: 2025-06-17T14:46:51.206Z
Learning: GameCharacterSkillJpaRepository에서 findByCharacterId 메서드는 skill 참조를 하지 않기 때문에 @EntityGraph를 사용하지 않는다. 실제 사용 패턴에 따라 선택적으로 eager loading을 적용하는 것이 성능상 더 효율적이다.
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemQueryRepositoryImpl.java (4)
Learnt from: Kimminu7
PR: ezcode-my/backend#63
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemQueryRepositoryImpl.java:24-40
Timestamp: 2025-06-14T14:33:58.372Z
Learning: ProblemController에서 ProblemSearchCondition 객체는 항상 new ProblemSearchCondition(category, difficulty)로 유효한 인스턴스를 생성해서 전달하므로, ProblemQueryRepositoryImpl의 searchByCondition 메서드에서 searchCondition 파라미터 자체에 대한 null 체크는 불필요하다. category와 difficulty 필드만 각각 null일 수 있다.
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java:0-0
Timestamp: 2025-06-15T04:37:29.231Z
Learning: EncounterChoiceRepositoryImpl in src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java is intentionally a skeleton implementation that is work-in-progress and will be completed later.
Learnt from: chat26666
PR: ezcode-my/backend#31
File: src/main/java/org/ezcode/codetest/domain/problem/model/entity/ProblemSearchDocument.java:49-56
Timestamp: 2025-06-05T00:52:54.460Z
Learning: ProblemSearchDocument.from() 메서드는 트랜잭션 내에서 DB에서 실제로 조회한 Problem 엔티티만 사용하므로 null 체크가 불필요함. 이 컨텍스트에서는 null Problem이 있을 경우 이미 이전 단계에서 예외가 발생함.
Learnt from: Kimminu7
PR: ezcode-my/backend#63
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/problem/ProblemController.java:39-44
Timestamp: 2025-06-14T14:55:06.361Z
Learning: ProblemQueryRepositoryImpl에서 String 타입의 difficulty를 Difficulty enum과 비교할 때는 Difficulty.getDifficultyFromKor() 메서드를 사용해서 String을 enum으로 변환한 후 비교해야 한다. 컨트롤러에서 검증 로직을 추가하지 않고 레포지토리 계층에서 타입 변환을 처리하는 것이 관심사 분리 원칙에 적합하다.
🧬 Code Graph Analysis (1)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemQueryRepositoryImpl.java (3)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemCategoryRepositoryImpl.java (1)
  • Repository (12-49)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/CategoryRepositoryImpl.java (1)
  • Repository (12-36)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemRepositoryImpl.java (1)
  • Repository (14-50)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (5)
src/main/java/org/ezcode/codetest/domain/problem/model/entity/Problem.java (1)

77-77: EAGER 로딩 변경에 대한 성능 영향 검증 필요

imageUrl을 EAGER 로딩으로 변경하면 Problem 엔티티 조회 시 항상 이미지 URL들이 함께 로딩됩니다. 이는 이미지 URL이 항상 필요한 상황에서는 성능을 개선하지만, 그렇지 않은 경우 불필요한 데이터 로딩으로 오히려 성능 저하를 야기할 수 있습니다.

실제 사용 패턴을 고려하여 EAGER 로딩이 적절한지 검증해주세요.

src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemQueryRepositoryImpl.java (4)

7-9: Import 추가 및 변수 선언 적절함

카테고리 조인을 위한 필요한 import들과 QueryDSL 변수들이 올바르게 추가되었습니다.

Also applies to: 17-17, 32-33


41-44: 명시적 조인을 통한 쿼리 구조 개선

Problem -> ProblemCategory -> Category로의 명시적 left join을 통해 카테고리 필터링이 가능하도록 쿼리 구조를 개선한 것이 좋습니다. distinct 사용도 조인으로 인한 중복 결과 방지를 위해 적절합니다.


64-70: 카운트 쿼리 일관성 개선

카운트 쿼리에서도 동일한 조인과 조건을 사용하도록 개선하여 페이징 결과의 일관성을 보장한 것이 좋습니다. countDistinct 사용도 적절합니다.


40-56: 심각한 버그: 카테고리 및 난이도 필터링이 작동하지 않음

현재 코드에서 query 객체가 생성된 후(45번 라인)에 builder에 조건을 추가하고 있어 카테고리와 난이도 필터링이 실제로 적용되지 않습니다.

QueryDSL에서 .where(builder)가 호출된 시점의 builder 상태만 쿼리에 반영되므로, 이후에 builder에 추가된 조건들은 무시됩니다.

다음과 같이 수정해주세요:

+		// 카테고리 필터링
+		if (searchCondition.category() != null) {
+			builder.and(category.code.eq(searchCondition.category())
+				.or(category.korName.eq(searchCondition.category())));
+		}
+
+		// 난이도 필터링
+		if (searchCondition.difficulty() != null) {
+			builder.and(problem.difficulty.eq(Difficulty.valueOf(searchCondition.difficulty())));
+		}
+
 		JPAQuery<Problem> query = jpaQueryFactory
 			.selectDistinct(problem)
 			.from(problem)
 			.leftJoin(problemCategory).on(problem.eq(problemCategory.problem))
 			.leftJoin(problemCategory.category, category)
 			.where(builder);
-
-		// 카테고리 필터링
-		if (searchCondition.category() != null) {
-			builder.and(category.code.eq(searchCondition.category())
-				.or(category.korName.eq(searchCondition.category())));
-		}
-
-		// 난이도 필터링
-		if (searchCondition.difficulty() != null) {
-			builder.and(problem.difficulty.eq(Difficulty.valueOf(searchCondition.difficulty())));
-		}
⛔ Skipped due to learnings
Learnt from: Kimminu7
PR: ezcode-my/backend#63
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemQueryRepositoryImpl.java:24-40
Timestamp: 2025-06-14T14:33:58.372Z
Learning: ProblemController에서 ProblemSearchCondition 객체는 항상 new ProblemSearchCondition(category, difficulty)로 유효한 인스턴스를 생성해서 전달하므로, ProblemQueryRepositoryImpl의 searchByCondition 메서드에서 searchCondition 파라미터 자체에 대한 null 체크는 불필요하다. category와 difficulty 필드만 각각 null일 수 있다.
Learnt from: Kimminu7
PR: ezcode-my/backend#63
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/problem/ProblemController.java:39-44
Timestamp: 2025-06-14T14:55:06.361Z
Learning: ProblemQueryRepositoryImpl에서 String 타입의 difficulty를 Difficulty enum과 비교할 때는 Difficulty.getDifficultyFromKor() 메서드를 사용해서 String을 enum으로 변환한 후 비교해야 한다. 컨트롤러에서 검증 로직을 추가하지 않고 레포지토리 계층에서 타입 변환을 처리하는 것이 관심사 분리 원칙에 적합하다.
Learnt from: chat26666
PR: ezcode-my/backend#31
File: src/main/java/org/ezcode/codetest/domain/problem/model/entity/ProblemSearchDocument.java:49-56
Timestamp: 2025-06-05T00:52:54.460Z
Learning: ProblemSearchDocument.from() 메서드는 트랜잭션 내에서 DB에서 실제로 조회한 Problem 엔티티만 사용하므로 null 체크가 불필요함. 이 컨텍스트에서는 null Problem이 있을 경우 이미 이전 단계에서 예외가 발생함.
Learnt from: NCookies
PR: ezcode-my/backend#27
File: src/main/java/org/ezcode/codetest/application/community/service/ReplyVoteService.java:37-44
Timestamp: 2025-06-04T03:18:43.558Z
Learning: JPA에서 @Query 어노테이션으로 정의된 커스텀 JPQL 쿼리는 EntityManager의 1차 캐시를 우회하고 항상 데이터베이스에 직접 쿼리를 실행한다. 캐시 효과를 얻으려면 표준 JPA 메서드(findById, save 등)를 사용해야 한다.
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Kimminu7 Kimminu7 merged commit ce44244 into dev Jun 30, 2025
2 checks passed
@Kimminu7 Kimminu7 deleted the feature/problem-improvement branch June 30, 2025 10:04
NCookies pushed a commit that referenced this pull request Jun 30, 2025
* feat : 카테고리 필터링 추가 ( code 또는 korName 필드 조회 )

* feat : join 을 통해 n:m 관계 최적화

* feat : EAGER 즉시 로딩 사용 ( 상세조회, 이미지 )

* feat : 카테고리 필터링 추가 ( code 또는 korName 필드 조회 )

* feat : join 을 통해 n:m 관계 최적화

* feat : EAGER 즉시 로딩 사용 ( 상세조회, 이미지 )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants