Skip to content

Conversation

@move-hoon
Copy link
Member

@move-hoon move-hoon commented Aug 7, 2025

🔗 관련 이슈

📘 작업 유형

  • ✨ Feature (기능 추가)
  • 🐞 Bugfix (버그 수정)
  • 🔧 Refactor (코드 리팩토링)
  • ⚙️ Chore (환경 설정)
  • 📝 Docs (문서 작성 및 수정)
  • ✅ Test (기능 테스트)
  • 🎨 style (코드 스타일 수정)

📙 작업 내역

  • 씨앗 카운트를 userBookId 기준으로 집계하도록 리팩토링하였습니다.

🧪 테스트 내역

  • 브라우저/기기에서 동작 확인
  • 엣지 케이스 테스트 완료
  • 기존 기능 영향 없음

🎨 스크린샷 또는 시연 영상 (선택)

기능 미리보기 기능 미리보기
기능 설명 기능 설명

✅ PR 체크리스트

  • 커밋 메시지가 명확합니다
  • PR 제목이 컨벤션에 맞습니다
  • 관련 이슈 번호를 작성했습니다
  • 기능이 정상적으로 작동합니다
  • 불필요한 코드를 제거했습니다

💬 추가 설명 or 리뷰 포인트 (선택)

  • ..

Summary by CodeRabbit

  • 신규 기능

    • 사용자의 특정 책에 대한 감정 태그별 시드 통계 조회 API(/api/v1/reading-records/{userBookId}/seed/stats) 추가
  • 기능 개선

    • 감정 태그 통계 조회 시 사용자 ID뿐만 아니라 사용자 도서 ID(userBookId)로도 필터링하도록 변경
    • 감정 태그 카테고리에서 '긴장감' 제거, '깨달음' 추가
  • 기존 기능 제거

    • 전체 시드 통계 조회(SeedController, SeedUseCase) 관련 API 및 내부 로직 삭제
  • 버그 수정 및 기타

    • 입력값 유효성 검사 강화(@Valid 적용)
    • 일부 패키지 및 클래스명, 메서드명 정비

@coderabbitai
Copy link

coderabbitai bot commented Aug 7, 2025

Walkthrough

씨앗 카운팅(Seed Counting) API가 기존의 userId 단위에서 userBookId 단위로 카운팅하도록 전체적으로 리팩토링되었습니다. 기존 씨앗(Seed) 관련 컨트롤러, API, 유스케이스, 서비스가 삭제되고, 읽기기록(ReadingRecord) 관련 모듈로 기능이 이전 및 확장되었습니다. 관련 도메인, 레포지토리, 인프라 계층의 메서드 시그니처도 userBookId를 추가하여 변경되었습니다. 일부 @Valid 어노테이션 및 import 정리도 포함되어 있습니다.

Changes

