From 4192cee3be3172833fc692469c4a3bee191ec2e3 Mon Sep 17 00:00:00 2001 From: HongGit Date: Fri, 4 Apr 2025 22:27:56 +0900 Subject: [PATCH] =?UTF-8?q?[refactor/#130]=20=EB=AC=B8=ED=95=AD=EC=84=B8?= =?UTF-8?q?=ED=8A=B8=20=EC=A1=B0=ED=9A=8C=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/ProblemSummaryResponse.java | 44 +++++++++---------- .../dto/response/HomeFeedResponse.java | 4 +- .../ProblemSetGetRepositoryCustom.java | 37 ++++++++++++++++ .../service/ProblemSetGetService.java | 42 +++++++----------- .../service/ProblemSetGetServiceTest.java | 12 ++--- 5 files changed, 81 insertions(+), 58 deletions(-) create mode 100644 src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetGetRepositoryCustom.java diff --git a/src/main/java/com/moplus/moplus_server/admin/problemset/dto/response/ProblemSummaryResponse.java b/src/main/java/com/moplus/moplus_server/admin/problemset/dto/response/ProblemSummaryResponse.java index a3c0df13..c2ded36a 100644 --- a/src/main/java/com/moplus/moplus_server/admin/problemset/dto/response/ProblemSummaryResponse.java +++ b/src/main/java/com/moplus/moplus_server/admin/problemset/dto/response/ProblemSummaryResponse.java @@ -3,29 +3,27 @@ import com.moplus.moplus_server.domain.problem.domain.problem.Problem; import jakarta.validation.constraints.NotNull; import java.util.Set; -import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; -@Builder -public record ProblemSummaryResponse( - @NotNull(message = "문항 ID는 필수입니다") - Long problemId, - @NotNull(message = "문항 custom ID는 필수입니다") - String problemCustomId, - String problemTitle, - String memo, - String mainProblemImageUrl, - @NotNull(message = "컬렉션 값은 필수입니다.") - Set tagNames -) { - public static ProblemSummaryResponse of(Problem problem, Set tagNames) { - - return ProblemSummaryResponse.builder() - .problemId(problem.getId()) - .problemCustomId(problem.getProblemCustomId()) - .memo(problem.getMemo()) - .problemTitle(problem.getTitle()) - .mainProblemImageUrl(problem.getMainProblemImageUrl()) - .tagNames(tagNames) - .build(); +@Getter +@NoArgsConstructor +public class ProblemSummaryResponse{ + @NotNull(message = "문항 ID는 필수입니다") + private Long problemId; + @NotNull(message = "문항 custom ID는 필수입니다") + private String problemCustomId; + private String problemTitle; + private String memo; + private String mainProblemImageUrl; + @NotNull(message = "컬렉션 값은 필수입니다.") + private Set tagNames; + public ProblemSummaryResponse (Problem problem, Set tagNames) { + this.problemId = problem.getId(); + this.problemCustomId = problem.getProblemCustomId(); + this.problemTitle = problem.getTitle(); + this.memo = problem.getMemo(); + this.mainProblemImageUrl = getMainProblemImageUrl(); + this.tagNames = tagNames; } } diff --git a/src/main/java/com/moplus/moplus_server/client/homefeed/dto/response/HomeFeedResponse.java b/src/main/java/com/moplus/moplus_server/client/homefeed/dto/response/HomeFeedResponse.java index f2d0842d..26bd228d 100644 --- a/src/main/java/com/moplus/moplus_server/client/homefeed/dto/response/HomeFeedResponse.java +++ b/src/main/java/com/moplus/moplus_server/client/homefeed/dto/response/HomeFeedResponse.java @@ -76,8 +76,8 @@ public record ProblemHomeFeedResponse( ) { public static ProblemHomeFeedResponse of(ProblemSummaryResponse problemSummaryResponse) { return new ProblemHomeFeedResponse( - problemSummaryResponse.problemId(), - problemSummaryResponse.mainProblemImageUrl() + problemSummaryResponse.getProblemId(), + problemSummaryResponse.getMainProblemImageUrl() ); } } diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetGetRepositoryCustom.java b/src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetGetRepositoryCustom.java new file mode 100644 index 00000000..f7d580aa --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetGetRepositoryCustom.java @@ -0,0 +1,37 @@ +package com.moplus.moplus_server.domain.problemset.repository; + +import static com.moplus.moplus_server.domain.concept.domain.QConceptTag.conceptTag; +import static com.moplus.moplus_server.domain.problem.domain.childProblem.QChildProblem.childProblem; +import static com.moplus.moplus_server.domain.problem.domain.problem.QProblem.problem; + +import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSummaryResponse; +import com.querydsl.core.group.GroupBy; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class ProblemSetGetRepositoryCustom { + private final JPAQueryFactory queryFactory; + + public List findProblemSummariesWithTags(List problemIds) { + return queryFactory + .from(problem) + .leftJoin(childProblem).on(childProblem.in(problem.childProblems)) + .leftJoin(conceptTag).on( + conceptTag.id.in(problem.conceptTagIds) + .or(conceptTag.id.in(childProblem.conceptTagIds)) + ) + .where(problem.id.in(problemIds)) + .distinct() + .transform(GroupBy.groupBy(problem.id).list( + Projections.constructor(ProblemSummaryResponse.class, + problem, + GroupBy.set(conceptTag.name) + ) + )); + } +} diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java index af4bda1f..21e22001 100644 --- a/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java @@ -3,21 +3,14 @@ import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSetGetResponse; import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSummaryResponse; import com.moplus.moplus_server.admin.publish.domain.Publish; -import com.moplus.moplus_server.domain.concept.domain.ConceptTag; -import com.moplus.moplus_server.domain.concept.repository.ConceptTagRepository; -import com.moplus.moplus_server.domain.problem.domain.problem.Problem; -import com.moplus.moplus_server.domain.problem.repository.ProblemRepository; import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; +import com.moplus.moplus_server.domain.problemset.repository.ProblemSetGetRepositoryCustom; import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository; import com.moplus.moplus_server.domain.publish.repository.PublishRepository; import java.time.LocalDate; -import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import java.util.Map; import lombok.RequiredArgsConstructor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,10 +19,8 @@ public class ProblemSetGetService { private final ProblemSetRepository problemSetRepository; - private final ProblemRepository problemRepository; - private final ConceptTagRepository conceptTagRepository; private final PublishRepository publishRepository; - Logger log = LoggerFactory.getLogger(ProblemSetRepository.class); + private final ProblemSetGetRepositoryCustom problemSetGetRepositoryCustom; @Transactional(readOnly = true) public ProblemSetGetResponse getProblemSet(Long problemSetId) { @@ -38,26 +29,23 @@ public ProblemSetGetResponse getProblemSet(Long problemSetId) { List publishedDates = publishRepository.findByProblemSetId(problemSetId).stream() .map(Publish::getPublishedDate) .toList(); + List problemIds = problemSet.getProblemIds(); + List fetched = problemSetGetRepositoryCustom.findProblemSummariesWithTags(problemIds); - List problemSummaries = new ArrayList<>(); - for (Long problemId : problemSet.getProblemIds()) { - Problem problem = problemRepository.findByIdElseThrow(problemId); - Set tagNames = new HashSet<>( - conceptTagRepository.findAllByIdsElseThrow(problem.getConceptTagIds()) - .stream() - .map(ConceptTag::getName) - .toList()); - problem.getChildProblems().stream() - .map(childProblem -> conceptTagRepository.findAllByIdsElseThrow(childProblem.getConceptTagIds())) - .forEach(conceptTags -> tagNames.addAll(conceptTags.stream().map(ConceptTag::getName).toList())); - problemSummaries.add(ProblemSummaryResponse.of(problem, tagNames)); - } - return ProblemSetGetResponse.of(problemSet, publishedDates, problemSummaries); + // 순서 재정렬 + Map mapped = fetched.stream() + .collect(java.util.stream.Collectors.toMap(ProblemSummaryResponse::getProblemId, p -> p)); + + List orderedSummaries = problemIds.stream() + .map(mapped::get) + .filter(java.util.Objects::nonNull) + .toList(); + + return ProblemSetGetResponse.of(problemSet, publishedDates, orderedSummaries); } @Transactional(readOnly = true) public List getProblemSets(List problemSetIds) { - problemSetIds.forEach((id) -> log.atInfo().log("set id: " + id + "을 조회합니다.")); return problemSetIds.stream() .map(this::getProblemSet) .toList(); diff --git a/src/test/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetServiceTest.java b/src/test/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetServiceTest.java index ec49a767..41c58ae9 100644 --- a/src/test/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetServiceTest.java +++ b/src/test/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetServiceTest.java @@ -57,8 +57,8 @@ void setUp() { assertThat(response).isNotNull(); assertThat(response.title()).isEqualTo("테스트 문항세트"); assertThat(response.problemSummaries()).hasSize(1); - assertThat(response.problemSummaries().get(0).problemCustomId()).isEqualTo("1224052001"); - assertThat(response.problemSummaries().get(0).tagNames()).contains("미분 개념", "적분 개념"); + assertThat(response.problemSummaries().get(0).getProblemCustomId()).isEqualTo("1224052001"); + assertThat(response.problemSummaries().get(0).getTagNames()).contains("미분 개념", "적분 개념"); } @Test @@ -87,11 +87,11 @@ void setUp() { assertThat(response.problemSummaries()).hasSize(2); // 첫 번째 문제 검증 - assertThat(response.problemSummaries().get(0).problemCustomId()).isEqualTo("1224052001"); - assertThat(response.problemSummaries().get(0).tagNames()).contains("미분 개념", "적분 개념"); + assertThat(response.problemSummaries().get(0).getProblemCustomId()).isEqualTo("1224052001"); + assertThat(response.problemSummaries().get(0).getTagNames()).contains("미분 개념", "적분 개념"); // 두 번째 문제 검증 - assertThat(response.problemSummaries().get(1).problemCustomId()).isEqualTo("1224052002"); - assertThat(response.problemSummaries().get(1).tagNames()).contains("미분 개념", "삼각함수 개념"); + assertThat(response.problemSummaries().get(1).getProblemCustomId()).isEqualTo("1224052002"); + assertThat(response.problemSummaries().get(1).getTagNames()).contains("미분 개념", "삼각함수 개념"); } } \ No newline at end of file