Skip to content

Conversation

@minwoo1999
Copy link
Member

@minwoo1999 minwoo1999 commented Jul 30, 2025

🔗 관련 이슈

📘 작업 유형

  • ✨ Feature (기능 추가)

  • 🐞 Bugfix (버그 수정)

  • 🔧 Refactor (코드 리팩토링)

  • ⚙️ Chore (환경 설정)

  • 📝 Docs (문서 작성 및 수정)

  • ✅ Test (기능 테스트)

  • 🎨 style (코드 스타일 수정)

📙 작업 내역

  • 독서기록 생성 및 조회 API 응답에 관련 도서 정보를 포함하도록 기능을 추가했습니다.

  • 응답에 추가된 정보는 도서 제목, 출판사, 도서 표지 이미지 URL입니다.

  • ReadingRecordDomainService에서 독서기록을 처리할 때, UserBookRepository를 통해 연관된 UserBook 엔티티를 조회하고 해당 도서 정보를 ReadingRecordInfoVO에 담아 반환하도록 수정했습니다.

  • 추가적으로, 알라딘 API에서 책 정보를 조회할 때 더 큰 사이즈의 표지 이미지를 가져오도록 요청 파라미터를 수정하여 이미지 품질을 개선했습니다.

🧪 테스트 내역

  • 브라우저/기기에서 동작 확인

  • 엣지 케이스 테스트 완료

  • 기존 기능 영향 없음

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

기능 | 미리보기 | 기능 | 미리보기 -- | -- | -- | -- 기능 설명 |   | 기능 설명 |  
Sheets로 내보내기

✅ PR 체크리스트

  • 커밋 메시지가 명확합니다

  • PR 제목이 컨벤션에 맞습니다

  • 관련 이슈 번호를 작성했습니다

  • 기능이 정상적으로 작동합니다

  • 불필요한 코드를 제거했습니다

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

  • 독서기록 목록 조회 시, N+1 문제를 방지하기 위해 개별 독서기록마다 UserBook을 조회하지 않습니다.

  • 대신, 해당 페이지의 모든 독서기록이 동일한 userBookId에 속하므로, UserBook한 번만 조회하여 모든 응답 DTO에 동일한 책 정보를 매핑해주었습니다.

  • 이 방식은 현재 요구사항에 효율적이며, 추후 여러 책의 독서기록을 한 번에 조회하는 기능이 생긴다면 추가적인 최적화가 필요할 수 있습니다.

Summary by CodeRabbit

  • 신규 기능
    • 독서 기록 응답에 책 제목, 출판사, 표지 이미지 URL 정보가 추가되어 확인할 수 있습니다.
  • 버그 수정
    • 도서 조회 시 큰 사이즈의 표지 이미지를 명확하게 요청하도록 개선되었습니다.

@coderabbitai
Copy link

coderabbitai bot commented Jul 30, 2025

📝 Walkthrough

Walkthrough

독서기록 목록 조회 API의 응답에 도서 썸네일, 제목, 출판사 컬럼이 추가되었습니다. 이를 위해 DTO, VO, 도메인 서비스, 저장소 인터페이스 및 구현체가 확장되었고, 도서 커버 이미지는 외부 API 요청 시 "Big" 사이즈로 명시적으로 요청하도록 변경되었습니다.

Changes

