Skip to content

[25.07.26 / TASK-212] Feature - Leaderboard에 캐싱 추가 #42

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

Merged
merged 2 commits into from
Jul 29, 2025

Conversation

ooheunda
Copy link
Contributor

@ooheunda ooheunda commented Jul 26, 2025

🔥 변경 사항

  • Leaderboard 서비스 계층에 redis 캐시 레이어를 추가하였습니다.
  • 관련되어 유닛 테스트 케이스를 추가하였습니다.

🏷 관련 이슈

  • X

📸 스크린샷 (UI 변경 시 필수)

X

📌 체크리스트

  • 기능이 정상적으로 동작하는지 테스트 완료
  • 코드 스타일 가이드 준수 여부 확인
  • 관련 문서 업데이트 완료 (필요 시)

Summary by CodeRabbit

  • 신규 기능

    • 유저 및 게시글 리더보드 조회 시 캐시가 적용되어, 동일한 조건의 요청에 대해 더 빠른 응답이 제공됩니다.
  • 테스트

    • 리더보드 서비스의 캐시 동작을 검증하는 테스트가 추가 및 개선되었습니다.
    • 캐시 적중 및 미적중 시나리오가 모두 테스트에 포함되었습니다.

@ooheunda ooheunda self-assigned this Jul 26, 2025
@ooheunda ooheunda added the enhancement New feature or request label Jul 26, 2025
Copy link

캐싱 도입하기

Copy link
Contributor

coderabbitai bot commented Jul 26, 2025

"""

Walkthrough

LeaderboardService에 캐싱 로직이 새롭게 도입되었습니다. getUserLeaderboardgetPostLeaderboard 메서드는 이제 캐시에서 데이터를 우선 조회한 뒤, 없을 경우에만 레포지토리를 조회하고 결과를 캐시에 저장합니다. 테스트 코드도 캐시 동작을 검증하도록 확장되었습니다.

Changes

파일/경로 변경 요약
src/services/leaderboard.service.ts 캐시 TTL 상수 추가, getUserLeaderboard, getPostLeaderboard에 캐싱 로직 도입 및 공개 상수, 메서드 시그니처 변경
src/services/test/leaderboard.service.test.ts 캐시 인터페이스 및 모듈 모킹, 캐시 적중/미스 시나리오 테스트 추가, 기존 테스트 리팩토링 및 명명 개선

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant LeaderboardService
    participant Cache
    participant Repository

    Client->>LeaderboardService: getUserLeaderboard(sort, dateRange, limit)
    LeaderboardService->>Cache: get(cacheKey)
    alt Cache hit
        Cache-->>LeaderboardService: cachedResult
        LeaderboardService-->>Client: cachedResult
    else Cache miss
        Cache-->>LeaderboardService: null
        LeaderboardService->>Repository: getUserLeaderboard(sort, dateRange, limit)
        Repository-->>LeaderboardService: rawResult
        LeaderboardService->>Cache: set(cacheKey, mappedResult, TTL)
        LeaderboardService-->>Client: mappedResult
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Possibly related PRs

Suggested reviewers

  • Nuung
  • six-standard

Poem

캐시 토끼가 뛰노는 밤,
랭킹 데이터 금방 찾아 감!
저장소 대신 캐시를 톡,
빠른 조회에 모두가 혹!
테스트도 꼼꼼히 챙긴 오늘,
토끼는 기뻐 깡총깡총 춤을!
🐇✨
"""

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 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 1d2e544 and 3a96087.

📒 Files selected for processing (1)
  • src/services/__test__/leaderboard.service.test.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: ooheunda
PR: Check-Data-Out/velog-dashboard-v2-api#27
File: src/services/leaderboard.service.ts:29-61
Timestamp: 2025-04-22T12:46:28.114Z
Learning: LeaderboardService의 mapRawResultToLeaderboardResponseData 메서드에서 `RawPostResult[] | RawUserResult[]` 타입을 사용하는 것이 `unknown[]`보다 타입 안전성 측면에서 더 좋은 접근 방식으로 판단됩니다.
src/services/__test__/leaderboard.service.test.ts (1)

Learnt from: ooheunda
PR: #27
File: src/services/leaderboard.service.ts:29-61
Timestamp: 2025-04-22T12:46:28.114Z
Learning: LeaderboardService의 mapRawResultToLeaderboardResponseData 메서드에서 RawPostResult[] | RawUserResult[] 타입을 사용하는 것이 unknown[]보다 타입 안전성 측면에서 더 좋은 접근 방식으로 판단됩니다.

🔇 Additional comments (12)
src/services/__test__/leaderboard.service.test.ts (12)

4-5: 캐시 관련 import가 적절히 추가되었습니다.

새로운 캐싱 기능을 테스트하기 위해 필요한 LEADERBOARD_CACHE_TTL 상수와 ICache 타입이 올바르게 import되었습니다.


8-13: 캐시 모듈 모킹이 올바르게 구현되었습니다.

캐시 모듈을 적절히 모킹하여 getset 메서드를 테스트할 수 있도록 설정했습니다. 모킹 구조가 실제 캐시 인터페이스와 일치합니다.


