Skip to content

refactor(rank): 학교 이름 조회할 때, 캐싱 거치도록 수정#280

Merged
huhdy32 merged 3 commits intodevelopfrom
refactor/rank
Jan 9, 2026
Merged

refactor(rank): 학교 이름 조회할 때, 캐싱 거치도록 수정#280
huhdy32 merged 3 commits intodevelopfrom
refactor/rank

Conversation

@huhdy32
Copy link
Collaborator

@huhdy32 huhdy32 commented Jan 9, 2026

Summary by CodeRabbit

  • Performance Improvements

    • Caching for school-name lookups with a 10-minute TTL to reduce repeated calls and improve ranking response times.
  • New Features

    • School names are now resolved and included directly in school ranking pages.
  • Refactor

    • Internal restructuring to simplify how school data is sourced for ranking responses (no public API changes).

✏️ Tip: You can customize this high-level summary in your review settings.

@huhdy32 huhdy32 self-assigned this Jan 9, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

📝 Walkthrough

Walkthrough

The PR moves the external school client dependency from the API module into the domain module, introduces a cached RankSchoolManager in the domain to resolve school names, adds a SchoolRankPageResult DTO, updates SchoolRankQueryService to return page results with school names, and simplifies the API controller/response to consume the domain-provided page results.

Changes

Cohort / File(s) Summary
Dependency Restructuring
app/api/mathrank-rank-read-api/build.gradle, domain/mathrank-rank-domain/build.gradle
Removed :client:external:mathrank-school from API module and added it to domain module.
API Layer Simplification
app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/RankReadController.java, app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/SchoolRankPageResponse.java
Removed direct SchoolClient usage from controller; updated response factory to accept SchoolRankPageResult instead of separate schoolName parameter.
Domain — New DTO
domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/dto/SchoolRankPageResult.java
Added SchoolRankPageResult record with factory method mapping from SchoolRankQueryResult + schoolName.
Domain — Cache Configuration
domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/RankDomainConfiguration.java
Added SCHOOL_NAME_CACHE constant and a RequiredCacheSpec bean with 10-minute TTL for school name caching.
Domain — Manager & Service Changes
domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/RankSchoolManager.java, domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/SchoolRankQueryService.java
Added RankSchoolManager component that resolves schoolName via SchoolClient with @Cacheable. Updated SchoolRankQueryService.querySchoolRanks to return PageResult<SchoolRankPageResult> and map query results using RankSchoolManager.
Test Config
domain/mathrank-rank-domain/src/test/resources/application.properties
Added school client timeout properties for tests (client.school.connection-timeout-seconds, client.school.read-timeout-seconds).

Sequence Diagram

sequenceDiagram
    participant Client
    participant RankReadController
    participant SchoolRankQueryService
    participant RankSchoolManager
    participant Cache
    participant SchoolClient

    Client->>RankReadController: GET /rankings/schools
    RankReadController->>SchoolRankQueryService: querySchoolRanks(params)
    SchoolRankQueryService->>SchoolRankQueryService: DB query -> PageResult<SchoolRankQueryResult>

    loop per result
        SchoolRankQueryService->>RankSchoolManager: getSchoolNameByCode(schoolCode)
        RankSchoolManager->>Cache: lookup key "schoolCode::<code>"
        alt cache hit
            Cache-->>RankSchoolManager: cached schoolName
        else cache miss
            RankSchoolManager->>SchoolClient: getSchool(request)
            SchoolClient-->>RankSchoolManager: SchoolInfo
            RankSchoolManager->>Cache: store schoolName
        end
        RankSchoolManager-->>SchoolRankQueryService: schoolName
        SchoolRankQueryService->>SchoolRankQueryService: build SchoolRankPageResult
    end

    SchoolRankQueryService-->>RankReadController: PageResult<SchoolRankPageResult>
    RankReadController-->>Client: SchoolRankPageResponse
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 I hopped from API down to domain,
I cached each school in sun or rain,
DTOs snug, lookups swift and tame,
Rankings bloom without the extra chain,
A happy hop — the system's changed its lane! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: refactoring the school name lookup to add caching, which is reflected across all modified files including the new RankSchoolManager component with @Cacheable annotation and cache configuration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be1b008 and c72a19d.

📒 Files selected for processing (1)
  • domain/mathrank-rank-domain/src/test/resources/application.properties
⏰ 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: test
🔇 Additional comments (1)
domain/mathrank-rank-domain/src/test/resources/application.properties (1)

9-10: Configuration addition looks good.

The timeout properties for the school client follow the established pattern and use reasonable values (100 seconds for both connection and read timeouts), consistent with other client configurations in the file.


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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @huhdy32, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 학교 랭크 조회 시 학교 이름 조회 과정의 성능을 최적화하기 위해 캐싱 메커니즘을 도입합니다. 기존에는 API 계층에서 직접 외부 클라이언트를 통해 학교 이름을 조회했으나, 이제 도메인 계층에 캐싱 기능을 갖춘 매니저를 두어 학교 이름 조회 로직을 중앙화하고 반복적인 외부 호출을 줄였습니다. 이를 통해 전반적인 응답 속도 향상과 시스템 부하 감소를 기대할 수 있습니다.

Highlights

  • 학교 이름 캐싱 로직 도입: 학교 이름을 조회할 때 성능 향상을 위해 캐싱 로직을 도입했습니다. RankSchoolManager를 통해 학교 이름 조회 시 캐시를 사용하도록 변경되었습니다.
  • 의존성 이동 및 역할 분리: 기존 RankReadController에서 직접 SchoolClient를 사용하던 로직을 domain 모듈의 RankSchoolManager로 이동시켜 의존성을 분리하고 역할을 명확히 했습니다.
  • 새로운 DTO 도입: 학교 랭크 조회 결과를 담는 새로운 DTO인 SchoolRankPageResult를 도입하여 학교 이름 정보를 포함하도록 변경했습니다. 이는 SchoolRankPageResponse에서도 사용됩니다.
  • 빌드 스크립트 및 컨트롤러 업데이트: 변경된 의존성 구조에 맞춰 build.gradle 파일들을 업데이트하고, RankReadController에서 SchoolClient 관련 코드를 제거했습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

이 PR은 학교 랭킹 조회 시 학교 이름을 캐싱하여 성능을 개선하는 리팩토링을 수행합니다. 학교 이름 조회 책임을 API 계층에서 도메인 계층으로 이동하고 캐시를 적용하여 아키텍처를 개선하고 성능을 향상시킨 점이 좋습니다. 다만, 코드의 안정성과 성능을 더욱 향상시키기 위해 몇 가지 개선점을 제안합니다.

Copy link

@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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/SchoolRankQueryService.java (1)

27-53: Add @Min(1) and @Min(1)/@Max(...) validation constraints to prevent negative pageNumber and pageSize.

The service is marked @Validated, but the method parameters lack constraint annotations. PageRequest.of(pageNumber - 1, pageSize) will throw IllegalArgumentException if pageNumber is 0 or negative; @NotNull alone does not prevent this. Although the controller provides safe defaults, the service method is publicly callable and should enforce its own input bounds.

Proposed fix
 import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.Max;
 
 	public PageResult<SchoolRankPageResult> querySchoolRanks(
-		@NotNull final Integer pageSize,
-		@NotNull final Integer pageNumber
+		@NotNull @Min(1) @Max(100) final Integer pageSize,
+		@NotNull @Min(1) final Integer pageNumber
 	) {

Additionally, note that .map(queryResult -> rankSchoolManager.getSchoolNameByCode(...)) will trigger per-item external lookups on cold caches; the per-schoolCode caching in RankSchoolManager mitigates this within a page (repeated schoolCodes hit cache), but on first load this can still cause multiple API calls. Consider batch-fetching or pre-warming the cache if the external school service becomes a bottleneck.

🧹 Nitpick comments (3)
domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/RankDomainConfiguration.java (1)

17-37: Cache spec addition looks consistent; double-check naming/TTL expectations.
Cache name and RequiredCacheSpec pattern match the existing ones; TTL 10 minutes is reasonable if school names rarely change. Consider whether the constant name should follow the *_CACHE_NAME convention used above for consistency (optional).

domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/dto/SchoolRankPageResult.java (1)

3-18: DTO is fine; clarify nullability expectations.
If score/rank/memberCount and schoolName are always present, consider primitives (long) and/or bean validation / documentation to prevent accidental null propagation.

app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/SchoolRankPageResponse.java (1)

3-16: Cleaner response mapping; decide fallback behavior for missing schoolName.
If schoolName can be null/blank (e.g., lookup failure), consider a consistent API fallback (empty string vs code vs “unknown”).

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 239a084 and be1b008.

📒 Files selected for processing (8)
  • app/api/mathrank-rank-read-api/build.gradle
  • app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/RankReadController.java
  • app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/SchoolRankPageResponse.java
  • domain/mathrank-rank-domain/build.gradle
  • domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/RankDomainConfiguration.java
  • domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/dto/SchoolRankPageResult.java
  • domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/RankSchoolManager.java
  • domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/SchoolRankQueryService.java
💤 Files with no reviewable changes (1)
  • app/api/mathrank-rank-read-api/build.gradle
⏰ 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: test
🔇 Additional comments (3)
app/api/mathrank-rank-read-api/src/main/java/kr/co/mathrank/rank/read/RankReadController.java (1)

51-53: Good API-layer simplification.
Controller now just maps domain results to response DTOs; avoids external client coupling in the API module.

domain/mathrank-rank-domain/build.gradle (1)

13-13: No actionable concerns. This dependency follows the established pattern in the codebase where domain modules depend on client libraries (including external ones) to integrate with external systems. There are no circular dependencies, and mathrank-school is a lightweight HTTP client library—not a web/API layer module. The usage in RankSchoolManager is a legitimate domain service calling an external school API.

Likely an incorrect or invalid review comment.

domain/mathrank-rank-domain/src/main/java/kr/co/mathrank/domain/rank/service/RankSchoolManager.java (1)

20-28: The caching logic is already correct; focus on input validation.

The current code with unless = "#result == null" already prevents caching when getSchool() returns empty. Since SchoolInfo.none().SCHUL_NM() returns null (all fields in the record are null), the fallback result is not cached. Replace @Valid with @NotBlank on the schoolCode parameter for more meaningful validation.

@huhdy32 huhdy32 enabled auto-merge (squash) January 9, 2026 09:24
@huhdy32 huhdy32 disabled auto-merge January 9, 2026 09:24
@huhdy32 huhdy32 enabled auto-merge (squash) January 9, 2026 09:24
@huhdy32 huhdy32 merged commit d84906e into develop Jan 9, 2026
2 checks passed
@huhdy32 huhdy32 deleted the refactor/rank branch January 9, 2026 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant