Skip to content

[FEAT] 서재 캐싱 오류 해결 & 내 정보 조회 응답 변경#278

Merged
JiwonLee42 merged 9 commits into
develop-demofrom
fix/#270-library-view-fix
May 22, 2026
Merged

[FEAT] 서재 캐싱 오류 해결 & 내 정보 조회 응답 변경#278
JiwonLee42 merged 9 commits into
develop-demofrom
fix/#270-library-view-fix

Conversation

@JiwonLee42

@JiwonLee42 JiwonLee42 commented May 20, 2026

Copy link
Copy Markdown
Contributor

📄 작업 내용 요약

  • 서재 캐싱 오류 해결: static class를 redis에 캐시로 넣기 -> Jackson 매핑 오류 발생, 커서 응답을 record 방식으로 변경
  • 서재 상태별 조회에서 캐시 제거: 자주 비용이 많이 드는 쿼리가 발생하는 페이지가 아니기 때문에, 홈 화면을 제외하고 서재 관련 API에서는 캐싱을 제거
  • 커서 응답 변경: 공통으로 사용하는 커서 응답 class를 record로 변경
  • 내 정보 조회 응답 변경: 토큰을 모두 반환 -> 필요한 최소한의 정보만 반환해서 클라이언트에서 자주 사용 가능하도록 함
  • 관련 adoc, test 코드 수정

📎 Issue 번호


✅ 작업 목록

  • 기능 구현
  • 코드 리뷰 반영
  • 테스트 코드 작성
  • 문서 업데이트

📝 기타 참고사항

Summary by CodeRabbit

  • 문서 업데이트

    • 사용자 정보 조회 및 온보딩(온보딩 완료/상태, 독서 목표 조회/수정) 섹션 추가 및 요청/응답 예시 보강
  • 개선사항

    • 사용자 정보 조회 응답 간소화(온보딩 플래그 제외)
    • 캐시 TTL 최적화로 일부 목록 응답의 신선도/성능 개선
    • 페이징 처리 변경: 일부 엔드포인트에서 cursor=0을 첫 조회로 처리하고(또는 최소값 검증 강화) 커서 유효성 규칙이 조정됨

Review Change Stack

@JiwonLee42 JiwonLee42 self-assigned this May 20, 2026
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@JiwonLee42 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 46 minutes and 24 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: aba046fa-cb96-4f6a-8487-9e38acddc2e8

📥 Commits

Reviewing files that changed from the base of the PR and between 5215272 and 1b1e6b3.

📒 Files selected for processing (3)
  • src/test/java/app/nook/controller/library/LibraryControllerTest.java
  • src/test/java/app/nook/library/service/LibraryServiceTest.java
  • src/test/java/app/nook/user/jwt/JwtProviderTest.java

Walkthrough

CursorResponse를 Java record로 전환하고, 라이브러리 캐시 무효화 이벤트 계약을 Set 기반으로 단순화하며, 인증 응답을 UserInfo로 축소하고 관련 컨트롤러/서비스/Redis 무효화 로직과 테스트를 일괄 갱신합니다.

Changes

Library Service & User Authentication Refactoring

Layer / File(s) Summary
문서 및 예제 스니펫 추가
src/docs/asciidoc/user.adoc
내 정보 조회 및 온보딩 관련 AsciiDoc 섹션과 HTTP 요청/응답 스니펫 인클루드를 추가했습니다.
CacheConfig TTL 매핑 조정
src/main/java/app/nook/global/config/CacheConfig.java
libraryStatusFirstPage 항목을 제거하고 ALADIN_SEARCH_CACHE(10분), WEEKLY_BESTSELLERS_CACHE/PERSONALIZED_BESTSELLERS_CACHE(각 30분)를 추가했습니다.
CursorResponse Record 전환
src/main/java/app/nook/global/dto/CursorResponse.java
Lombok 기반 클래스를 Java record로 전환하고 of(...) 팩토리는 유지했습니다.
LibraryViewDto 제네릭 고정
src/main/java/app/nook/library/dto/LibraryViewDto.java
StatusBookResponseDto.bookItems 제네릭에서 와일드카드를 제거하고 UserStatusBookItem로 고정했습니다.
LibraryQueryService 캐시/접근자 변경
src/main/java/app/nook/library/service/LibraryQueryService.java
@Cacheable 주석 및 import 제거, toResolvedCursorResponse에서 get*/is* 접근자를 items()/nextCursor()/hasNext()로 전환했습니다.
AuthController @Validated 및 /auth/me
src/main/java/app/nook/user/controller/AuthController.java
클래스 레벨 @Validated 추가 및 /auth/me 핸들러 포맷 조정(반환은 UserDTO.UserInfo).
UserDTO.UserInfo 및 UserService 반환형 변경
src/main/java/app/nook/user/dto/UserDTO.java, src/main/java/app/nook/user/service/UserService.java
UserInfo record(id,email,nickName) 추가, UserService#getThisUser 반환형을 LoginResponse → UserInfo로 변경하여 onboardingCompleted 제거.
OAuthService 로깅 문구 정정
src/main/java/app/nook/user/oauth/OAuthService.java
Google/Kakao 토큰 요청 실패시 log.error 메시지 인자 표기만 조정했습니다.
LibraryController 커서 정규화 및 검증 강화
src/main/java/app/nook/library/controller/LibraryController.java
/library/status에서 cursor=0을 null로 정규화하여 전달, /library/focus-records의 cursor @Min(0) → @Min(1)으로 변경.
LibraryCacheInvalidateEvent 계약 변경
src/main/java/app/nook/library/event/LibraryCacheInvalidateEvent.java, src/main/java/app/nook/library/event/LibraryCacheInvalidationListener.java
affectedYearMonths를 List → Set으로 변경하고 evictStatusFirstPage 및 상세 팩토리 제거, monthly(userId, Set) 팩토리로 대체. 리스너는 월별 무효화만 수행.
LibraryCommandService 이벤트 발행 정리
src/main/java/app/nook/library/service/LibraryCommandService.java
registerBook/changeReadingStatus의 statusOnly 발행 제거, deleteByBookId에서 연월 수집을 Set으로 변경하고 monthly(...) 발행으로 조정.
RedisCacheService 월별 무효화 시그니처 조정
src/main/java/app/nook/redis/service/RedisCacheService.java
evictLibraryMonthlyCaches 파라미터를 List → Collection으로 변경하고 null/empty 가드 제거, evictLibraryStatusFirstPage 및 CacheManager 의존성 제거.
테스트 일괄 업데이트: CursorResponse 접근자
src/test/java/app/nook/...
여러 서비스 테스트에서 CursorResponse 접근자를 get*/is* → items()/nextCursor()/hasNext()로 변경했습니다.
테스트: LibraryController 커서/유효성 검증
src/test/java/app/nook/controller/library/LibraryControllerTest.java
cursor=-1 실패 케이스를 제거하고 cursor=0을 첫 조회로 처리하는 성공 테스트로 대체, /library/focus-records에서 cursor=0 입력 시 400 테스트 추가 및 서비스 미호출 검증.
테스트: 캐시 무효화 통합/유닛 테스트 조정
src/test/java/app/nook/library/service/*
LibraryServiceTest와 LibraryCachingIntegrationTest에서 이벤트 검증 범위를 사용자 기준으로 축소하고 affectedYearMonths를 Set으로 검증하도록 변경.
OAuthServiceTest redirect_uri 인코딩 검증 추가
src/test/java/app/nook/user/oauth/OAuthServiceTest.java
토큰 요청 검증에 URL 인코딩된 redirect_uri 포함 여부 assert를 추가했습니다.
기타 포맷·무해 변경
src/main/java/app/nook/user/repository/UserRepository.java, 기타 테스트
UserRepository 포맷 수정 및 테스트 공백 조정 등 소수 변경 포함.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • UMC-NOOK/Server#209: CursorResponse record 전환과 LibraryController의 커서 페이징 검증이 #209의 서재 책 상태별 조회/커서 페이징 구현 흐름과 직접 연결됩니다.
  • UMC-NOOK/Server#277: LibraryCommandService의 registerBook 관련 변경들이 두 PR 사이에서 메서드 수준 충돌 가능성이 있습니다.
  • UMC-NOOK/Server#232: CacheConfig에서 사용되는 캐시 이름들과 TTL 조정이 #232에서 도입된 캐시 정의와 연관됩니다.

Poem

🐰 레코드로 깔끔히 갈아엎고,
달력은 Set으로 묶어두고,
응답은 작게, 검증은 단단히,
테스트는 맞춰서 다시 달았네. 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive CustomUserDetailService 제거, OAuthService 로깅 수정, 여러 테스트 케이스 변경 등 #270과 직접 연관되지 않은 변경사항들이 포함되어 있습니다. CustomUserDetailService 제거 사유, OAuthService 로깅 변경 의도, 변경된 테스트 케이스들이 #270 해결과 어떤 관계가 있는지 명확히 설명하십시오.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목 '[FEAT] 서재 캐싱 오류 해결 & 내 정보 조회 응답 변경'은 주요 변경 사항을 명확하고 간결하게 요약하고 있습니다.
Linked Issues check ✅ Passed PR은 #270 이슈의 목표인 서재 캐싱 오류 해결(커서 응답 record 변경, 캐시 무효화 로직 개선)과 내 정보 조회 응답 변경을 모두 구현했습니다.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/#270-library-view-fix

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.

@JiwonLee42

Copy link
Copy Markdown
Contributor Author
Overall Project 67.03% -0.16% 🍏
Files changed 71.88% 🍏

File Coverage
LibraryController.java 100% 🍏
LibraryCacheInvalidationListener.java 100% 🍏
LibraryCacheInvalidateEvent.java 100% 🍏
AuthController.java 100% 🍏
RedisCacheService.java 100% 🍏
LibraryCommandService.java 93.92% 🍏
UserService.java 93.48% -4.35%
LibraryQueryService.java 90.56% 🍏
OAuthService.java 63.49% -2.12%

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/app/nook/library/controller/LibraryController.java`:
- Line 73: The controller validation change to `@Min`(1) for the cursor breaks
compatibility and is inconsistent with other controllers and the
BookSearchFacade logic; revert the LibraryController `@RequestParam` annotation
back to `@Min`(0) to match FocusController and BookSearchController, and ensure
BookSearchFacade still treats cursor==0 as “new search” (or add an explicit
conversion from null to 0 in the controller before calling the facade) so
behavior and validations remain consistent across LibraryController,
FocusController, BookSearchController and the BookSearchFacade.

In `@src/main/java/app/nook/redis/service/RedisCacheService.java`:
- Around line 15-19: evictLibraryMonthlyCaches currently always uses
YearMonth.now(), which leaves stale ZSETs for past months when items with
historical focus data are deleted; change the method signature and callers to
accept a collection of affected YearMonth values (or compute the affected
YearMonths before deletion and pass them in the event payload) and then call
redisZSETService.evictMonthlyBooks/evictMonthlyFocusTime/evictMonthlyHourlyFocus
for each YearMonth in that collection instead of only YearMonth.now(); update
any event producers to include the list of impacted YearMonth entries or add a
pre-delete computation step to derive them so all relevant monthly ZSETs are
evicted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 196b5fc6-dc79-4254-8c19-05b055c3606e

📥 Commits

Reviewing files that changed from the base of the PR and between c0b6692 and d165e4d.

📒 Files selected for processing (24)
  • src/docs/asciidoc/user.adoc
  • src/main/java/app/nook/global/config/CacheConfig.java
  • src/main/java/app/nook/global/dto/CursorResponse.java
  • src/main/java/app/nook/library/controller/LibraryController.java
  • src/main/java/app/nook/library/dto/LibraryViewDto.java
  • src/main/java/app/nook/library/event/LibraryCacheInvalidateEvent.java
  • src/main/java/app/nook/library/event/LibraryCacheInvalidationListener.java
  • src/main/java/app/nook/library/service/LibraryCommandService.java
  • src/main/java/app/nook/library/service/LibraryQueryService.java
  • src/main/java/app/nook/redis/service/RedisCacheService.java
  • src/main/java/app/nook/user/controller/AuthController.java
  • src/main/java/app/nook/user/dto/UserDTO.java
  • src/main/java/app/nook/user/oauth/OAuthService.java
  • src/main/java/app/nook/user/repository/UserRepository.java
  • src/main/java/app/nook/user/service/CustomUserDetailService.java
  • src/main/java/app/nook/user/service/UserService.java
  • src/test/java/app/nook/controller/library/LibraryControllerTest.java
  • src/test/java/app/nook/controller/user/AuthControllerTest.java
  • src/test/java/app/nook/focus/service/FocusQueryServiceTest.java
  • src/test/java/app/nook/library/service/LibraryCachingIntegrationTest.java
  • src/test/java/app/nook/library/service/LibraryServiceTest.java
  • src/test/java/app/nook/record/service/RecordQueryServiceTest.java
  • src/test/java/app/nook/user/oauth/OAuthServiceTest.java
  • src/test/java/app/nook/user/repository/UserRepositoryTest.java
💤 Files with no reviewable changes (2)
  • src/main/java/app/nook/user/service/CustomUserDetailService.java
  • src/main/java/app/nook/global/config/CacheConfig.java

Comment thread src/main/java/app/nook/library/controller/LibraryController.java Outdated
Comment thread src/main/java/app/nook/redis/service/RedisCacheService.java Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/test/java/app/nook/controller/library/LibraryControllerTest.java (1)

313-336: ⚡ Quick win

cursor=0 성공 케이스와 별개로 음수 커서 실패 테스트도 유지해 주세요.

@Min(0) 검증 분기는 그대로 살아 있는데, 이번 교체로 cursor=-1이 400으로 막히는지 확인하는 테스트가 빠졌습니다. cursor=0 정상화 테스트는 유지하되, 음수 입력 검증 케이스를 하나 추가해 두는 편이 안전합니다.

➕ 테스트 보강 예시
+    `@Test`
+    `@WithCustomUser`
+    void 서재_상태별_책_조회_실패_cursor_음수() throws Exception {
+        mockMvc.perform(
+                        get("/api/v1/library/status")
+                                .param("status", "READING")
+                                .param("cursor", "-1")
+                                .param("size", "20")
+                                .header(AUTH_HEADER, AUTH_TOKEN)
+                )
+                .andExpect(status().isBadRequest());
+
+        verifyNoInteractions(libraryCommandService, libraryQueryService);
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/app/nook/controller/library/LibraryControllerTest.java` around
lines 313 - 336, Keep the existing success test
서재_상태별_책_조회_성공_cursor_0은_첫조회로_처리() as-is, and add a new test that exercises the
validation branch for negative cursors: perform a GET to
"/api/v1/library/status" with param("cursor","-1") (and suitable
status/size/header), expect status().isBadRequest(), and verify
libraryQueryService.getBooksByStatus is not invoked; this ensures the `@Min`(0)
validation is covered and negative cursor inputs return 400.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/test/java/app/nook/controller/library/LibraryControllerTest.java`:
- Around line 313-336: Keep the existing success test
서재_상태별_책_조회_성공_cursor_0은_첫조회로_처리() as-is, and add a new test that exercises the
validation branch for negative cursors: perform a GET to
"/api/v1/library/status" with param("cursor","-1") (and suitable
status/size/header), expect status().isBadRequest(), and verify
libraryQueryService.getBooksByStatus is not invoked; this ensures the `@Min`(0)
validation is covered and negative cursor inputs return 400.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 35251ed5-4136-49e0-84fc-2908b3115432

📥 Commits

Reviewing files that changed from the base of the PR and between d165e4d and 5215272.

📒 Files selected for processing (7)
  • src/main/java/app/nook/library/controller/LibraryController.java
  • src/main/java/app/nook/library/event/LibraryCacheInvalidateEvent.java
  • src/main/java/app/nook/library/event/LibraryCacheInvalidationListener.java
  • src/main/java/app/nook/library/service/LibraryCommandService.java
  • src/main/java/app/nook/redis/service/RedisCacheService.java
  • src/test/java/app/nook/controller/library/LibraryControllerTest.java
  • src/test/java/app/nook/library/service/LibraryCachingIntegrationTest.java

@JiwonLee42

Copy link
Copy Markdown
Contributor Author
Overall Project 67.96% -0.16% 🍏
Files changed 81.82% 🍏

File Coverage
LibraryController.java 100% 🍏
LibraryCacheInvalidationListener.java 100% 🍏
LibraryCacheInvalidateEvent.java 100% 🍏
AuthController.java 100% 🍏
RedisCacheService.java 100% 🍏
LibraryCommandService.java 94.36% 🍏
UserService.java 93.48% -4.35%
LibraryQueryService.java 90.56% 🍏
OAuthService.java 63.49% -2.12%

@JiwonLee42

Copy link
Copy Markdown
Contributor Author
Overall Project 67.96% -0.16% 🍏
Files changed 81.82% 🍏

File Coverage
LibraryController.java 100% 🍏
LibraryCacheInvalidationListener.java 100% 🍏
LibraryCacheInvalidateEvent.java 100% 🍏
AuthController.java 100% 🍏
RedisCacheService.java 100% 🍏
LibraryCommandService.java 94.36% 🍏
UserService.java 93.48% -4.35%
LibraryQueryService.java 90.56% 🍏
OAuthService.java 63.49% -2.12%

@JiwonLee42 JiwonLee42 merged commit c5cb9f4 into develop-demo May 22, 2026
5 checks passed
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.

[FIX] 서재 책 등록 버그 수정

1 participant