Skip to content

FEAT : 내 북로그 조회 / 내 북마크 피드 목록 조회 / 다른 유저 북로그 조회 api 추가#112

Merged
icarus0616 merged 1 commit into
devfrom
feat/111-user-booklog
Feb 2, 2026
Merged

FEAT : 내 북로그 조회 / 내 북마크 피드 목록 조회 / 다른 유저 북로그 조회 api 추가#112
icarus0616 merged 1 commit into
devfrom
feat/111-user-booklog

Conversation

@ktg3891
Copy link
Copy Markdown
Collaborator

@ktg3891 ktg3891 commented Feb 1, 2026

  • 내 북로그 조회 API 추가
  • 내 북마크한 북로그 조회 API 추가
  • 다른 유저의 공개 북로그 조회 API 추가

Summary by CodeRabbit

  • New Features
    • Users can now retrieve and browse their personal booklogs through a dedicated API endpoint.
    • Users can access and review their bookmarked booklogs with pagination support.
    • Support for viewing other users' public booklogs with full pagination capabilities.
    • Enhanced feed response formatting with post details and bookmark information.

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 1, 2026

📝 Walkthrough

Walkthrough

This 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

Cohort / File(s) Summary
Repository Layer Updates
booklog/src/main/java/com/example/booklog/domain/booklog/repository/BooklogBookmarkRepository.java
Added @Param annotations to method parameters for better Spring Data query binding. Introduced new method findMyBookmarkedPostIds(Long userId, Pageable pageable) with custom JPQL query for paginated bookmark retrieval.
Service & Facade Layer
booklog/src/main/java/com/example/booklog/domain/booklog/service/BooklogReadFacade.java, booklog/src/main/java/com/example/booklog/domain/booklog/service/BooklogReadFacadeImpl.java, booklog/src/main/java/com/example/booklog/domain/users/service/UserBooklogReadService.java
Added new feed assembly workflow via assembleFeedCards() that enriches posts with author, book, image, tag, and bookmark data. Introduced validateCreateRequest() validation method. Added new UserBooklogReadService with three public methods for reading own and others' booklogs, including bookmark handling with page-size adjustment to detect hasNext state. Updated SimpleTagView to support category metadata.
Controller Layer
booklog/src/main/java/com/example/booklog/domain/users/controller/MeBooklogController.java, booklog/src/main/java/com/example/booklog/domain/users/controller/UserBooklogController.java
Added two new REST controllers. MeBooklogController exposes authenticated user's booklogs and bookmarks at /api/v1/me/booklogs. UserBooklogController exposes another user's public booklogs at /api/v1/users/{userId}/booklogs. Both return BooklogFeedResponse via UserBooklogReadService.
Minor Updates
booklog/src/main/java/com/example/booklog/domain/booklog/service/BooklogPostServiceImpl.java, booklog/src/main/java/com/example/booklog/domain/users/service/MeAvatarService.java
BooklogPostServiceImpl: formatting change (added blank line). MeAvatarService: added @Profile("!local") annotation to exclude service from local profile.

Sequence Diagram

sequenceDiagram
    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>
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • jaehyeon4406
  • icarus0616
  • millkk04

Poem

🐰 Hop along through feed and bookmark,
New endpoints dance in the code's arc,
Controllers guide with Pageable grace,
While facade enriches each bookmark's place,
Booklog blooms in the Spring-bound space! 📚✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% 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 clearly summarizes the main changes: adding three APIs for retrieving booklogs (user's own, user's bookmarks, and other users' public booklogs).

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/111-user-booklog

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.

Copy link
Copy Markdown

@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: 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).

findTagsByTagIds is 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();

Comment on lines +91 to +100
// (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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find the BookmarkRepository class
fd -t f "BookmarkRepository" --type f

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 173


🏁 Script executed:

# Search for the repository file containing findMyBookmarkedPostIds
rg "findMyBookmarkedPostIds" -t java

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 392


🏁 Script executed:

# Also find the BookmarkRepository.java file
fd "BookmarkRepository.java" -t f

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 173


🏁 Script executed:

cat -n booklog/src/main/java/com/example/booklog/domain/booklog/repository/BooklogBookmarkRepository.java

Repository: 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 3

Repository: 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).

@icarus0616 icarus0616 merged commit 3e3a22d into dev Feb 2, 2026
1 check passed
@icarus0616 icarus0616 self-assigned this Feb 2, 2026
@icarus0616 icarus0616 self-requested a review February 2, 2026 06:08
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.

2 participants