FEAT : 내 북로그 조회 / 내 북마크 피드 목록 조회 / 다른 유저 북로그 조회 api 추가#112
Conversation
📝 WalkthroughWalkthroughThis PR introduces new REST endpoints for reading user booklogs and bookmarked posts. It adds two controllers (MeBooklogController and UserBooklogController), a new UserBooklogReadService with feed assembly logic, updates the repository layer with pagination support, and extends the facade with feed card assembly capabilities. Changes
Sequence DiagramsequenceDiagram
actor User
participant Controller as MeBooklogController/<br/>UserBooklogController
participant Service as UserBooklogReadService
participant Repo as BooklogPostRepository/<br/>BookmarkRepository
participant Facade as BooklogReadFacadeImpl
participant ImgRepo as PostImageRepository
User->>Controller: GET /api/v1/me/booklogs<br/>(userId, pageable)
Controller->>Service: getMyBooklogs(userId, pageable)
Service->>Repo: findByUserIdAndStatus(userId, PUBLISHED)
Repo-->>Service: Slice<BooklogPost>
Service->>Facade: assembleFeedCards(userId, slice)
Facade->>Repo: fetch authors, books, tags
Facade->>ImgRepo: fetch post images
Facade->>Repo: check bookmark status
Facade-->>Service: BooklogFeedResponse (enriched cards)
Service-->>Controller: BooklogFeedResponse
Controller-->>User: ApiResponse<BooklogFeedResponse>
User->>Controller: GET /api/v1/me/booklogs/bookmarks<br/>(userId, pageable)
Controller->>Service: getMyBookmarkedBooklogs(userId, pageable)
Service->>Repo: findMyBookmarkedPostIds(userId, adjusted pageable)
Repo-->>Service: List<Long> (bookmark order)
Service->>Repo: findByIdAndStatus(postIds, PUBLISHED)
Repo-->>Service: List<BooklogPost>
Service->>Service: reorder to bookmark sequence
Service->>Facade: assembleFeedCards(userId, reordered slice)
Facade-->>Service: BooklogFeedResponse
Service-->>Controller: BooklogFeedResponse
Controller-->>User: ApiResponse<BooklogFeedResponse>
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@booklog/src/main/java/com/example/booklog/domain/users/service/UserBooklogReadService.java`:
- Around line 91-100: The current logic mutates the Pageable to size+1 which
shifts the offset (pageNumber*(size+1)) and breaks pagination; instead compute
the correct offset = pageable.getPageNumber() * size and request size+1 items
from the repository without changing the Pageable. Update the call to
bookmarkRepository.findMyBookmarkedPostIds to accept (meId, offset, limit) or
add a new method (e.g., findMyBookmarkedPostIdsWithOffset(meId, offset,
sizePlusOne)), use sizePlusOne = size + 1 to fetch one extra item, then set
hasNext = results.size() > size and slicedIds = hasNext ? results.subList(0,
size) : results; keep UserBooklogReadService logic but stop constructing
PageRequest.of(pageable.getPageNumber(), size + 1).
🧹 Nitpick comments (1)
booklog/src/main/java/com/example/booklog/domain/booklog/service/BooklogReadFacadeImpl.java (1)
246-266: Avoid per-post tag lookups (N+1).
findTagsByTagIdsis called inside the post loop, which can issue one DB call per post. Batch tag resolution once and map by ID to reduce queries.♻️ Suggested batching approach
// 태그 배치 (postId -> tagIds) List<BooklogPostTag> mappings = postTagRepository.findAllByPostIdIn(postIds); Map<Long, List<Long>> postIdToTagIds = mappings.stream() .collect(Collectors.groupingBy( BooklogPostTag::getPostId, Collectors.mapping(BooklogPostTag::getTagId, Collectors.toList()) )); + List<Long> allTagIds = mappings.stream() + .map(BooklogPostTag::getTagId) + .distinct() + .toList(); + Map<Long, TagView> tagViewMap = findTagsByTagIds(allTagIds).stream() + .collect(Collectors.toMap(TagView::getTagId, t -> t)); @@ - List<? extends TagView> tags = findTagsByTagIds( - postIdToTagIds.getOrDefault(postId, List.of()) - ); + List<? extends TagView> tags = postIdToTagIds.getOrDefault(postId, List.of()).stream() + .map(tagViewMap::get) + .filter(Objects::nonNull) + .toList();
| // (1) bookmark 테이블에서 postIds 최신순 | ||
| // hasNext 판단 위해 size+1로 뽑는 게 좋아서 Pageable을 강제 조정 | ||
| int size = pageable.getPageSize(); | ||
| Pageable plusOne = PageRequest.of(pageable.getPageNumber(), size + 1); | ||
|
|
||
| List<Long> postIds = bookmarkRepository.findMyBookmarkedPostIds(meId, plusOne); | ||
|
|
||
| boolean hasNext = postIds.size() > size; | ||
| List<Long> slicedIds = hasNext ? postIds.subList(0, size) : postIds; | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find the BookmarkRepository class
fd -t f "BookmarkRepository" --type fRepository: Project-BookLog/BookLog-BackEnd
Length of output: 173
🏁 Script executed:
# Search for the repository file containing findMyBookmarkedPostIds
rg "findMyBookmarkedPostIds" -t javaRepository: Project-BookLog/BookLog-BackEnd
Length of output: 392
🏁 Script executed:
# Also find the BookmarkRepository.java file
fd "BookmarkRepository.java" -t fRepository: Project-BookLog/BookLog-BackEnd
Length of output: 173
🏁 Script executed:
cat -n booklog/src/main/java/com/example/booklog/domain/booklog/repository/BooklogBookmarkRepository.javaRepository: Project-BookLog/BookLog-BackEnd
Length of output: 1945
🏁 Script executed:
cat -n booklog/src/main/java/com/example/booklog/domain/users/service/UserBooklogReadService.java | sed -n '80,110p'Repository: Project-BookLog/BookLog-BackEnd
Length of output: 1426
🏁 Script executed:
# Let me verify the Spring Data JPA offset calculation behavior
# and check if there are other usages of this pattern in the codebase
rg "PageRequest.of.*\+\s*1" -t java --context 3Repository: Project-BookLog/BookLog-BackEnd
Length of output: 1864
Fix pagination offset when using size + 1 here.
PageRequest.of(pageable.getPageNumber(), size + 1) changes the offset to pageNumber * (size + 1) instead of pageNumber * size, which skips items for page ≥ 1. This causes pagination to miss bookmarks. Use the original page size for the query and determine hasNext separately, or refactor to return a Slice instead.
🤖 Prompt for AI Agents
In
`@booklog/src/main/java/com/example/booklog/domain/users/service/UserBooklogReadService.java`
around lines 91 - 100, The current logic mutates the Pageable to size+1 which
shifts the offset (pageNumber*(size+1)) and breaks pagination; instead compute
the correct offset = pageable.getPageNumber() * size and request size+1 items
from the repository without changing the Pageable. Update the call to
bookmarkRepository.findMyBookmarkedPostIds to accept (meId, offset, limit) or
add a new method (e.g., findMyBookmarkedPostIdsWithOffset(meId, offset,
sizePlusOne)), use sizePlusOne = size + 1 to fetch one extra item, then set
hasNext = results.size() > size and slicedIds = hasNext ? results.subList(0,
size) : results; keep UserBooklogReadService logic but stop constructing
PageRequest.of(pageable.getPageNumber(), size + 1).
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.