-
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
Conversation
|
Caution Review failedFailed to post review comments. Configuration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (7)
🚧 Files skipped from review as they are similar to previous changes (6)
🧰 Additional context used🧬 Code graph analysis (1)capturecat-core/src/main/java/com/capturecat/core/service/user/UserTagService.java (1)
WalkthroughAdds a paginated GET endpoint to retrieve the authenticated user’s tags, including controller, service, repository (custom interface + QueryDSL impl), tests, and documentation/error-code docs. Introduces optional lastCursor + Pageable cursor pagination. No existing public API signatures are removed. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant C as Client
participant Ctrl as UserTagController
participant Svc as UserTagService
participant URepo as UserRepository
participant TRepo as UserTagRepository/CustomImpl
note right of TRepo #DDEBF7: QueryDSL/JPA executes query (left join fetch tag,<br/>filter by user, order desc, limit pageSize+1)
C->>Ctrl: GET /v1/user-tags (Auth, lastCursor, pageable)
Ctrl->>Svc: getAll(loginUser, lastCursor, pageable)
Svc->>URepo: findById(loginUser.id)
alt user found
URepo-->>Svc: User
Svc->>TRepo: findAllByUser(User, lastCursor, pageable)
TRepo-->>Svc: Slice<UserTag>
Svc-->Svc: map -> TagResponse, build CursorResponse
Svc-->>Ctrl: CursorResponse<TagResponse>
Ctrl-->>C: 200 OK (ApiResponse success)
else user not found
URepo-->>Svc: empty
Svc-->>Ctrl: throw USER_NOT_FOUND
Ctrl-->>C: Error response (USER_NOT_FOUND)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
✨ Finishing Touches
🧪 Generate unit tests
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (9)
capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagCustomRepository.java (1)
6-9: Specify deterministic sort and fetch strategy for cursor-friendly pagingTo keep cursor pagination stable and avoid N+1s, make the contract explicit about ordering and fetching.
Apply this diff to add JavaDoc guidance:
public interface UserTagCustomRepository { - Slice<UserTag> findAllByUser(User user, Pageable pageable); + /** + * Returns a slice of the user's tags with a deterministic order suitable for cursor paging. + * Implementations should: + * - Order by tag.id (DESC) or another stable key documented here. + * - Fetch-join the Tag association to prevent N+1 queries. + */ + Slice<UserTag> findAllByUser(User user, Pageable pageable); }capturecat-core/src/docs/asciidoc/user.adoc (1)
52-63: Document pagination inputs and include query-parameters snippetThe endpoint returns a CursorResponse but docs don’t show any request params. If Pageable (size, sort) or a cursor is supported, surface that for clients and include the query-parameters snippet.
Apply this diff to augment the docs:
[[유저-태그-조회]] === 유저 태그 조회 사용자의 태그를 조회합니다. ==== 성공 -operation::getUserTags[snippets='curl-request,http-request,request-headers,http-response,response-fields'] +operation::getUserTags[snippets='curl-request,http-request,request-headers,query-parameters,http-response,response-fields'] ==== 실패 유저 태그 조회가 실패했다면 HTTP 상태 코드와 함께 <<에러-객체-형식, 에러 객체>>가 돌아옵니다. <<error-codes#유저-태그-조회, 유저 태그 조회 API에서 발생할 수 있는 에러>>를 살펴보세요.Follow-up: Update the controller test to emit the query-parameters snippet (see my comment on UserTagControllerTest).
capturecat-core/src/test/java/com/capturecat/core/service/user/UserTagServiceTest.java (1)
122-138: Strengthen assertions to cover pagination metadataAlso assert hasNext and lastCursor, and verify repository interaction for completeness.
Apply this diff:
// when var response = userTagService.getAll(new LoginUser(user), PageRequest.of(0, 10)); // then assertThat(response.items()).hasSize(1); assertThat(response.items().get(0).name()).isEqualTo(tag.getName()); + assertThat(response.hasNext()).isFalse(); + assertThat(response.lastCursor()).isEqualTo(tag.getId()); + verify(userTagRepository, times(1)).findAllByUser(eq(user), any());capturecat-core/src/main/java/com/capturecat/core/service/user/UserTagService.java (1)
55-66: Align cursor key with sort and cap page size
- CursorResponse uses TagResponse::id (tag.id) as the cursor key. Ensure the repository sorts by tag.id consistently, or change the cursor key to match the actual sort key (e.g., userTag.id). Otherwise, pagination can skip/duplicate items when pages advance.
- Consider capping page size and applying a default deterministic sort when none is provided.
Apply this minimal service-side guard; add imports for PageRequest and Sort:
@Transactional(readOnly = true) public CursorResponse<TagResponse> getAll(LoginUser loginUser, Pageable pageable) { User user = userRepository.findByUsername(loginUser.getUsername()) .orElseThrow(() -> new CoreException(ErrorType.USER_NOT_FOUND)); - Slice<UserTag> userTags = userTagRepository.findAllByUser(user, pageable); + int maxSize = 50; + boolean hasSort = pageable.getSort() != null && pageable.getSort().isSorted(); + Pageable sanitized = PageRequest.of( + pageable.getPageNumber(), + Math.min(pageable.getPageSize(), maxSize), + hasSort ? pageable.getSort() : Sort.by(Sort.Direction.DESC, "tag.id") + ); + Slice<UserTag> userTags = userTagRepository.findAllByUser(user, sanitized); List<TagResponse> tags = userTags.stream() .map(ut -> TagResponse.from(ut.getTag())) .toList(); return CursorUtil.toCursorResponse(tags, userTags.hasNext(), TagResponse::id); }Add imports:
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort;Verification (please run in the PR branch):
- Confirm repository ordering matches the cursor key:
#!/bin/bash # Inspect custom repo impl for ordering and pagination application rg -nP 'class\s+UserTagCustomRepositoryImpl\b|orderBy\(|applyPagination\(|fetchJoin|join\(.*tag' -C3 --type=javacapturecat-core/src/test/java/com/capturecat/core/api/user/UserTagControllerTest.java (1)
69-91: Emit query-parameters snippet and mark lastCursor optional in docsExpose pageable input (e.g., size) in docs and make lastCursor optional for empty pages.
Apply this diff:
@Test void 유저_태그_조회() { // given BDDMockito.given(userTagService.getAll(any(), any())).willReturn( new CursorResponse(false, 1L, List.of(new TagResponse(1L, "java")))); // when & then given() .header(HttpHeaders.AUTHORIZATION, JwtUtil.BEARER_PREFIX + ACCESS_TOKEN) .contentType(ContentType.JSON) + .queryParam("size", 10) .when().get("/v1/user-tags") .then().status(HttpStatus.OK) .apply(document("getUserTags", requestPreprocessor(), responsePreprocessor(), - requestHeaders(headerWithName(HttpHeaders.AUTHORIZATION).description("유효한 Access 토큰")), + requestHeaders(headerWithName(HttpHeaders.AUTHORIZATION).description("유효한 Access 토큰")), + queryParameters( + parameterWithName("size").optional().description("페이지 크기 (기본값/최대값은 서버 설정에 따름)") + ), responseFields( fieldWithPath("result").type(JsonFieldType.STRING).description("요청 결과"), fieldWithPath("data").type(JsonFieldType.OBJECT).description("커서 페이지 응답"), fieldWithPath("data.hasNext").type(JsonFieldType.BOOLEAN).description("다음 페이지 존재 여부"), - fieldWithPath("data.lastCursor").type(JsonFieldType.NUMBER).description("마지막 커서 ID"), + fieldWithPath("data.lastCursor").type(JsonFieldType.NUMBER).optional().description("마지막 커서 ID"), fieldWithPath("data.items").type(JsonFieldType.ARRAY).description("태그 목록"), fieldWithPath("data.items[].id").type(JsonFieldType.NUMBER).description("태그 ID"), fieldWithPath("data.items[].name").type(JsonFieldType.STRING).description("태그 이름")))); }capturecat-core/src/main/java/com/capturecat/core/api/user/UserTagController.java (1)
35-37: Cap page size and document defaults.If you keep Pageable temporarily, set an explicit default and ensure a global max to avoid unbounded queries.
Minimal tweak if staying with Pageable:
- public ApiResponse<CursorResponse<TagResponse>> getAll(@AuthenticationPrincipal LoginUser loginUser, - @PageableDefault Pageable pageable) { + public ApiResponse<CursorResponse<TagResponse>> getAll(@AuthenticationPrincipal LoginUser loginUser, + @PageableDefault(size = 20) Pageable pageable) {Run to verify a max is enforced somewhere (properties or a customizer):
#!/bin/bash rg -nP -C3 'spring\.data\.web\.pageable\.max-page-size|PageableHandlerMethodArgumentResolverCustomizer'capturecat-core/src/test/java/com/capturecat/core/domain/user/UserTagRepositoryTest.java (1)
58-64: Strengthen assertions: verify hasNext and deterministic order.Add checks for hasNext=false and descending order to align with cursor/keyset expectations.
Apply this diff:
// then assertThat(result).isNotNull(); assertThat(result.getContent()).hasSize(2); + assertThat(result.hasNext()).isFalse(); + var ids = result.getContent().stream().map(UserTag::getId).toList(); + assertThat(ids).isSortedAccordingTo(java.util.Comparator.reverseOrder()); assertThat(result.getContent()) .extracting("tag.name") - .containsExactlyInAnyOrder("tag1", "tag2"); + .containsExactlyInAnyOrder("tag1", "tag2");capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagCustomRepositoryImpl.java (2)
24-26: Join type: consider inner join if Tag is mandatory.If UserTag.tag is non-nullable, replace leftJoin with join for a tighter plan.
- .leftJoin(userTag.tag).fetchJoin() + .join(userTag.tag).fetchJoin()
23-33: Add supporting DB index for scan efficiency.Add an index on (user_id, id desc) to match the filter and sort used by keyset.
Example DDL:
- create index idx_user_tag_user_id_id_desc on user_tag(user_id, id desc);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
capturecat-core/src/docs/asciidoc/error-codes.adoc(1 hunks)capturecat-core/src/docs/asciidoc/user.adoc(1 hunks)capturecat-core/src/main/java/com/capturecat/core/api/user/UserTagController.java(3 hunks)capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagCustomRepository.java(1 hunks)capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagCustomRepositoryImpl.java(1 hunks)capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagRepository.java(1 hunks)capturecat-core/src/main/java/com/capturecat/core/service/user/UserTagService.java(3 hunks)capturecat-core/src/test/java/com/capturecat/core/api/user/UserErrorCodeControllerTest.java(1 hunks)capturecat-core/src/test/java/com/capturecat/core/api/user/UserTagControllerTest.java(3 hunks)capturecat-core/src/test/java/com/capturecat/core/domain/user/UserTagRepositoryTest.java(1 hunks)capturecat-core/src/test/java/com/capturecat/core/service/user/UserTagServiceTest.java(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
capturecat-core/src/test/java/com/capturecat/core/api/user/UserErrorCodeControllerTest.java (1)
capturecat-core/src/test/java/com/capturecat/core/api/tag/TagErrorCodeControllerTest.java (1)
TagErrorCodeControllerTest(13-20)
🔇 Additional comments (4)
capturecat-core/src/docs/asciidoc/error-codes.adoc (1)
97-99: Docs section wired correctly to generated snippetsAnchor and include path align with tests (errorCode/getUserTags). Looks good.
capturecat-core/src/test/java/com/capturecat/core/service/user/UserTagServiceTest.java (1)
140-151: LGTM on failure path coverageUSER_NOT_FOUND path is exercised correctly.
capturecat-core/src/test/java/com/capturecat/core/api/user/UserErrorCodeControllerTest.java (1)
23-27: Docs generation for getUserTags error codes is correctIncludes USER_NOT_FOUND and targets the right snippet path.
capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagRepository.java (1)
7-12: Extending the custom repository is appropriateInterface composition looks correct; no issues.
| @GetMapping | ||
| public ApiResponse<CursorResponse<TagResponse>> getAll(@AuthenticationPrincipal LoginUser loginUser, | ||
| @PageableDefault Pageable pageable) { | ||
| CursorResponse<TagResponse> tagResponse = userTagService.getAll(loginUser, pageable); | ||
|
|
||
| return ApiResponse.success(tagResponse); | ||
| } |
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):
- @GetMapping
- public ApiResponse<CursorResponse<TagResponse>> getAll(@AuthenticationPrincipal LoginUser loginUser,
- @PageableDefault Pageable pageable) {
- CursorResponse<TagResponse> tagResponse = userTagService.getAll(loginUser, pageable);
- return ApiResponse.success(tagResponse);
- }
+ @GetMapping
+ public ApiResponse<CursorResponse<TagResponse>> getAll(
+ @AuthenticationPrincipal LoginUser loginUser,
+ @RequestParam(name = "lastCursor", required = false) Long lastCursor,
+ @RequestParam(name = "size", defaultValue = "20") int size
+ ) {
+ CursorResponse<TagResponse> tagResponse = userTagService.getAll(loginUser, lastCursor, size);
+ return ApiResponse.success(tagResponse);
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @GetMapping | |
| public ApiResponse<CursorResponse<TagResponse>> getAll(@AuthenticationPrincipal LoginUser loginUser, | |
| @PageableDefault Pageable pageable) { | |
| CursorResponse<TagResponse> tagResponse = userTagService.getAll(loginUser, pageable); | |
| return ApiResponse.success(tagResponse); | |
| } | |
| @GetMapping | |
| public ApiResponse<CursorResponse<TagResponse>> getAll( | |
| @AuthenticationPrincipal LoginUser loginUser, | |
| @RequestParam(name = "lastCursor", required = false) Long lastCursor, | |
| @RequestParam(name = "size", defaultValue = "20") int size | |
| ) { | |
| CursorResponse<TagResponse> tagResponse = userTagService.getAll(loginUser, lastCursor, size); | |
| return ApiResponse.success(tagResponse); | |
| } |
🤖 Prompt for AI Agents
In
capturecat-core/src/main/java/com/capturecat/core/api/user/UserTagController.java
around lines 34 to 40, the controller currently returns a CursorResponse but
accepts a Pageable (offset-based) which must be replaced with true keyset/cursor
pagination: change the method signature to accept cursor parameters (e.g., Long
lastCursor, int size) instead of Pageable, validate and default size,
convert/forward those params to the userTagService.getAll call, and update the
service interface to accept (lastCursor, size) so the repository can implement
id-based keyset queries (WHERE id < :lastCursor ORDER BY id DESC LIMIT :size or
similar) returning a CursorResponse<TagResponse>; ensure the controller maps
missing lastCursor to "start from newest" semantics and wraps the returned
CursorResponse in ApiResponse.success before returning.
| @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); | ||
| } |
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
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:
- Change UserTagCustomRepository signature to (User user, Long lastCursor, int size).
- Adapt UserTagService and controller accordingly.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @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) | |
| ); | |
| } |
🤖 Prompt for AI Agents
In
capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagCustomRepositoryImpl.java
around lines 21 to 33, the current implementation uses offset/limit for
pagination which breaks cursor semantics; change the repository signature to
findAllByUser(User user, Long lastCursor, int size) (and update the
interface/service/controller to match), remove offset usage, add a keyset WHERE
clause userTag.id < lastCursor when lastCursor is non-null, set limit to size +
1, keep orderBy(userTag.id.desc()), fetch the results and return a Slice
constructed from the size+1 sentinel to determine hasNext. Ensure NPE-safe
handling of a null lastCursor (treat as head) and propagate the new parameters
through service and controller method signatures.
# Conflicts: # capturecat-core/src/docs/asciidoc/error-codes.adoc # capturecat-core/src/docs/asciidoc/user.adoc # capturecat-core/src/main/java/com/capturecat/core/api/user/UserTagController.java # capturecat-core/src/main/java/com/capturecat/core/service/user/UserTagService.java # capturecat-core/src/test/java/com/capturecat/core/api/user/UserErrorCodeControllerTest.java # capturecat-core/src/test/java/com/capturecat/core/api/user/UserTagControllerTest.java # capturecat-core/src/test/java/com/capturecat/core/domain/user/UserTagRepositoryTest.java # capturecat-core/src/test/java/com/capturecat/core/service/user/UserTagServiceTest.java
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.
Actionable comments posted: 0
🧹 Nitpick comments (3)
capturecat-core/src/test/java/com/capturecat/core/service/user/UserTagServiceTest.java (2)
128-145: Happy-path retrieval test looks good; consider tightening expectations.Good coverage of the mapping. Optionally, also assert pagination signals and repository interaction:
- Verify repository call happens once with a Pageable.
- Add an additional test for an empty Slice to ensure items() is empty and cursor fields behave as expected (if applicable).
Example additions within this test:
@@ // then assertThat(response.items()).hasSize(1); assertThat(response.items().get(0).name()).isEqualTo(tag.getName()); + verify(userTagRepository, times(1)).findAllByUser(eq(user), any());
147-158: Prefer asserting onerrorTypeover message and verify no downstream calls.Asserting on the exception message is brittle. CoreException exposes its ErrorType via a Lombok-generated
getErrorType(), so assert on that instead of the message. Also verify thatuserTagRepository.findAllByUseris never invoked when the user is not found.@@ - assertThatThrownBy(() -> userTagService.getAll(new LoginUser(user), PageRequest.of(0, 10))) - .isInstanceOf(CoreException.class) - .hasMessage(ErrorType.USER_NOT_FOUND.getCode().getMessage()); + assertThatThrownBy(() -> userTagService.getAll(new LoginUser(user), PageRequest.of(0, 10))) + .isInstanceOf(CoreException.class) + .extracting(e -> ((CoreException) e).getErrorType()) + .isEqualTo(ErrorType.USER_NOT_FOUND); + + verify(userTagRepository, never()).findAllByUser(any(), any());capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagRepository.java (1)
9-9: LGTM: repository fragment extension is correct.File: capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagRepository.java
Lines: 9-9public interface UserTagRepository extends JpaRepository<UserTag, Long>, UserTagCustomRepository {Extending
UserTagCustomRepositoryis the right hook for a QueryDSL-based slice query.
- Verified that
UserTagCustomRepositoryandUserTagCustomRepositoryImplexist and thatSlice<UserTag> findAllByUser(User, Pageable)is correctly declared and implemented.- Optional: fetch-join the
tagassociation (or project to a DTO) in the QueryDSL query to prevent N+1 issues.- Optional: apply a stable, indexed sort (e.g.,
createdAt DESCorid DESC) for deterministic slicing/cursor behavior and align service/controller defaults accordingly.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
capturecat-core/src/docs/asciidoc/error-codes.adoc(1 hunks)capturecat-core/src/docs/asciidoc/user.adoc(1 hunks)capturecat-core/src/main/java/com/capturecat/core/api/user/UserTagController.java(3 hunks)capturecat-core/src/main/java/com/capturecat/core/domain/user/UserTagRepository.java(1 hunks)capturecat-core/src/main/java/com/capturecat/core/service/user/UserTagService.java(3 hunks)capturecat-core/src/test/java/com/capturecat/core/api/user/UserErrorCodeControllerTest.java(1 hunks)capturecat-core/src/test/java/com/capturecat/core/api/user/UserTagControllerTest.java(3 hunks)capturecat-core/src/test/java/com/capturecat/core/service/user/UserTagServiceTest.java(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- capturecat-core/src/docs/asciidoc/error-codes.adoc
🚧 Files skipped from review as they are similar to previous changes (5)
- capturecat-core/src/docs/asciidoc/user.adoc
- capturecat-core/src/main/java/com/capturecat/core/api/user/UserTagController.java
- capturecat-core/src/test/java/com/capturecat/core/api/user/UserTagControllerTest.java
- capturecat-core/src/test/java/com/capturecat/core/api/user/UserErrorCodeControllerTest.java
- capturecat-core/src/main/java/com/capturecat/core/service/user/UserTagService.java
🧰 Additional context used
🧬 Code graph analysis (1)
capturecat-core/src/test/java/com/capturecat/core/service/user/UserTagServiceTest.java (2)
capturecat-core/src/test/java/com/capturecat/core/DummyObject.java (1)
DummyObject(18-100)capturecat-core/src/test/java/com/capturecat/core/domain/tag/TagFixture.java (1)
TagFixture(5-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build
- GitHub Check: deploy-dev
🔇 Additional comments (1)
capturecat-core/src/test/java/com/capturecat/core/service/user/UserTagServiceTest.java (1)
15-15: LGTM: required imports only.The added imports are minimal and directly support the new retrieval tests.
Also applies to: 23-24, 31-31
7d46bff to
bfdee69
Compare
📌 관련 이슈 (필수)
📝 작업 내용 (필수)
태그 설정 부분에서 사용할 유저 태그 조회 API를 구현했습니다.
💬 리뷰 참고 사항 (선택)
Summary by CodeRabbit
New Features
Documentation
Tests