Skip to content

[FEAT] 사용자 서재 조회 API V2 추가#538

Open
ljy1348 wants to merge 3 commits into
devfrom
feat/#537
Open

[FEAT] 사용자 서재 조회 API V2 추가#538
ljy1348 wants to merge 3 commits into
devfrom
feat/#537

Conversation

@ljy1348

@ljy1348 ljy1348 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Related Issue

Key Changes

유저 서재 조회 API V2 추가
/users/{userId}/novels/v2에서 정렬, 필터, 커서 기반 페이지네이션을 지원하도록 api 추가 했습니다.

유저 서재 정렬 기능 추가
유저 서재 v2 조회용 UserNovelSortType을 추가했습니다.
지원 정렬 조건은 다음과 같습니다.
created_desc: 등록 최신순
created_asc: 등록 오래된순
read_date: 읽은 날짜순
rating_desc: 별점 높은순
rating_asc: 별점 낮은순

읽은 날짜순 정렬
읽은 날짜순 정렬 시 startDate DESC NULLS LAST, userNovelId DESC 기준으로 조회되도록 추가했습니다.
커서에도 lastStartDate를 포함해 읽은 날짜순 페이지네이션이 정상 동작하도록 했습니다.

유저 서재 필터 기능 확장
기존 관심 여부, 읽음 상태, 매력 포인트 필터 외에 장르, 완결 여부, 별점 범위, 미평가 작품만 보기, 키워드 필터를 추가했습니다.
QueryDSL 기반으로 필터 조건과 count 조회를 처리하도록 UserNovelCustomRepository를 확장했습니다.

커서 페이지네이션 도입
정렬 기준 추가에 따라 기존 novelId 커서 방식에서, Base64 URL-safe 방식의 커서를 도입했습니다.
커서 인코딩/디코딩을 위한 CursorCodec을 추가했습니다.
요청 size보다 1개 더 조회해 isLoadablenextCursor를 판단하도록 구현했습니다.
정렬 조건별 커서 조건을 분리해 최신순, 오래된순, 별점순, 읽은 날짜순 페이지네이션을 처리했습니다.

유저 서재 키워드 조회 API 추가
/users/{userId}/novels/keywords API를 추가했습니다.
사용자가 서재에 등록한 키워드를 사용 횟수 기준으로 집계해 조회하도록 했습니다.

Repository 책임 정리
유저 서재 키워드 집계 및 삭제 쿼리를 UserNovelKeywordCustomRepository로 분리했습니다.
기존 repository 메서드에서 처리하던 jpql 기반 로직을 custom repository에서 query dsl로 변경했습니다.

To Reviewers

References

ljy1348 added 2 commits June 18, 2026 21:53
 - 유저 서재 v2 목록 조회 API에 정렬, 필터, 커서 페이지네이션 추가
 - 유저가 서재에 등록한 키워드 목록 조회 API 추가
 - 유저 서재 키워드 집계/삭제 쿼리를 QueryDSL 커스텀 리포지토리로 이동
@ljy1348 ljy1348 linked an issue Jun 19, 2026 that may be closed by this pull request
2 tasks
@GiJungPark GiJungPark changed the title Feat/#537 [FEAT] 사용자 서재 조회 API V2 추가 Jun 19, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 800dd640dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +55 to +59
new CaseBuilder()
.when(userNovel.userNovelRating.eq(0.0f))
.then(0)
.otherwise(1)
.asc(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Put unrated items after rated ones for ascending ratings

When sortType=rating_asc and the library contains interest-only/unrated entries (userNovelRating == 0.0f), this case expression sorts those unrated rows before actual low ratings such as 0.5 or 1.0. The descending sort already treats 0.0f as unrated by pushing it after rated rows, and there is a separate unratedOnly filter, so the ascending rating view can otherwise be filled with unrated works instead of the user's lowest-rated works.

Useful? React with 👍 / 👎.

@GiJungPark GiJungPark left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

확인 부탁드릴게요~

Comment on lines +114 to +116
if (isProfileInaccessible(visitor, ownerId, owner)) {
throw new CustomUserException(PRIVATE_PROFILE_STATUS, "the profile status of the user is set to private");
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

p2;
ownerId를 가지고 User를 가져올 때 접근 가능한 사용자인지 파악할 수 있는 UserService 메서드를 추가하면 좋을 것 같아요!
그리고 차단하거나 당한 사용자는 서로의 피드가 안보여서 해당 API 호출이 불가능하지만, Block여부를 전반적으로 체크하면 좋을 것 같아요!

.join(userNovel.novel, novel).fetchJoin()
.where(userNovel.user.userId.eq(userId));

applyFiltersV2(queryBuilder, isInterest, readStatuses, genres, isCompleted, ratingMin, ratingMax,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

p4;
반환 값이 없다보니, 헷갈리거나 오해의 소지가 있을 수도 있을것 같아요!
주석이 있으면 좋을 것 같습니다


@Component
@RequiredArgsConstructor
public class CursorCodec {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

p3;
repository에 해당 컴포넌트가 위치하는게 어색하게 느껴집니다!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

UserNovelCursor가 실질적으로 쓰이는 위치가 레파지토리라고 생각하여 해당 위치에 넣었습니다!
이동해야 한다면 domain 쪽으로 이동시킬까 합니다

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.

[FEAT] 서재 필터 UX 개선

2 participants