17-32: 테스트 설정에서 캐시 모킹이 적절히 초기화되었습니다.

  • 변수명이 repo에서 mockRepo로 일관성 있게 변경되었습니다
  • 캐시 모킹 인스턴스가 올바르게 설정되었습니다
  • beforeEach에서 모든 필요한 의존성이 적절히 초기화되었습니다

39-89: 테스트 데이터 포맷팅이 개선되었습니다.

mock 데이터가 더 읽기 쉬운 형태로 재구성되었으며, 예상 결과와 실제 repository 결과 간의 구조가 명확히 구분되어 있습니다. 데이터 변환 로직을 테스트하기에 적합한 구조입니다.


91-98: 기존 테스트에 캐시 미스 시나리오가 적절히 추가되었습니다.

기존 테스트 케이스에 mockCache.get.mockResolvedValue(null)을 추가하여 캐시 미스 상황을 시뮬레이션하고, 기존 로직이 여전히 올바르게 작동함을 확인할 수 있습니다.


100-107: 쿼리 파라미터 테스트에 캐시 미스 설정이 추가되었습니다.

캐시 미스를 모킹하여 repository 메서드가 올바른 파라미터로 호출되는지 확인하는 테스트가 적절히 유지되었습니다.


138-146: 캐시 히트 시나리오 테스트가 잘 구현되었습니다.

  • 캐시에서 데이터를 반환하도록 모킹
  • 올바른 캐시 키로 조회하는지 검증
  • repository 메서드가 호출되지 않는지 확인
  • 캐시된 데이터가 그대로 반환되는지 검증

모든 중요한 측면이 테스트되었습니다.


148-157: 캐시 미스 시나리오 테스트가 포괄적으로 구현되었습니다.

  • repository 메서드 호출 확인
  • 캐시에 결과 저장 확인 (올바른 키, 데이터, TTL)
  • 변환된 결과 반환 확인

캐싱 로직의 전체 플로우가 적절히 테스트되었습니다.


161-211: Post 리더보드 테스트 데이터가 일관성 있게 구성되었습니다.

User 리더보드와 동일한 패턴으로 mock 데이터와 예상 결과가 구조화되어 있어 테스트 가독성과 유지보수성이 향상되었습니다.


260-268: Post 리더보드 캐시 히트 테스트가 올바르게 구현되었습니다.

User 리더보드 테스트와 동일한 패턴으로 캐시 히트 시나리오를 테스트하여 일관성을 유지했습니다. 캐시 키 형식(leaderboard:post:viewCount:30:10)이 적절합니다.


270-279: Post 리더보드 캐시 미스 테스트가 완전히 구현되었습니다.

모든 캐싱 로직이 적절히 테스트되었으며, TTL 상수를 사용하여 캐시 만료 시간이 올바르게 설정되는지 확인합니다.


92-93: 모든 기존 테스트에 일관되게 캐시 미스 설정이 추가되었습니다.

기존 테스트 케이스들이 새로운 캐싱 로직과 호환되도록 적절히 수정되었습니다. 각 테스트에서 mockCache.get.mockResolvedValue(null)로 캐시 미스를 시뮬레이션하여 기존 로직의 동작을 보장합니다.

Also applies to: 101-102, 110-111, 119-120, 131-132, 149-150, 214-215, 223-224, 232-233, 241-242, 253-254, 271-272

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/leaderboard-caching

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 generate unit tests to generate unit tests for 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.

Copy link
Contributor

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

🧹 Nitpick comments (3)
src/services/leaderboard.service.ts (1)

31-31: 캐시 저장 시 에러 처리 추가를 고려해주세요.

현재 캐시 저장 실패 시 에러가 무시되어 전체 로직에 영향을 주지 않지만, 로깅을 통해 모니터링할 수 있도록 개선하는 것이 좋겠습니다.

-      cache.set(cacheKey, result, LEADERBOARD_CACHE_TTL);
+      try {
+        await cache.set(cacheKey, result, LEADERBOARD_CACHE_TTL);
+      } catch (error) {
+        logger.warn('Failed to cache user leaderboard data', { cacheKey, error });
+      }
src/services/__test__/leaderboard.service.test.ts (2)

91-93: 중복된 mock 클리어링을 제거해주세요.

afterEach에서 이미 jest.clearAllMocks()를 호출하고 있으므로, beforeEach에서 중복으로 호출할 필요가 없습니다.

-    beforeEach(() => {
-      jest.clearAllMocks();
-    });

217-219: 동일한 중복 mock 클리어링 제거 필요

getUserLeaderboard 테스트와 마찬가지로 중복된 mock 클리어링을 제거해주세요.

-    beforeEach(() => {
-      jest.clearAllMocks();
-    });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 396adba and 1d2e544.