Cohort / File(s) Change Summary
ReadingRecordResponse DTO 확장
apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/response/ReadingRecordResponse.kt
bookTitle, bookPublisher, bookCoverImageUrl 필드 추가 및 factory 메서드(from) 수정
ReadingRecordInfoVO 확장
domain/src/main/kotlin/org/yapp/domain/readingrecord/vo/ReadingRecordInfoVO.kt
VO에 도서 제목, 출판사, 커버 이미지 URL 필드 및 생성자/팩토리 메서드 수정
ReadingRecordDomainService 확장
domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecordDomainService.kt
UserBookRepository 의존성 추가, 도서 정보 조회 및 VO에 포함, 목록 조회/생성 시 book 정보 포함
UserBookRepository 인터페이스 및 구현체 확장
domain/src/main/kotlin/org/yapp/domain/userbook/UserBookRepository.kt,
infra/src/main/kotlin/org/yapp/infra/userbook/repository/impl/UserBookRepositoryImpl.kt
findById(UUID): UserBook? 메서드 추가 및 구현
AladinApi 외부 API 파라미터 수정
infra/src/main/kotlin/org/yapp/infra/external/aladin/AladinApi.kt
커버 이미지 사이즈를 "Big"으로 명시하는 파라미터 추가

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API
    participant DomainService
    participant UserBookRepo
    participant DB

    Client->>API: 독서기록 목록 조회 요청
    API->>DomainService: findReadingRecordsByDynamicCondition()
    DomainService->>UserBookRepo: findById(userBookId)
    UserBookRepo->>DB: SELECT * FROM user_book WHERE id=?
    DB-->>UserBookRepo: UserBook
    UserBookRepo-->>DomainService: UserBook
    DomainService->>DB: SELECT * FROM reading_record WHERE userBookId=?
    DB-->>DomainService: ReadingRecord 목록
    DomainService->>DomainService: 각 ReadingRecord + UserBook 정보로 ReadingRecordInfoVO 생성
    DomainService-->>API: Page<ReadingRecordInfoVO>
    API-->>Client: ReadingRecordResponse (bookTitle, bookPublisher, bookCoverImageUrl 포함)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Assessment against linked issues

Objective Addressed Explanation
독서기록 목록 조회 응답에 도서 썸네일, 제목, 출판사 컬럼 추가 (#58)

Assessment against linked issues: Out-of-scope changes

(해당 변경사항 중 범위를 벗어난 기능적 코드 변경은 발견되지 않았습니다.)

Possibly related PRs

Suggested labels

✨ feat

Suggested reviewers

  • hoonyworld

Note

⚡️ Unit Test Generation is now available in beta!

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

✨ 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-189-feature/#58

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.
    • @coderabbitai modularize this function.
  • 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.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 82f0a61 and a1145fb.

📒 Files selected for processing (6)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/response/ReadingRecordResponse.kt (2 hunks)
  • domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecordDomainService.kt (3 hunks)
  • domain/src/main/kotlin/org/yapp/domain/readingrecord/vo/ReadingRecordInfoVO.kt (3 hunks)
  • domain/src/main/kotlin/org/yapp/domain/userbook/UserBookRepository.kt (1 hunks)
  • infra/src/main/kotlin/org/yapp/infra/external/aladin/AladinApi.kt (1 hunks)
  • infra/src/main/kotlin/org/yapp/infra/userbook/repository/impl/UserBookRepositoryImpl.kt (1 hunks)
⏰ 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 (10)
infra/src/main/kotlin/org/yapp/infra/external/aladin/AladinApi.kt (1)

25-26: 커버 이미지 품질 개선이 적절히 구현됨

API 파라미터에 "Cover" = "Big"을 추가하여 고해상도 커버 이미지를 요청하도록 개선되었습니다. 불변 맵을 가변 맵으로 변환하여 파라미터를 추가하는 방식도 적절합니다.

infra/src/main/kotlin/org/yapp/infra/userbook/repository/impl/UserBookRepositoryImpl.kt (1)

31-33: 구현은 올바르나 보안 취약점을 상속함

JPA 리포지토리 패턴과 도메인 변환이 올바르게 구현되었습니다. 하지만 인터페이스에서 지적한 사용자 인증 우회 가능성을 그대로 구현하고 있습니다.

인터페이스 레벨에서 보안 이슈가 해결되면 이 구현도 함께 수정이 필요합니다.

apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/response/ReadingRecordResponse.kt (2)

35-42: DTO 필드 확장이 적절히 구현됨

도서 관련 필드들이 적절한 스키마 문서화와 함께 추가되었습니다. nullable 타입 사용도 도서 정보가 항상 사용 가능하지 않을 수 있다는 점을 고려할 때 적절합니다.


56-59: 매핑 로직이 올바르게 구현됨

ReadingRecordInfoVO에서 새로운 도서 관련 필드들을 올바르게 매핑하고 있습니다.

domain/src/main/kotlin/org/yapp/domain/readingrecord/vo/ReadingRecordInfoVO.kt (2)

15-17: 도메인 VO 확장이 적절함

도서 관련 필드들이 nullable로 적절히 추가되었고, 기본값 null 설정도 합리적입니다.


29-32: 팩토리 메서드 업데이트가 올바름

newInstance 메서드가 새로운 파라미터들을 선택적으로 받도록 올바르게 업데이트되었고, 생성자 호출에서도 적절히 매핑하고 있습니다.

Also applies to: 42-45

domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecordDomainService.kt (4)

10-10: 새로운 의존성 추가가 적절합니다.

UserBookRepository 의존성 추가가 도서 정보를 독서기록 응답에 포함시키기 위한 요구사항에 맞게 잘 구현되었습니다.

Also applies to: 19-19


68-83: N+1 쿼리 문제 방지를 위한 최적화가 잘 구현되었습니다.

코멘트에서 언급한 대로 UserBook을 한 번만 조회하여 모든 독서기록에 적용하는 방식이 성능상 효율적입니다. 다만 findReadingRecordsByDynamicCondition에서도 createReadingRecord와 동일하게 UserBook이 null일 가능성에 대한 처리가 적절히 되어 있습니다.


76-82: 일관된 VO 생성 패턴 사용을 권장합니다.

두 메서드 모두에서 ReadingRecordInfoVO.newInstance() 호출 시 동일한 패턴으로 book 관련 정보를 전달하고 있어 코드 일관성이 좋습니다. 향후 유지보수를 위해 이 패턴을 유지하는 것을 권장합니다.

⛔ Skipped due to learnings
Learnt from: hoonyworld
PR: YAPP-Github/Reed-Server#39
File: apis/src/main/kotlin/org/yapp/apis/book/dto/response/BookSearchResponse.kt:45-45
Timestamp: 2025-07-17T15:09:36.267Z
Learning: Response DTO 클래스에서는 불변성을 지키기 위해 프로퍼티를 val로 선언하고, 업데이트가 필요한 경우 copy() 메서드를 사용해야 합니다.

51-59: UserBook이 존재하지 않을 때 예외 처리 검증 필요

  • domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecordDomainService.kt
    • createReadingRecord() 메서드 내 userBookRepository.findById(userBookId) 호출부
    • findReadingRecordsByDynamicCondition() 메서드 내 동일 호출부

현재 findById()가 null을 반환해도 독서기록은 생성되며 VO에는 도서 정보가 누락됩니다.
비즈니스 요구사항상 UserBook이 없는 경우에도 기록 생성을 허용해야 하는지,
허용하지 않는다면 곧바로 예외를 던지거나 별도 검증 로직을 추가해야 합니다.
확인 부탁드립니다.

fun findByUserIdAndBookIsbn(userId: UUID, isbn: String): UserBook?
fun findByBookIdAndUserId(bookId: UUID, userId: UUID): UserBook?
fun findByIdAndUserId(id: UUID, userId: UUID): UserBook?
fun findById(id: UUID): UserBook?
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

보안 취약점: 사용자 인증 우회 가능성

새로 추가된 findById(id: UUID) 메서드는 사용자 ID 검증을 생략하여 다른 사용자의 UserBook에 접근할 수 있는 보안 취약점을 생성합니다. 기존 메서드들(findByIdAndUserId, findByBookIdAndUserId 등)은 모두 userId를 통한 접근 제어를 수행하고 있습니다.

사용자 스코프를 유지하도록 다음과 같이 수정하는 것을 권장합니다:

-    fun findById(id: UUID): UserBook?
+    // 이 메서드 대신 기존의 findByIdAndUserId를 사용하거나,
+    // 반드시 필요한 경우 명시적으로 internal용임을 표시
🤖 Prompt for AI Agents
In domain/src/main/kotlin/org/yapp/domain/userbook/UserBookRepository.kt at line
13, the findById(id: UUID) method lacks user ID verification, allowing
unauthorized access to other users' UserBook data. Modify this method to include
userId as a parameter and enforce access control by querying with both id and
userId, similar to existing methods like findByIdAndUserId, to maintain user
scope and prevent authentication bypass.

@minwoo1999 minwoo1999 changed the title Book 189 feature/#58 feat: 독서기록 목록조회 컬럼추가 Jul 31, 2025
@minwoo1999 minwoo1999 merged commit 5542b9c into develop Jul 31, 2025
6 of 7 checks passed
@move-hoon move-hoon deleted the BOOK-189-feature/#58 branch August 12, 2025 06:29
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-189/feat] 독서기록 목록조회 컬럼추가

2 participants