Cohort / File(s) Change Summary
씨앗 API/유스케이스/컨트롤러 제거
apis/src/main/kotlin/org/yapp/apis/seed/controller/SeedController.kt, apis/src/main/kotlin/org/yapp/apis/seed/controller/SeedControllerApi.kt, apis/src/main/kotlin/org/yapp/apis/seed/usecase/SeedUseCase.kt
Seed(씨앗) 관련 REST 컨트롤러, API 인터페이스, 유스케이스 클래스 전체 삭제
씨앗 통계 기능의 읽기기록(ReadingRecord)로 이전 및 확장
apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordController.kt, apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt, apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordTagService.kt, apis/src/main/kotlin/org/yapp/apis/readingrecord/usecase/ReadingRecordUseCase.kt, apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/response/SeedStatsResponse.kt
씨앗 통계 API를 userBookId로 필터링하는 새로운 엔드포인트 및 서비스/유스케이스/DTO 추가 및 리팩토링, 클래스 및 메서드 네이밍/위치 변경, 패키지 이동 등
도메인/레포지토리 계층 userBookId 파라미터 추가
domain/src/main/kotlin/org/yapp/domain/readingrecordtag/ReadingRecordTagDomainService.kt, domain/src/main/kotlin/org/yapp/domain/readingrecordtag/ReadingRecordTagRepository.kt, infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/JpaReadingRecordTagQuerydslRepository.kt, infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/impl/JpaReadingRecordTagQuerydslRepositoryImpl.kt, infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/impl/ReadingRecordTagRepositoryImpl.kt
씨앗 통계 관련 메서드에서 userBookId 파라미터 추가, 기존 메서드 삭제 및 대체, 쿼리 및 where절에 userBookId 조건 추가
@Valid 어노테이션 및 import 정리
apis/src/main/kotlin/org/yapp/apis/auth/strategy/withdraw/WithdrawStrategy.kt, apis/src/main/kotlin/org/yapp/apis/book/service/BookQueryService.kt, apis/src/main/kotlin/org/yapp/apis/book/usecase/BookUseCase.kt, apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt, infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/JpaReadingRecordTagRepository.kt
withdraw, getBookDetail 등 일부 메서드 파라미터에 @Valid 추가, import 구문 정리(불필요한 import 제거 및 와일드카드 사용 등)
감정 태그 카테고리 enum 변경
global-utils/src/main/kotlin/org/yapp/globalutils/tag/GeneralEmotionTagCategory.kt
TENSION("긴장감") 삭제, REALIZATION("깨달음") 추가 및 순서 변경

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ReadingRecordController
    participant ReadingRecordUseCase
    participant ReadingRecordTagService
    participant UserService
    participant ReadingRecordTagDomainService
    participant ReadingRecordTagRepository

    Client->>ReadingRecordController: GET /reading-records/{userBookId}/seed/stats
    ReadingRecordController->>ReadingRecordUseCase: getSeedStats(userId, userBookId)
    ReadingRecordUseCase->>UserService: validateUserExists(userId)
    UserService-->>ReadingRecordUseCase: (validation result)
    ReadingRecordUseCase->>ReadingRecordTagService: getSeedStatsByUserIdAndUserBookId(userId, userBookId)
    ReadingRecordTagService->>ReadingRecordTagDomainService: countTagsByUserIdAndUserBookIdAndCategories(userId, userBookId, categories)
    ReadingRecordTagDomainService->>ReadingRecordTagRepository: countTagsByUserIdAndUserBookIdAndCategories(userId, userBookId, categories)
    ReadingRecordTagRepository-->>ReadingRecordTagDomainService: Map<String, Int>
    ReadingRecordTagDomainService-->>ReadingRecordTagService: TagStatsVO
    ReadingRecordTagService-->>ReadingRecordUseCase: SeedStatsResponse
    ReadingRecordUseCase-->>ReadingRecordController: SeedStatsResponse
    ReadingRecordController-->>Client: HTTP 200 + SeedStatsResponse
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~35 minutes

Assessment against linked issues

Objective Addressed Explanation
씨앗 카운팅 API를 userBookId 별로 카운팅 하도록 리팩토링 (#83)

Assessment against linked issues: Out-of-scope changes

해당 변경사항에서 명확히 linked issue(#83)와 무관한 기능적 코드 변경은 발견되지 않았습니다.

Possibly related PRs

Suggested labels

🔨 refactor

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee473fd and 5d007b1.

📒 Files selected for processing (1)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: intellij idea에서 와일드카드 임포트를 방지하는 설정 방법: file > settings > editor > code style > java > imports 탭에서 "c...
Learnt from: hoonyworld
PR: YAPP-Github/Reed-Server#31
File: apis/src/main/kotlin/org/yapp/apis/book/controller/BookControllerApi.kt:13-13
Timestamp: 2025-07-08T14:24:44.340Z
Learning: IntelliJ IDEA에서 와일드카드 임포트를 방지하는 설정 방법: File > Settings > Editor > Code Style > Java > Imports 탭에서 "Class count to use import with '*'" 값을 높게 설정(예: 500)하면 해당 임계값 이하에서는 와일드카드 임포트가 자동으로 사용되지 않음. 와일드카드 임포트 관련 리뷰 시 이 IDE 설정 방법도 함께 안내하면 좋음.

Applied to files:

  • apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt
🔇 Additional comments (2)
apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt (2)

20-20: 리팩토링 목표에 부합하는 새로운 응답 DTO import

SeedStatsResponsereadingrecord 패키지로 이동한 것이 도메인 통합 목표에 잘 부합합니다.


110-132: 씨앗 통계 API가 리팩토링 목표에 잘 부합합니다

userBookId를 path parameter로 받는 새로운 API 엔드포인트가 PR 목표인 "userBookId 기준 씨앗 카운팅"에 완벽히 부합합니다. OpenAPI 문서화도 적절하게 작성되었고, 매개변수 정의도 명확합니다.

API 설계가 기존 패턴과 일관성 있게 /api/v1/reading-records/{userBookId}/seed/stats 형태로 구성된 점도 좋습니다.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch BOOK-237-refactor/#83

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

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

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4990849 and f6eb0b2.

📒 Files selected for processing (19)
  • apis/src/main/kotlin/org/yapp/apis/auth/strategy/withdraw/WithdrawStrategy.kt (1 hunks)
  • apis/src/main/kotlin/org/yapp/apis/book/service/BookQueryService.kt (1 hunks)
  • apis/src/main/kotlin/org/yapp/apis/book/usecase/BookUseCase.kt (1 hunks)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordController.kt (2 hunks)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt (2 hunks)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/response/SeedStatsResponse.kt (1 hunks)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt (0 hunks)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordTagService.kt (1 hunks)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/usecase/ReadingRecordUseCase.kt (3 hunks)
  • apis/src/main/kotlin/org/yapp/apis/seed/controller/SeedController.kt (0 hunks)
  • apis/src/main/kotlin/org/yapp/apis/seed/controller/SeedControllerApi.kt (0 hunks)
  • apis/src/main/kotlin/org/yapp/apis/seed/usecase/SeedUseCase.kt (0 hunks)
  • domain/src/main/kotlin/org/yapp/domain/readingrecordtag/ReadingRecordTagDomainService.kt (1 hunks)
  • domain/src/main/kotlin/org/yapp/domain/readingrecordtag/ReadingRecordTagRepository.kt (1 hunks)
  • global-utils/src/main/kotlin/org/yapp/globalutils/tag/GeneralEmotionTagCategory.kt (1 hunks)
  • infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/JpaReadingRecordTagQuerydslRepository.kt (1 hunks)
  • infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/JpaReadingRecordTagRepository.kt (1 hunks)
  • infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/impl/JpaReadingRecordTagQuerydslRepositoryImpl.kt (3 hunks)
  • infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/impl/ReadingRecordTagRepositoryImpl.kt (1 hunks)
💤 Files with no reviewable changes (4)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt
  • apis/src/main/kotlin/org/yapp/apis/seed/controller/SeedController.kt
  • apis/src/main/kotlin/org/yapp/apis/seed/usecase/SeedUseCase.kt
  • apis/src/main/kotlin/org/yapp/apis/seed/controller/SeedControllerApi.kt
⏰ 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). (1)
  • GitHub Check: build-validation
🔇 Additional comments (22)
apis/src/main/kotlin/org/yapp/apis/auth/strategy/withdraw/WithdrawStrategy.kt (2)

3-3: 입력 검증 강화를 위한 import 추가 승인

jakarta.validation.Valid import 추가가 적절합니다.


11-11: @Valid 어노테이션 추가 승인

withdraw 메서드의 request 파라미터에 @Valid 어노테이션을 추가하여 입력 검증을 강화한 것이 좋습니다. 이는 서비스 계층에서 데이터 무결성을 보장하는 모범 사례입니다.

apis/src/main/kotlin/org/yapp/apis/book/service/BookQueryService.kt (2)

3-3: 입력 검증을 위한 import 추가 승인

jakarta.validation.Valid import가 적절하게 추가되었습니다.


11-11: @Valid 어노테이션 추가 승인

getBookDetail 메서드의 request 파라미터에 @Valid 어노테이션을 추가한 것이 좋습니다. 이는 입력 데이터의 유효성을 보장하는 좋은 관행입니다.

apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/response/SeedStatsResponse.kt (1)

1-1: 패키지 이동이 깔끔하게 처리되었습니다.

씨앗 관련 기능을 reading record 도메인으로 통합하는 리팩토링에 맞춰 DTO의 패키지 위치가 적절하게 변경되었습니다. 내부 구조는 그대로 유지되어 API 일관성이 보장됩니다.

global-utils/src/main/kotlin/org/yapp/globalutils/tag/GeneralEmotionTagCategory.kt (1)

8-9: 감정 카테고리 변경 영향 검토 필요: 코드 내 직접 참조는 없으나 데이터·시스템 검증 요망

스크립트 결과, TENSION("긴장감") 은 코드상 다른 참조가 전혀 없으며(build.gradle.kts 내 설정 외), REALIZATION("깨달음") 도 해당 enum 외에는 호출되지 않습니다.
하지만 기존 DB나 외부 시스템에 남아 있는 “긴장감” 태그 데이터, 그리고 이를 활용하는 API·UI가 예상치 못한 오류를 일으키지 않도록 아래 사항을 반드시 검토해주세요.

  • DB·데이터 마이그레이션
    • 기존 “긴장감” 레코드 처리 방안(삭제, 대체, 알림 등)
    • 데이터 백업 및 롤백 절차
  • API·서비스 영향
    • enum 변경에 따른 직렬화/역직렬화 오류 여부
    • 문서·스키마 업데이트
  • 프론트엔드·UI 확인
    • 드롭다운·필터 등에서 “긴장감” 항목 제거
    • “깨달음” 추가 후 사용자 경험 점검
apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordController.kt (2)

23-23: 필요한 임포트가 정확히 추가되었습니다.

새로운 endpoint를 위한 SeedStatsResponse 임포트가 적절히 추가되었습니다.


74-81: 새로운 씨앗 통계 조회 endpoint가 깔끔하게 구현되었습니다.

userBookId 단위로 씨앗 통계를 조회하는 새로운 endpoint가 적절하게 구현되었습니다. 인증, 경로 변수 처리, 그리고 use case 계층으로의 위임이 기존 패턴과 일관되게 처리되었습니다.

apis/src/main/kotlin/org/yapp/apis/readingrecord/usecase/ReadingRecordUseCase.kt (1)

9-9: 필요한 의존성과 임포트가 적절히 추가되었습니다.

새로운 기능을 위한 SeedStatsResponse 임포트와 ReadingRecordTagService 의존성이 깔끔하게 추가되었습니다.

Also applies to: 11-11, 21-21

infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/impl/JpaReadingRecordTagQuerydslRepositoryImpl.kt (3)

23-26: 메서드 시그니처 업데이트가 올바르게 적용되었습니다.

userBookId 파라미터가 추가되어 더 세밀한 필터링이 가능해졌습니다. 메서드명도 새로운 기능을 명확히 반영하고 있습니다.


40-40: userBookId 필터링 조건이 적절히 추가되었습니다.

새로운 확장 함수를 사용하여 일관된 패턴으로 필터링 조건이 구현되었습니다.


59-61: 확장 함수가 기존 패턴을 잘 따르고 있습니다.

userBookIdEq 확장 함수가 기존의 userIdEq 함수와 동일한 패턴으로 구현되어 코드 일관성이 유지되었습니다.

domain/src/main/kotlin/org/yapp/domain/readingrecordtag/ReadingRecordTagRepository.kt (1)

8-8: 도메인 레포지토리 인터페이스가 올바르게 업데이트되었습니다.

userBookId 파라미터 추가로 책별 태그 카운팅이 가능해졌으며, 메서드명이 새로운 기능을 명확히 나타냅니다.

infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/impl/ReadingRecordTagRepositoryImpl.kt (1)

23-24: 레포지토리 구현이 올바르게 업데이트되었습니다.

새로운 userBookId 파라미터가 적절히 하위 레포지토리로 전달되고 있으며, 도메인 인터페이스와 일치합니다.

infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/JpaReadingRecordTagQuerydslRepository.kt (1)

6-11: Querydsl 레포지토리 인터페이스가 명확하게 정의되었습니다.

메서드 시그니처가 새로운 요구사항을 잘 반영하고 있으며, 파라미터 순서가 논리적입니다.

domain/src/main/kotlin/org/yapp/domain/readingrecordtag/ReadingRecordTagDomainService.kt (1)

11-18: 도메인 서비스가 적절히 업데이트되었습니다.

새로운 userBookId 파라미터가 레포지토리로 올바르게 전달되고 있으며, TagStatsVO 생성 로직은 기존과 동일하게 유지되었습니다.

apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordTagService.kt (4)

1-1: 패키지 이름 변경이 올바르게 적용되었습니다.

기존 seed 패키지에서 readingrecord 패키지로의 이전이 적절히 수행되어 도메인 경계가 명확해졌습니다.


10-12: 클래스명 변경이 적절합니다.

SeedService에서 ReadingRecordTagService로의 이름 변경이 도메인 이전의 목적에 부합하며, 역할이 더 명확하게 표현됩니다.


13-18: 메서드 시그니처 변경이 올바르게 수행되었습니다.

userBookId 파라미터 추가와 도메인 서비스 메서드 호출이 리팩토링 목표에 부합하게 구현되었습니다. userBookId를 기준으로 씨앗을 집계하는 요구사항이 잘 반영되었습니다.


4-4: SeedStatsResponse import 경로 검증 완료
SeedStatsResponse 클래스가 org.yapp.apis.readingrecord.dto.response 위치(apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/response/SeedStatsResponse.kt)에 존재하므로 import 경로가 정확합니다.
수정할 필요 없습니다.

apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt (2)

20-20: SeedStatsResponse import 경로 검증 필요

SeedStatsResponse가 readingrecord 패키지로 이동되었다고 하는데, 실제 파일 위치와 일치하는지 확인이 필요합니다.


110-132: 전체 리팩토링 완료 확인

스크립트 결과 다음을 확인했습니다:

  • seed 관련 Controller/Service 클래스(*SeedController, *SeedService)는 모두 삭제됨
  • DTO 파일은 apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/response/SeedStatsResponse.kt 하나만 존재
  • countTagsByUserIdAndUserBookIdAndCategories 호출은 새 API 흐름에 맞게 정상 참조

따라서 추가 조치는 필요하지 않습니다.

import org.yapp.apis.book.dto.response.BookSearchResponse

sealed interface BookQueryService {
fun searchBooks(request: BookSearchRequest): BookSearchResponse
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

일관성을 위한 검토 제안

searchBooks 메서드에도 동일한 검증 패턴을 적용하는 것을 고려해보시기 바랍니다. 현재 getBookDetail에만 @Valid 어노테이션이 적용되어 있어 일관성 측면에서 검토가 필요할 수 있습니다.

🤖 Prompt for AI Agents
In apis/src/main/kotlin/org/yapp/apis/book/service/BookQueryService.kt at line
10, the searchBooks method lacks the @Valid annotation used in getBookDetail,
causing inconsistency in validation. Add the @Valid annotation to the
searchBooks method parameter to ensure consistent validation behavior across
methods.

Comment on lines 7 to 11
import org.yapp.apis.book.dto.request.*
import org.yapp.apis.book.dto.response.BookDetailResponse
import org.yapp.apis.book.dto.response.BookSearchResponse
import org.yapp.apis.book.dto.response.BookSearchResponse.*
import org.yapp.apis.book.dto.response.BookSearchResponse.BookSummary
import org.yapp.apis.book.dto.response.UserBookPageResponse
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

와일드카드(*) import 사용 자제 권고

org.yapp.apis.book.dto.request.* 와일드카드 import 는 IDE 설정에 따라 자동 적용될 수 있지만,

  1. 클래스 충돌 가능성 증가, 2) 읽기/리뷰 시 실제 사용 타입을 한눈에 파악하기 어렵다는 단점이 있습니다.
    현재 파일에서 사용되는 Request DTO 들이 5-6개 수준이므로 명시적 import 로 유지해도 가독성·유지보수성이 충분히 확보됩니다.
-import org.yapp.apis.book.dto.request.*
+import org.yapp.apis.book.dto.request.BookCreateRequest
+import org.yapp.apis.book.dto.request.BookDetailRequest
+import org.yapp.apis.book.dto.request.BookSearchRequest
+import org.yapp.apis.book.dto.request.UpsertUserBookRequest
+import org.yapp.apis.book.dto.request.UserBookRegisterRequest
+import org.yapp.apis.book.dto.request.UserBooksByIsbn13sRequest

반대로 BookSearchResponse.* 대신 BookSummary 단일 import 로 구체화한 변경은 👍 긍정적입니다.
필요하다면 IDE 설정(“Add import on demand”) 기준치를 상향해 와일드카드 자동 전환을 방지하는 것도 고려해 주세요.

📝 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.

Suggested change
import org.yapp.apis.book.dto.request.*
import org.yapp.apis.book.dto.response.BookDetailResponse
import org.yapp.apis.book.dto.response.BookSearchResponse
import org.yapp.apis.book.dto.response.BookSearchResponse.*
import org.yapp.apis.book.dto.response.BookSearchResponse.BookSummary
import org.yapp.apis.book.dto.response.UserBookPageResponse
-import org.yapp.apis.book.dto.request.*
+import org.yapp.apis.book.dto.request.BookCreateRequest
+import org.yapp.apis.book.dto.request.BookDetailRequest
+import org.yapp.apis.book.dto.request.BookSearchRequest
+import org.yapp.apis.book.dto.request.UpsertUserBookRequest
+import org.yapp.apis.book.dto.request.UserBookRegisterRequest
+import org.yapp.apis.book.dto.request.UserBooksByIsbn13sRequest
import org.yapp.apis.book.dto.response.BookDetailResponse
import org.yapp.apis.book.dto.response.BookSearchResponse
import org.yapp.apis.book.dto.response.BookSearchResponse.BookSummary
import org.yapp.apis.book.dto.response.UserBookPageResponse
🤖 Prompt for AI Agents
In apis/src/main/kotlin/org/yapp/apis/book/usecase/BookUseCase.kt around lines 7
to 11, replace the wildcard import 'org.yapp.apis.book.dto.request.*' with
explicit imports of only the Request DTO classes actually used in this file.
This avoids potential class conflicts and improves code readability by making
dependencies clear. Review the file to identify all used Request DTOs and import
them individually instead of using the wildcard.

import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.*
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Import 문 개선사항을 확인해주세요.

wildcard import로 변경되었는데, 사용하지 않는 annotation들이 많이 import될 가능성이 있습니다. 명시적 import가 더 나을 수 있습니다.

🤖 Prompt for AI Agents
In
apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt
at line 17, the import statement uses a wildcard import for Spring web
annotations, which may import unused annotations unnecessarily. Replace the
wildcard import with explicit imports of only the annotations actually used in
this file to improve clarity and reduce unnecessary imports.

import org.yapp.domain.readingrecord.ReadingRecordSortType
import org.yapp.globalutils.exception.ErrorResponse
import java.util.UUID
import java.util.*
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Import 문 일관성 확인

java.util.* wildcard import로 변경되었는데, UUID만 사용한다면 명시적 import가 더 적절할 수 있습니다.

🤖 Prompt for AI Agents
In
apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt
at line 23, the import statement uses a wildcard import for java.util.*, but
only UUID is used. Replace the wildcard import with an explicit import of
java.util.UUID to maintain import consistency and clarity.

Comment on lines 110 to 132
@Operation(
summary = "씨앗 통계 조회",
description = "사용자가 모은 감정 태그별 씨앗 개수를 조회합니다."
)
@ApiResponses(
value = [
ApiResponse(
responseCode = "200",
description = "씨앗 통계 조회 성공",
content = [Content(schema = Schema(implementation = SeedStatsResponse::class))]
),
ApiResponse(
responseCode = "404",
description = "사용자를 찾을 수 없음",
content = [Content(schema = Schema(implementation = ErrorResponse::class))]
)
]
)
@GetMapping("/{userBookId}/seed/stats")
fun getReadingRecordSeedStats(
@AuthenticationPrincipal userId: UUID,
@PathVariable userBookId: UUID
): ResponseEntity<SeedStatsResponse>
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

새로운 API 엔드포인트가 잘 설계되었습니다.

씨앗 통계 조회 API가 userBookId를 path parameter로 받도록 설계되어 리팩토링 목표에 부합합니다. OpenAPI 문서화도 적절하게 작성되었습니다.

다만, API 경로의 일관성을 확인해보세요:

  • 기존: /api/v1/reading-records/{userBookId}/seed/stats
  • 씨앗 관련 기능이므로 /api/v1/seeds/stats?userBookId={userBookId} 형태도 고려할 수 있습니다.
🤖 Prompt for AI Agents
In
apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt
lines 110 to 132, the new seed stats API uses a path parameter for userBookId,
but the API path lacks consistency with existing endpoints. To fix this, either
update the path to match the existing pattern
/api/v1/reading-records/{userBookId}/seed/stats or refactor the endpoint to use
a query parameter like /api/v1/seeds/stats?userBookId={userBookId} to better
reflect seed-related functionality and maintain API consistency.

import org.springframework.data.jpa.repository.JpaRepository
import org.yapp.infra.readingrecordtag.entity.ReadingRecordTagEntity
import java.util.UUID
import java.util.*
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

와일드카드 임포트보다는 명시적 임포트 사용을 권장합니다.

java.util.* 와일드카드 임포트보다는 java.util.UUID처럼 명시적 임포트를 사용하는 것이 좋습니다. 명시적 임포트가 의존성을 명확하게 하고, 네이밍 충돌을 방지하며, 코드 가독성을 향상시킵니다.

-import java.util.*
+import java.util.UUID
📝 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.

Suggested change
import java.util.*
-import java.util.*
+import java.util.UUID
🤖 Prompt for AI Agents
In
infra/src/main/kotlin/org/yapp/infra/readingrecordtag/repository/JpaReadingRecordTagRepository.kt
at line 5, replace the wildcard import 'import java.util.*' with an explicit
import of only the needed classes, such as 'import java.util.UUID'. This change
clarifies dependencies, prevents naming conflicts, and improves code
readability.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Aug 7, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
20.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@move-hoon move-hoon merged commit 23ee350 into develop Aug 7, 2025
2 of 3 checks passed
@move-hoon move-hoon deleted the BOOK-237-refactor/#83 branch August 12, 2025 06:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BOOK-237/refactor] 씨앗 카운팅 API를 userBookId 별로 카운팅 하도록 리팩토링

2 participants