📒 Files selected for processing (2)
  • src/services/__test__/leaderboard.service.test.ts (3 hunks)
  • src/services/leaderboard.service.ts (4 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: ooheunda
PR: Check-Data-Out/velog-dashboard-v2-api#27
File: src/services/leaderboard.service.ts:29-61
Timestamp: 2025-04-22T12:46:28.114Z
Learning: LeaderboardService의 mapRawResultToLeaderboardResponseData 메서드에서 `RawPostResult[] | RawUserResult[]` 타입을 사용하는 것이 `unknown[]`보다 타입 안전성 측면에서 더 좋은 접근 방식으로 판단됩니다.
src/services/leaderboard.service.ts (1)

Learnt from: ooheunda
PR: #27
File: src/services/leaderboard.service.ts:29-61
Timestamp: 2025-04-22T12:46:28.114Z
Learning: LeaderboardService의 mapRawResultToLeaderboardResponseData 메서드에서 RawPostResult[] | RawUserResult[] 타입을 사용하는 것이 unknown[]보다 타입 안전성 측면에서 더 좋은 접근 방식으로 판단됩니다.

src/services/__test__/leaderboard.service.test.ts (1)

Learnt from: ooheunda
PR: #27
File: src/services/leaderboard.service.ts:29-61
Timestamp: 2025-04-22T12:46:28.114Z
Learning: LeaderboardService의 mapRawResultToLeaderboardResponseData 메서드에서 RawPostResult[] | RawUserResult[] 타입을 사용하는 것이 unknown[]보다 타입 안전성 측면에서 더 좋은 접근 방식으로 판단됩니다.

⏰ 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). (2)
  • GitHub Check: build-and-test (20)
  • GitHub Check: build-and-test (23)
🔇 Additional comments (7)
src/services/leaderboard.service.ts (2)

1-1: 캐시 설정 임포트가 올바르게 추가되었습니다.

캐시 기능 구현을 위한 필수 의존성이 적절히 추가되었습니다.


11-11: 캐시 TTL 상수 정의가 적절합니다.

30분(1800초)의 캐시 만료 시간은 리더보드 데이터의 특성을 고려할 때 합리적인 설정입니다.

src/services/__test__/leaderboard.service.test.ts (5)

4-5: 테스트 파일에 필요한 임포트가 올바르게 추가되었습니다.

캐시 TTL 상수와 ICache 타입 임포트가 적절히 추가되어 테스트에서 캐시 기능을 검증할 수 있습니다.


8-13: 캐시 모듈 모킹이 올바르게 구현되었습니다.

jest.mock을 사용하여 캐시 모듈의 get, set 메서드를 적절히 모킹했습니다.


17-32: 테스트 설정이 개선되었습니다.

변수명이 repo에서 mockRepo로 변경되어 가독성이 향상되었고, 캐시 모킹 설정도 적절히 추가되었습니다.


142-161: 캐시 시나리오 테스트가 잘 구현되었습니다.

캐시 히트와 미스 시나리오 모두 적절히 테스트되고 있으며, 캐시 키, TTL, 그리고 Repository 호출 여부를 정확히 검증하고 있습니다.


268-287: 게시물 리더보드 캐시 테스트가 완전합니다.

사용자 리더보드와 동일한 패턴으로 캐시 히트/미스 시나리오가 모두 테스트되어 일관성 있는 테스트 커버리지를 제공합니다.

Copy link
Member

@six-standard six-standard left a comment

Choose a reason for hiding this comment

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

코드 잘 읽었습니다. 수고 많으셨습니다!

좋았던 점

  • 네이밍을 확실히 해주신 점 (repo -> mockRepo, mockCache) 덕분에 읽기 편했습니다!

let mockPool: jest.Mocked<Pool>;
let mockCache: jest.Mocked<ICache>;
Copy link
Member

Choose a reason for hiding this comment

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

아주 조씀다~ 추상화 계층 mocking~~

Copy link
Member

Choose a reason for hiding this comment

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

이걸 노리고 딱 만들었는데 찰떡같이~ 리시브~

Copy link
Member

@Nuung Nuung left a comment

Choose a reason for hiding this comment

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

좋았던 점

  • 추상화 계층 mocking 과 이를 기반으로 캐시 여부에 따른 함수 호출 여부까지, 빠짐 없는 유닛테스트 너무 잘봤습니다!!

아쉬운 점

  • 혹시 캐시 get / set 과정에 시리얼라이징 이슈는 없으셨어요? 원하는 객체 형태로 바로 잘 나오던가요?

@ooheunda
Copy link
Contributor Author

@Nuung
넵 처음 캐시 설정할 떄에도 따로 이슈는 없었고, 방금 타입도 잘 나오는지 체크해봤는데 이상없네요! DB로부터 서빙하는 값이랑 동일하게 나옵니다.

Copy link
Contributor

@Jihyun3478 Jihyun3478 left a comment

Choose a reason for hiding this comment

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

코드 잘 읽었습니다. 고생하셨습니다~!!

좋았던 점

  • 캐시 로직 구조가 명확해서 좋았습니다! 특히 TTL도 상수로 따로 분리된 점이 좋은 것 같아요!👍
  • 캐시 hit/miss에 대한 테스트코드를 꼼꼼히 작성해주신 부분도 좋았습니다!
  • mock 객체의 역할이 명확하게 드러나도록 mockRepo, mockCache로 네이밍 해주신 부분 좋은 것 같습니다!

@ooheunda ooheunda merged commit dbd4335 into main Jul 29, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants