Skip to content

[refactor/#91] 문항세트 조회 api 리팩토링 #93

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from

Conversation

seokbeom00
Copy link
Member

@seokbeom00 seokbeom00 commented Mar 12, 2025

💡 Issue

📄 Description

  • 기존 무식하게 구현되어있던 문항세트 조회 api를 개선했습니다.
  • QueryDsl을 활용하여 복잡한 쿼리를 가독성있는 코드로 작성했습니다.
  • 최초 존재하는 문항세트인지 체크하는 조회쿼리와, 발해날짜들을 조회하는 쿼리는 제외한 쿼리들을 중점적으로 설명드리겠습니다.

기존 쿼리

  • 문항세트에 속한 문항들을 개별 조회

  • 문항에 속한 개념태그들을 개별 조회

  • SELECT절에 엔티티가 포함되어, 불필요한 필드들도 조회

  • 위와 같은 문제점들 때문에, 문항세트에 속한 문항의 개수와 문항에 속한 개념태그들의 수가 늘어남에 따라 쿼리의 개수도 배로 증가하는 구조였습니다.

개선된 쿼리

  • 문항세트에 속한 문항ID들을 조회합니다.

  • 조회한 문항ID들을 IN절로 문항 필드들을 조회합니다 (여기서 새끼문항과 join을 통해 새끼문항의 ID들도 가져옵니다).

  • 새끼문항에 속한 개념태그ID들 + 조회한 문항에 속한 개념태그ID들을 IN절로 조회합니다.

  • SELECT절에 필요한 필드만 명시적으로 남겼습니다.

  • 최종적으로 총 4번의 쿼리로 개선했습니다.

💬 To Reviewers

  • 추후, 개념태그가 많은 문항 더미 데이터들을 추가하여 부하테스트를 통해 비교해보면 좋을 것 같습니다.

@seokbeom00 seokbeom00 added the Type: Refactor [이슈 목적] 프로덕션 코드 리팩토링 label Mar 12, 2025
@seokbeom00 seokbeom00 self-assigned this Mar 12, 2025
Copy link
Contributor

@sejoon00 sejoon00 left a comment

Choose a reason for hiding this comment

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

고생했어요!
JPA의 영속성 컨텍스트 저장 매커니즘을 한번 살펴보면 좋을 것 같아요

private final ProblemRepository problemRepository;
private final ConceptTagRepository conceptTagRepository;
private final PublishRepository publishRepository;
private final ProblemSetGetRepositoryCustom problemSetGetRepositoryCustom;

@Transactional(readOnly = true)
public ProblemSetGetResponse getProblemSet(Long problemSetId) {
ProblemSet problemSet = problemSetRepository.findByIdElseThrow(problemSetId);
if (problemSet.isDeleted()) {
throw new BusinessException(ErrorCode.DELETE_PROBLEM_SET_GET_ERROR);
Copy link
Contributor

Choose a reason for hiding this comment

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

명시적인 예외 클래스로 만들어주실 수 있을까요?
DeletedException 이라던지


// 문항 및 새끼 문항의 개념 태그 조회
List<Long> allProblemIds = problemSet.getProblemIds(); // 문제 ID 목록
List<Long> childProblemIds = queryFactory
Copy link
Contributor

Choose a reason for hiding this comment

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

위에서 problem과 childproblem을 fetch join해와서 한번더 조회를 하지않아도 될것 같아요

problem.title.title,
problem.memo,
problem.mainProblemImageUrl
)
Copy link
Contributor

Choose a reason for hiding this comment

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

JPA는 select 문에 조회하고 싶은 엔티티를 넣어야지 영속성 컨텍스트에 반영해요
fetch join을 해서 영속성 컨텍스트에 넣어주거나 select 문에 엔티티를 선언해주어야해요

.fetch();

Set<Long> allProblemAndChildProblemIds = new HashSet<>(allProblemIds);
allProblemAndChildProblemIds.addAll(childProblemIds); // 문제 + 자식 문제 ID 합침
Copy link
Contributor

Choose a reason for hiding this comment

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

문항과 새끼문항의 아이디를 set으로 합치는 이유는 어떤걸가요?

.from(problem)
.leftJoin(conceptTag)
.on(conceptTag.id.in(problem.conceptTagIds))
.where(problem.id.in(allProblemAndChildProblemIds)) // 문제 + 자식 문제 ID
Copy link
Contributor

Choose a reason for hiding this comment

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

문항 테이블에서 새끼 문항 id로 검색하는것 같은데요?

.memo(tuple.get(problem.memo))
.mainProblemImageUrl(tuple.get(problem.mainProblemImageUrl))
.tagNames(conceptTagMap.getOrDefault(tuple.get(problem.id), new HashSet<>())) // 태그 매핑
.build()
Copy link
Contributor

Choose a reason for hiding this comment

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

DTO에 대한 정보가 repository까지 내려오는거는 유지보수 관점에서 좋지 않은것 같아요
DTO가 바뀌면 repository까지 수정하러 내려와야할 것 같네요
mapper로직을 넣어주거나 DTO 자체를 repository가 모르게 구성하는건 어떨까요?

@seokbeom00 seokbeom00 closed this Apr 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Refactor [이슈 목적] 프로덕션 코드 리팩토링
Projects
None yet
Development

Successfully merging this pull request may close these issues.

♻️ 문항세트 조회 api 리팩토링
2 participants