-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 유저 태그 조회 API #127
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
feat: 유저 태그 조회 API #127
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.capturecat.core.domain.user; | ||
|
|
||
| import org.springframework.data.domain.Pageable; | ||
| import org.springframework.data.domain.Slice; | ||
|
|
||
| public interface UserTagCustomRepository { | ||
|
|
||
| Slice<UserTag> findAllByUser(User user, Pageable pageable); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,34 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package com.capturecat.core.domain.user; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import static com.capturecat.core.domain.user.QUserTag.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.data.domain.Pageable; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.data.domain.Slice; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.querydsl.jpa.impl.JPAQueryFactory; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.capturecat.core.support.util.SliceUtil; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class UserTagCustomRepositoryImpl implements UserTagCustomRepository { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final JPAQueryFactory queryFactory; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public Slice<UserTag> findAllByUser(User user, Pageable pageable) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<UserTag> userTags = queryFactory | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .selectFrom(userTag) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .leftJoin(userTag.tag).fetchJoin() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .where(userTag.user.eq(user)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .offset(pageable.getOffset()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .limit(pageable.getPageSize() + 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .orderBy(userTag.id.desc()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .fetch(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return SliceUtil.toSlice(userTags, pageable); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+21
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Offset pagination in “cursor” flow — migrate to keyset (id < lastCursor). Current query uses offset/limit; this breaks true cursor semantics and can suffer O(n) skips for large pages. Prefer keyset on id with size+1 fetch. Apply this diff (and update the interface + service accordingly): - @Override
- public Slice<UserTag> findAllByUser(User user, Pageable pageable) {
- List<UserTag> userTags = queryFactory
- .selectFrom(userTag)
- .leftJoin(userTag.tag).fetchJoin()
- .where(userTag.user.eq(user))
- .offset(pageable.getOffset())
- .limit(pageable.getPageSize() + 1)
- .orderBy(userTag.id.desc())
- .fetch();
-
- return SliceUtil.toSlice(userTags, pageable);
- }
+ @Override
+ public Slice<UserTag> findAllByUser(User user, Long lastCursor, int size) {
+ List<UserTag> userTags = queryFactory
+ .selectFrom(userTag)
+ .leftJoin(userTag.tag).fetchJoin()
+ .where(
+ userTag.user.eq(user),
+ lastCursor != null ? userTag.id.lt(lastCursor) : null
+ )
+ .orderBy(userTag.id.desc())
+ .limit(size + 1)
+ .fetch();
+
+ return SliceUtil.toSlice(userTags, org.springframework.data.domain.PageRequest.of(0, size));
+ }Follow-ups:
📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Cursor response but offset-based input — switch to true keyset pagination.
The endpoint returns CursorResponse but accepts Pageable (page/offset). With the current repository impl using offset/limit, large offsets will degrade and can cause inconsistent pages under concurrent writes. Expose cursor params (lastCursor, size) and have the service/repo use id-based keyset (id < lastCursor) instead of offset.
Apply this diff (requires coordinated service + repository interface changes):
📝 Committable suggestion
🤖 Prompt for AI Agents