From 3c79aced25146410e38741b22d60aaff88a94f1f Mon Sep 17 00:00:00 2001 From: huhdy32 Date: Fri, 9 Jan 2026 16:56:15 +0900 Subject: [PATCH 1/2] =?UTF-8?q?refactor(rank):=20=ED=95=99=EA=B5=90=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C,?= =?UTF-8?q?=20=EC=BA=90=EC=8B=B1=20=EA=B1=B0=EC=B9=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/mathrank-rank-read-api/build.gradle | 1 - .../rank/read/RankReadController.java | 11 +------ .../rank/read/SchoolRankPageResponse.java | 6 ++-- domain/mathrank-rank-domain/build.gradle | 1 + .../domain/rank/RankDomainConfiguration.java | 21 ++++++++++++++ .../domain/rank/dto/SchoolRankPageResult.java | 19 ++++++++++++ .../rank/service/RankSchoolManager.java | 29 +++++++++++++++++++ .../rank/service/SchoolRankQueryService.java | 23 +++++++++------ 8 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/dto/SchoolRankPageResult.java create mode 100644 domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/RankSchoolManager.java diff --git a/app/api/mathrank-rank-read-api/build.gradle b/app/api/mathrank-rank-read-api/build.gradle index 15f47bbd..ef4c54eb 100644 --- a/app/api/mathrank-rank-read-api/build.gradle +++ b/app/api/mathrank-rank-read-api/build.gradle @@ -5,7 +5,6 @@ dependencies { implementation project(':domain:mathrank-rank-domain') implementation project(':client:internal:mathrank-member-client') - implementation project(':client:external:mathrank-school') implementation project(':app:api:mathrank-api-common') diff --git a/app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/RankReadController.java b/app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/RankReadController.java index 0e9bd908..1d896bbf 100644 --- a/app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/RankReadController.java +++ b/app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/RankReadController.java @@ -8,9 +8,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import kr.co.mathrank.app.api.common.authentication.Authorization; -import kr.co.mathrank.client.external.school.RequestType; -import kr.co.mathrank.client.external.school.SchoolClient; -import kr.co.mathrank.client.external.school.SchoolInfo; import kr.co.mathrank.client.internal.member.MemberClient; import kr.co.mathrank.common.page.PageResult; import kr.co.mathrank.domain.rank.service.RankPageQueryService; @@ -26,7 +23,6 @@ public class RankReadController { private final RankPageQueryService rankPageQueryService; private final MemberClient memberClient; private final SchoolRankQueryService schoolRankQueryService; - private final SchoolClient schoolClient; @Operation(summary = "내 랭크 조회 API", description = "사용자의 랭크를 조회합니다. 사용자 문제 풀이 기록에 맞춰 실시간으로 반영됩니다.") @GetMapping("/api/v1/rank") @@ -53,11 +49,6 @@ public ResponseEntity> querySchoolRankPage( @RequestParam(defaultValue = "1") final Integer pageNumber ) { return ResponseEntity.ok(schoolRankQueryService.querySchoolRanks(pageSize, pageNumber) - .map(schoolRankQueryResult -> SchoolRankPageResponse.from( - schoolRankQueryResult, - schoolClient.getSchool(RequestType.JSON.getType(), schoolRankQueryResult.schoolCode()) - .orElseGet(SchoolInfo::none) - .SCHUL_NM() - ))); + .map(SchoolRankPageResponse::from)); } } diff --git a/app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/SchoolRankPageResponse.java b/app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/SchoolRankPageResponse.java index 84fad200..267f64f4 100644 --- a/app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/SchoolRankPageResponse.java +++ b/app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/SchoolRankPageResponse.java @@ -1,6 +1,6 @@ package kr.co.mathrank.rank.read; -import kr.co.mathrank.domain.rank.dto.SchoolRankQueryResult; +import kr.co.mathrank.domain.rank.dto.SchoolRankPageResult; public record SchoolRankPageResponse( String schoolCode, @@ -9,10 +9,10 @@ public record SchoolRankPageResponse( Long rank, Long memberCount ) { - public static SchoolRankPageResponse from(final SchoolRankQueryResult result, final String schoolName) { + public static SchoolRankPageResponse from(final SchoolRankPageResult result) { return new SchoolRankPageResponse( result.schoolCode(), - schoolName, + result.schoolName(), result.score(), result.rank(), result.memberCount() diff --git a/domain/mathrank-rank-domain/build.gradle b/domain/mathrank-rank-domain/build.gradle index b79e349f..9b62d720 100644 --- a/domain/mathrank-rank-domain/build.gradle +++ b/domain/mathrank-rank-domain/build.gradle @@ -10,6 +10,7 @@ dependencies { implementation project(':common:mathrank-cache') implementation project(':client:internal:mathrank-problem-client') implementation project(':client:internal:mathrank-member-client') + implementation project(':client:external:mathrank-school') testImplementation 'org.testcontainers:junit-jupiter' testImplementation 'org.springframework.boot:spring-boot-testcontainers' diff --git a/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/RankDomainConfiguration.java b/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/RankDomainConfiguration.java index 292f7c63..98286c7f 100644 --- a/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/RankDomainConfiguration.java +++ b/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/RankDomainConfiguration.java @@ -14,6 +14,27 @@ public class RankDomainConfiguration { public static final String USER_RANK_CACHE_NAME = "mathrank::domain::rank::user"; public static final String RANK_BOARD_CACHE_NAME = "mathrank::domain::rank::board"; public static final String SCHOOL_RANK_BOARD_CACHE_NAME = "mathrank::domain::rank::school::board"; + public static final String SCHOOL_NAME_CACHE = "mathrank::domain::rank::school"; + + @Bean + RequiredCacheSpec rankDomainSchoolNameCacheSpec() { + return new RequiredCacheSpec() { + @Override + public String moduleName() { + return "mathrank-domain-rank"; + } + + @Override + public String cacheName() { + return SCHOOL_NAME_CACHE; + } + + @Override + public Duration ttl() { + return Duration.ofMinutes(10L); // 잘 업데이트 되지 않는 데이터 + } + }; + } @Bean RequiredCacheSpec userRankCacheSpec() { diff --git a/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/dto/SchoolRankPageResult.java b/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/dto/SchoolRankPageResult.java new file mode 100644 index 00000000..95df7e9c --- /dev/null +++ b/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/dto/SchoolRankPageResult.java @@ -0,0 +1,19 @@ +package kr.co.mathrank.domain.rank.dto; + +public record SchoolRankPageResult( + String schoolCode, + String schoolName, + Long score, + Long rank, + Long memberCount +) { + public static SchoolRankPageResult from(final SchoolRankQueryResult result, final String schoolName) { + return new SchoolRankPageResult( + result.schoolCode(), + schoolName, + result.score(), + result.rank(), + result.memberCount() + ); + } +} \ No newline at end of file diff --git a/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/RankSchoolManager.java b/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/RankSchoolManager.java new file mode 100644 index 00000000..99f35cfa --- /dev/null +++ b/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/RankSchoolManager.java @@ -0,0 +1,29 @@ +package kr.co.mathrank.domain.rank.service; + +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import kr.co.mathrank.client.external.school.RequestType; +import kr.co.mathrank.client.external.school.SchoolClient; +import kr.co.mathrank.client.external.school.SchoolInfo; +import kr.co.mathrank.domain.rank.RankDomainConfiguration; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class RankSchoolManager { + private final SchoolClient schoolClient; + + @Cacheable( + cacheNames = RankDomainConfiguration.SCHOOL_NAME_CACHE, + key = "'schoolCode::' + #schoolCode", + unless = "#result == null" // 결과가 null이면 캐싱하지 않음 ( 다음에 다시 호출 ) + ) + public String getSchoolNameByCode(@NotNull @Valid final String schoolCode) { + return schoolClient.getSchool(RequestType.JSON.getType(), schoolCode) + .orElseGet(() -> SchoolInfo.none()).SCHUL_NM(); + } +} diff --git a/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/SchoolRankQueryService.java b/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/SchoolRankQueryService.java index 18845167..535c1ee1 100644 --- a/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/SchoolRankQueryService.java +++ b/domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/SchoolRankQueryService.java @@ -9,9 +9,11 @@ import org.springframework.validation.annotation.Validated; import jakarta.validation.constraints.NotNull; +import kr.co.mathrank.client.external.school.SchoolClient; import kr.co.mathrank.common.page.PageResult; import kr.co.mathrank.common.page.PageUtil; import kr.co.mathrank.domain.rank.RankDomainConfiguration; +import kr.co.mathrank.domain.rank.dto.SchoolRankPageResult; import kr.co.mathrank.domain.rank.dto.SchoolRankQueryResult; import kr.co.mathrank.domain.rank.repository.SolverRepository; import lombok.RequiredArgsConstructor; @@ -22,12 +24,13 @@ @CacheConfig(cacheNames = RankDomainConfiguration.SCHOOL_RANK_BOARD_CACHE_NAME) public class SchoolRankQueryService { private final SolverRepository solverRepository; + private final RankSchoolManager rankSchoolManager; @Cacheable( key = "'pageNumber::' + #pageNumber + '::pageSize::' + #pageSize", condition = "#pageNumber <= 4" ) - public PageResult querySchoolRanks( + public PageResult querySchoolRanks( @NotNull final Integer pageSize, @NotNull final Integer pageNumber ) { @@ -36,14 +39,16 @@ public PageResult querySchoolRanks( final Long countSchoolCode = solverRepository.countDistinctSchools(); return PageResult.of( - schoolRankQueryResults, - pageNumber, - pageSize, - PageUtil.getNextPages( - pageSize, + schoolRankQueryResults, pageNumber, - countSchoolCode, - schoolRankQueryResults.size() - )); + pageSize, + PageUtil.getNextPages( + pageSize, + pageNumber, + countSchoolCode, + schoolRankQueryResults.size() + )) + .map(queryResult -> SchoolRankPageResult.from(queryResult, + rankSchoolManager.getSchoolNameByCode(queryResult.schoolCode()))); } } From c72a19d665bf75287a8c2d44f878f58872d20679 Mon Sep 17 00:00:00 2001 From: huhdy32 Date: Fri, 9 Jan 2026 18:17:34 +0900 Subject: [PATCH 2/2] =?UTF-8?q?test(rank):=20=EC=99=B8=EB=B6=80=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/test/resources/application.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/domain/mathrank-rank-domain/src/test/resources/application.properties b/domain/mathrank-rank-domain/src/test/resources/application.properties index fd2f65a6..a3a65559 100644 --- a/domain/mathrank-rank-domain/src/test/resources/application.properties +++ b/domain/mathrank-rank-domain/src/test/resources/application.properties @@ -6,6 +6,9 @@ client.problem.read-timeout-seconds=10 client.member.connection-timeout-seconds=100 client.member.read-timeout-seconds=1000 +client.school.connection-timeout-seconds=100 +client.school.read-timeout-seconds=100 + spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create