Skip to content

Conversation

@minwoo1999
Copy link
Member

@minwoo1999 minwoo1999 commented Oct 24, 2025

🔗 관련 이슈

📘 작업 유형

  • ✨ Feature (기능 추가)

  • 🐞 Bugfix (버그 수정)

  • 🔧 Refactor (코드 리팩토링)

  • ⚙️ Chore (환경 설정)

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

  • ✅ Test (기능 테스트)

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

📙 작업 내역

  • BookControllerApi

    • 기본 정렬 기준을 createdAtupdatedAt으로 변경

    • @Parameter 예시 및 설명 추가 (페이징 예시 구체화)

  • ReadingRecordControllerApi

    • 페이지네이션 기본 정렬 기준을 createdAtupdatedAt으로 변경

    • Swagger 문서 설명(@Parameter) 개선

  • CreateReadingRecordRequest

    • review 필드의 @NotBlank 제거 → 선택 입력 가능하도록 변경

    • Schema(required = false)로 수정

    • validReview() 메서드 제거 (null 허용 반영)

  • UpdateReadingRecordRequest

    • validReview() 제거

    • validEmotionTags()의 non-null 보장 로직 수정

  • UserBookSortType

    • UPDATED_DATE_ASC, UPDATED_DATE_DESC 정렬 타입 추가

  • JpaUserBookQuerydslRepositoryImpl

    • UserBookSortType에 따른 정렬 로직 추가 (updatedAt 기준)

    • 기본 정렬을 updatedAt.desc()로 변경

🧪 테스트 내역

  • API 문서(Swagger)에서 정렬 기준 변경 확인

  • 페이징 파라미터 정상 작동 확인

  • review 필드 nullable 처리 후 생성 요청 성공 확인

  • 기존 기능 영향 없음

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

기능 | 미리보기 | 기능 | 미리보기 -- | -- | -- | -- Swagger 문서 정렬 기준 변경 | | 독서 기록 생성 요청 (review optional) |

✅ PR 체크리스트

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

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

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

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

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

💬 추가 설명 or 리뷰 포인트

  • review 필드의 nullable 처리에 따라 백엔드 유효성 검증 로직 확인 부탁드립니다.

  • updatedAt 기준 정렬 변경으로 기존 정렬 결과가 달라질 수 있습니다.

  • 향후 정렬 타입 확장 시(RATING_DESC 등) UserBookSortType enum만 확장하면 대응 가능하도록 설계했습니다.

Summary by CodeRabbit

  • 새로운 기능

    • 업데이트 날짜 기준 정렬 옵션 추가
    • 리뷰 필드를 선택 항목으로 변경
  • 개선 사항

    • 기본 정렬을 생성일에서 최근 업데이트일로 변경 — 목록과 기록에서 최근 업데이트 항목 우선 표시
    • 요청 처리 흐름 간소화(입력/검증 방식 정리)
  • 작업(마이그레이션)

    • 리뷰 컬럼을 NULL 허용으로 변경하는 DB 마이그레이션 추가

@coderabbitai
Copy link

coderabbitai bot commented Oct 24, 2025

Walkthrough

기본 정렬 필드를 createdAt에서 updatedAt으로 변경하고, 읽기 기록의 감상평(review)을 선택적(nullable)으로 전환하며 관련 DTO/엔티티/도메인/리포지토리 매핑과 호출부를 일관되게 수정한 리팩토링입니다.

Changes

코호트 / 파일(들) 변경 요약
컨트롤러 페이징 주석 및 기본 정렬 변경
apis/src/main/kotlin/org/yapp/apis/book/controller/BookControllerApi.kt, apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt
@PageableDefault의 기본 정렬을 createdAtupdatedAt으로 변경; BookControllerApi의 pageable 파라미터에 @Parameter 문서 주석(설명·예시) 추가
리포지토리 정렬 처리 추가 및 기본 정렬 변경
infra/src/main/kotlin/org/yapp/infra/userbook/repository/impl/JpaUserBookQuerydslRepositoryImpl.kt
기본 정렬(null 매핑)을 updatedAt.desc()로 변경; UPDATED_DATE_ASC/UPDATED_DATE_DESC 케이스 처리 추가
열거형 확장 (정렬 타입)
domain/src/main/kotlin/org/yapp/domain/userbook/UserBookSortType.kt
UPDATED_DATE_ASC, UPDATED_DATE_DESC 상수 추가 (기존 CREATED_DATE_DESC 유지)
읽기기록 요청 DTO 변경 (Create)
apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/CreateReadingRecordRequest.kt
review에서 @NotBlank 제거 및 @Schema(required = false)로 변경(선택사항); 기존 validReview() 제거; 일부 검증 헬퍼 !!requireNotNull(...)로 변경
읽기기록 요청 DTO 변경 (Update)
apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/UpdateReadingRecordRequest.kt
validPageNumber(), validQuote(), validReview(), validEmotionTags() 등의 보조 접근자 메서드 제거 (필드만 유지)
읽기기록 응답 DTO 변경
apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/response/ReadingRecordResponse.kt
review 타입을 StringString?로 변경; 매퍼 from()에서 안전 호출(?.value) 사용
서비스 호출부 변경 (ReadingRecordService)
apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt
생성/수정 호출 시 기존의 유효성 헬퍼 반환값 대신 DTO 필드를 직접 전달하도록 변경 (request.review, request.pageNumber 등)
도메인: 읽기기록 nullable 처리 및 팩토리/업데이트 변경
domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecord.kt, domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecordDomainService.kt, domain/src/main/kotlin/org/yapp/domain/readingrecord/vo/ReadingRecordInfoVO.kt
도메인 review 타입을 ReviewReview?로 변경; create/reconstruct 파라미터 및 초기화에서 nullable 처리(review?.let { ... }); 도메인 서비스의 createReadingRecordreview: String?로 시그니처 변경; VO의 review도 nullable로 변경
엔티티 매핑 변경 (읽기기록)
infra/src/main/kotlin/org/yapp/infra/readingrecord/entity/ReadingRecordEntity.kt
DB 컬럼 review를 nullable로 변경(nullable = true), 엔티티 프로퍼티 타입을 String?로 변경; toDomain()/fromDomain() 매핑에서 안전 호출로 nullable 처리
DB 마이그레이션 추가
infra/src/main/resources/db/migration/mysql/V20251025_001__make_review_column_nullable.sql
reading_records 테이블의 review 컬럼을 NULL 허용으로 변경하는 마이그레이션 추가

Sequence Diagram

해당 변경들은 기본 정렬 필드와 nullable 전환을 위한 리팩토링으로 새로운 제어 흐름이나 비동기 상호작용을 도입하지 않으므로 시퀀스 다이어그램을 생략합니다.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 분

검토 시 주의할 파일/영역:

  • domain/readingrecord/ReadingRecord.kt — nullable 전환에 따른 생성·업데이트 로직과 기존 값 유지 여부 검증
  • infra/.../ReadingRecordEntity.kt 및 마이그레이션 — DB 제약(기존 데이터)과 엔티티 매핑의 일치성 확인
  • apis/.../CreateReadingRecordRequest.kt, UpdateReadingRecordRequest.kt, ReadingRecordService.kt — 유효성 제거가 상위 계층(컨트롤러/검증)에서 충분히 보장되는지 확인
  • UserBook 정렬 관련(enum + Querydsl) — 새 enum 값이 모든 호출 지점에서 일관되게 처리되는지 확인

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning 연결된 issue #125에서 명시한 요구사항을 초과하는 변경사항이 발견되었습니다. UpdateReadingRecordRequest에서 validPageNumber(), validQuote(), validReview(), validEmotionTags() 메서드가 모두 제거되었는데, issue에서는 review 필드의 Optional 처리만 요청했을 뿐 다른 필드의 검증 메서드 제거는 명시되지 않았습니다 [#125]. 마찬가지로 CreateReadingRecordRequest에서 validPageNumber()와 validQuote() 메서드가 !! 어설션에서 requireNotNull() 호출로 변경되었으며, ReadingRecordService에서도 검증된 메서드 호출 대신 직접 필드 접근으로 변경되었습니다. 이러한 검증 메서드의 광범위한 리팩토링은 issue에서 요청한 범위를 초과합니다. UpdateReadingRecordRequest와 CreateReadingRecordRequest에서 검증 메서드의 광범위한 리팩토링은 issue #125의 요청 범위("기본정렬을 UPDATE_AT으로 변경, 감상평은 Optional로 수정")를 초과합니다. review 필드의 Optional 처리와 관련된 검증 메서드 변경만 필요하며, 다른 필드(pageNumber, quote, emotionTags)의 검증 메서드 제거나 리팩토링은 별도의 issue에서 명확히 정의되어야 합니다. 범위를 벗어난 변경사항을 제거하거나 추가 issue로 분리하기를 권장합니다.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed Pull request의 제목은 "refactor: 기본정렬과 동적정렬 UPDATE시간으로도 가능하도록 수정 , 감상평 Optional"로, 변경 사항의 두 가지 핵심을 명확하게 전달합니다. 기본 정렬을 updatedAt으로 변경하고 리뷰 필드를 옵션으로 만드는 내용이 직접적으로 표현되어 있습니다. 제목은 구체적이고 명확하며, 팀원이 PR 히스토리를 스캔할 때 주요 변경 사항을 즉시 이해할 수 있습니다.
Linked Issues Check ✅ Passed 연결된 issue #125의 요구사항을 분석하면, 두 가지 주요 목표가 있습니다: 기본 정렬을 UPDATE_AT으로 변경 [#125] 및 감상평(review) 필드를 Optional로 수정 [#125]. 코드 변경 사항을 검토하면 BookControllerApi와 ReadingRecordControllerApi에서 createdAt에서 updatedAt으로의 정렬 변경이 구현되었고 [#125], UserBookSortType에 UPDATED_DATE_ASC와 UPDATED_DATE_DESC가 추가되었으며 [#125], JpaUserBookQuerydslRepositoryImpl에서 updatedAt 정렬이 지원되고 기본값으로 설정되었습니다 [#125]. 또한 CreateReadingRecordRequest, ReadingRecord, ReadingRecordEntity 등 전체 계층에서 review 필드가 nullable로 변경되었습니다 [#125]. 모든 주요 코딩 요구사항이 충족되었습니다.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch BOOK-377-refactor/#125

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b82956 and fe70aa2.

📒 Files selected for processing (1)
  • infra/src/main/resources/db/migration/mysql/V20251025_001__make_review_column_nullable.sql (1 hunks)
🔇 Additional comments (1)
infra/src/main/resources/db/migration/mysql/V20251025_001__make_review_column_nullable.sql (1)

1-1: 마이그레이션 문법이 정확하고 PR 목표와 일치합니다.

MySQL MODIFY COLUMN 문법이 올바르며, 감상평(review) 필드를 선택적으로 변경하는 PR 목표와 일치합니다. Flyway 마이그레이션 파일명(V20251025_001)도 적절한 버전 관리 규칙을 따릅니다.

다만, 다음 항목을 확인해주시기 바랍니다:

  1. reading_records 테이블의 review 컬럼 관련 제약사항: 유니크 키, 외래키, 인덱스 등이 있는지 확인하여 이번 스키마 변경이 다른 제약을 손상하지 않는지 검증해주세요.

  2. 마이그레이션 버전 충돌: 다른 마이그레이션 파일에서 동일한 날짜 버전(20251025_001)을 사용하지 않는지 확인해주세요.

  3. 코드 변경과의 동기화: ReadingRecord.kt, ReadingRecordEntity.kt 등에서 이미 nullable review(Review?)를 지원하고 있는지 다시 한번 확인 부탁드립니다.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
infra/src/main/kotlin/org/yapp/infra/userbook/repository/impl/JpaUserBookQuerydslRepositoryImpl.kt (1)

161-170: UPDATED_DATE 정렬 추가 및 기본값 변경, 방향성 OK — 안정성·성능 2가지 확인 권고

  • 구현은 타당합니다. null 시 updatedAt.desc() 기본값도 의도에 부합합니다.
  • 동일 updatedAt 행들 간 안정적 페이지네이션을 위해 2차 정렬(id DESC 등) 추가를 고려하세요.
  • updatedAt 기준 정렬이 빈번하므로 user_book.updated_at 인덱스 존재 여부를 확인하세요.
apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/UpdateReadingRecordRequest.kt (2)

34-36: 문서 예시가 제약과 불일치(@SiZe(max=3) vs 예시 4개)

예시는 3개 이하로 맞추세요.

-    @field:Schema(description = "수정할 감정 태그 목록", example = """["따뜻함","즐거움","슬픔","깨달음"]""")
+    @field:Schema(description = "수정할 감정 태그 목록", example = """["따뜻함","즐거움","슬픔"]""")

30-33: validReview() 메서드 제거로 인한 컴파일 오류 - 두 곳에서 호출 실패

UpdateReadingRecordRequest에서 validReview() 메서드가 제거되었으나, 서비스 계층에서 여전히 호출하고 있어 빌드가 실패합니다:

  • ReadingRecordService.kt:28 - request.validReview() 호출
  • ReadingRecordService.kt:67 - request.validReview() 호출

review 필드가 선택사항(String?)이므로, 다음 중 하나로 수정하세요:

  1. UpdateReadingRecordRequestfun validReview(): String? = review 메서드 추가
  2. 또는 서비스에서 request.review (nullable 처리)로 변경
apis/src/main/kotlin/org/yapp/apis/book/controller/BookControllerApi.kt (1)

157-166: sort 파라미터 이름 충돌(Spring Pageable vs Enum) — 400 바인딩 실패 위험

메서드에 @RequestParam sort: UserBookSortType?Pageable(기본 sort 파라미터)을 동시에 둔 상태에서 예시 ?sort=updatedAt,desc를 사용하면, enum 바인딩에서 실패(400)할 수 있습니다. 파라미터 명 분리 또는 노출 정책 정리가 필요합니다.

권장 수정안(도메인 정렬 파라미터를 sortType으로 변경, 예시도 일치화):

-        @RequestParam(required = false) @Parameter(description = "정렬 방식") sort: UserBookSortType?,
+        @RequestParam(name = "sortType", required = false)
+        @Parameter(
+            description = "정렬 방식 (TITLE_ASC|TITLE_DESC|CREATED_DATE_ASC|CREATED_DATE_DESC|UPDATED_DATE_ASC|UPDATED_DATE_DESC)",
+            example = "UPDATED_DATE_DESC"
+        )
+        sortType: UserBookSortType?,
@@
-        @Parameter(
-            description = "페이징 정보 (기본값: 10개, 최신 수정일 순)",
-            example = "?page=0&size=10&sort=updatedAt,desc"
-        )
+        @Parameter(
+            description = "페이징 정보 (기본값: 10개, 최신 수정일 순)",
+            example = "?page=0&size=10"
+        )

또는 Pageable의 sort 파라미터를 숨기고(문서) 도메인 정렬만 사용하도록 일원화하는 방안도 고려하세요.

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

85-88: 문서 문구 최신화 필요(“등록순”→“수정일 순” 포함)

기본/권장 정렬이 updatedAt 기준으로 바뀌었으므로 설명을 최신화해 주세요.

-        description = "사용자의 책에 대한 독서 기록을 페이징하여 조회합니다. 정렬은 페이지 번호 또는 최신 등록순으로 가능합니다."
+        description = "사용자의 책에 대한 독서 기록을 페이징하여 조회합니다. 정렬은 페이지 번호 또는 최신 수정일 순 등으로 가능합니다."
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec11ea2 and 13142b0.

📒 Files selected for processing (6)
  • apis/src/main/kotlin/org/yapp/apis/book/controller/BookControllerApi.kt (1 hunks)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt (1 hunks)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/CreateReadingRecordRequest.kt (2 hunks)
  • apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/UpdateReadingRecordRequest.kt (1 hunks)
  • domain/src/main/kotlin/org/yapp/domain/userbook/UserBookSortType.kt (1 hunks)
  • infra/src/main/kotlin/org/yapp/infra/userbook/repository/impl/JpaUserBookQuerydslRepositoryImpl.kt (1 hunks)
🔇 Additional comments (1)
domain/src/main/kotlin/org/yapp/domain/userbook/UserBookSortType.kt (1)

8-10: 새 정렬 타입 추가 LGTM — 노출·호환성 확인

도메인 확장은 적절합니다. 컨트롤러의 쿼리 파라미터/문서 및 클라이언트 사용처도 함께 반영됐는지 확인 부탁드립니다.

Comment on lines 105 to 110
@AuthenticationPrincipal @Parameter(description = "인증된 사용자 ID") userId: UUID,
@PathVariable @Parameter(description = "독서 기록을 조회할 사용자 책 ID") userBookId: UUID,
@RequestParam(required = false) @Parameter(description = "정렬 방식 (PAGE_NUMBER_ASC, PAGE_NUMBER_DESC, CREATED_DATE_ASC, CREATED_DATE_DESC)") sort: ReadingRecordSortType?,
@PageableDefault(size = 10, sort = ["createdAt"], direction = Sort.Direction.DESC)
@Parameter(description = "페이지네이션 정보 (페이지 번호, 페이지 크기, 정렬 방식)") pageable: Pageable
@PageableDefault(size = 10, sort = ["updatedAt"], direction = Sort.Direction.DESC)
@Parameter(description = "페이지네이션 정보 (기본값: 10개, 최신 수정일 순)") pageable: Pageable
): ResponseEntity<ReadingRecordPageResponse>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

sort 파라미터 충돌 위험 — enum 정렬 vs Pageable 정렬 분리 필요

여기도 @RequestParam sort: ReadingRecordSortType?와 Pageable의 sort가 충돌합니다. ?sort=updatedAt,desc 사용 시 enum 바인딩 실패 가능.

권장 수정:

-        @RequestParam(required = false) @Parameter(description = "정렬 방식 (PAGE_NUMBER_ASC, PAGE_NUMBER_DESC, CREATED_DATE_ASC, CREATED_DATE_DESC)") sort: ReadingRecordSortType?,
+        @RequestParam(name = "sortType", required = false)
+        @Parameter(description = "정렬 방식 (PAGE_NUMBER_ASC|PAGE_NUMBER_DESC|CREATED_DATE_ASC|CREATED_DATE_DESC|UPDATED_DATE_ASC|UPDATED_DATE_DESC)", example = "UPDATED_DATE_DESC")
+        sortType: ReadingRecordSortType?,
-        @PageableDefault(size = 10, sort = ["updatedAt"], direction = Sort.Direction.DESC)
-        @Parameter(description = "페이지네이션 정보 (기본값: 10개, 최신 수정일 순)") pageable: Pageable
+        @PageableDefault(size = 10, sort = ["updatedAt"], direction = Sort.Direction.DESC)
+        @Parameter(description = "페이지네이션 정보 (기본값: 10개, 최신 수정일 순)") pageable: Pageable

서비스/레포에서 sortType 반영되도록 함께 조정이 필요합니다.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt
around lines 105 to 110, the request parameter name `sort` collides with Spring
Pageable's `sort` query parameter causing enum binding failures; rename the enum
param (e.g., `sortType`), update the annotation to @RequestParam(name =
"sortType", required = false) and the method signature accordingly, then ensure
the controller converts that sortType into a Spring Sort (or passes it to the
service/repository) and explicitly ignore or reconcile Pageable.sort so the
service applies the enum-based ordering consistently.

Comment on lines 107 to 110
@RequestParam(required = false) @Parameter(description = "정렬 방식 (PAGE_NUMBER_ASC, PAGE_NUMBER_DESC, CREATED_DATE_ASC, CREATED_DATE_DESC)") sort: ReadingRecordSortType?,
@PageableDefault(size = 10, sort = ["createdAt"], direction = Sort.Direction.DESC)
@Parameter(description = "페이지네이션 정보 (페이지 번호, 페이지 크기, 정렬 방식)") pageable: Pageable
@PageableDefault(size = 10, sort = ["updatedAt"], direction = Sort.Direction.DESC)
@Parameter(description = "페이지네이션 정보 (기본값: 10개, 최신 수정일 순)") pageable: Pageable
): ResponseEntity<ReadingRecordPageResponse>
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

OpenAPI 예시/문서에 UPDATED_DATE_ 추가 고려*

도메인 정렬 타입에 UPDATED_DATE가 추가되었으므로 문서에도 반영하세요.

🤖 Prompt for AI Agents
In
apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt
around lines 107 to 110, the @Parameter description for the sort RequestParam
omits the newly added UPDATED_DATE sort values; update the description to
include UPDATED_DATE_ASC and UPDATED_DATE_DESC (e.g. list all supported enums
including PAGE_NUMBER_ASC, PAGE_NUMBER_DESC, CREATED_DATE_ASC,
CREATED_DATE_DESC, UPDATED_DATE_ASC, UPDATED_DATE_DESC) so the OpenAPI docs
reflect the domain change.

Comment on lines 33 to 35
@field:Size(max = 1000, message = "감상평은 1000자를 초과할 수 없습니다.")
@field:Schema(description = "감상평", example = "이 책은 매우 인상적이었습니다.", required = true)
@field:Schema(description = "감상평", example = "이 책은 매우 인상적이었습니다.", required = false)
val review: String? = null,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

LGTM! 감상평 필드가 선택사항으로 올바르게 변경되었습니다.

@NotBlank 제약 조건이 제거되고 required = false로 설정되어 감상평을 선택적으로 입력할 수 있게 되었습니다. 기존의 @Size 검증은 유지되어 값이 제공될 경우 최대 1000자로 제한됩니다.

다음 스크립트를 실행하여 백엔드 로직이 nullable review를 올바르게 처리하는지 확인하세요:


🏁 Script executed:

#!/bin/bash
# Description: CreateReadingRecordRequest를 사용하는 서비스 계층이나 컨트롤러에서 
# review 필드를 null로 처리하는지 확인

# Test: CreateReadingRecordRequest를 사용하는 모든 위치 검색
rg -n --type=kt -C 5 "CreateReadingRecordRequest" 

Length of output: 26



🏁 Script executed:

#!/bin/bash
# Search for CreateReadingRecordRequest usages without specifying file type
rg -n "CreateReadingRecordRequest" -A 5 -B 5

# Search for any calls to validReview method
echo "=== Searching for validReview() calls ==="
rg -n "validReview\s*\(" -A 3 -B 3

# Check the current state of the CreateReadingRecordRequest file
echo "=== Current CreateReadingRecordRequest.kt file ==="
fd "CreateReadingRecordRequest.kt" -x cat {}

Length of output: 18142


긴급: validReview() 메서드가 제거되었으나 서비스 계층에서 여전히 호출되고 있습니다.

CreateReadingRecordRequest.kt에서 validReview() 메서드가 제거되었지만, ReadingRecordService.kt의 다음 위치에서 여전히 호출되고 있어 컴파일 실패가 발생합니다:

  • 라인 28: review = request.validReview(),
  • 라인 67: review = request.validReview(),

수정 방법:

  1. CreateReadingRecordRequest.ktvalidReview() 메서드를 추가하여 nullable review를 반환하거나,
  2. ReadingRecordService.kt에서 request.validReview() 호출을 request.review로 변경해야 합니다.

review 필드가 이제 선택사항이므로 force unwrap(!!)을 사용할 수 없습니다.

🤖 Prompt for AI Agents
In
apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/CreateReadingRecordRequest.kt
around lines 33-35 and in
apis/src/main/kotlin/org/yapp/apis/readingrecord/ReadingRecordService.kt at
lines 28 and 67, the request.validReview() method was removed causing
compilation failures; fix by either (A) reintroducing a simple validReview():
String? method on CreateReadingRecordRequest that returns the nullable review
as-is, or (B) update ReadingRecordService.kt at the two call sites to use
request.review (nullable) instead of request.validReview(); do not use !!,
preserve nullability.

fun validPageNumber(): Int = pageNumber!!
fun validQuote(): String = quote!!
fun validReview(): String = review!!

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

LGTM! validReview() 헬퍼 메서드 제거가 적절합니다.

감상평이 선택사항이 되면서 validReview() 메서드(이전의 review!!)가 제거되었습니다. 필수 필드인 pageNumberquote는 여전히 검증 헬퍼를 유지하고 있어 일관성 있는 구조를 유지하고 있습니다.

제거된 validReview() 메서드를 호출하는 코드가 있는지 확인하세요:


🏁 Script executed:

#!/bin/bash
# Description: validReview() 메서드 사용처 검색. 
# 예상 결과: 사용처가 없어야 함 (있다면 컴파일 에러 발생)

# Test: validReview() 호출 검색
rg -n --type=kt "\.validReview\(\)"

Length of output: 26


🏁 Script executed:

#!/bin/bash
# Description: validReview() 메서드 사용처 검색 (수정된 버전)
# 방법: glob 패턴으로 .kt 파일만 검색

rg -n --glob="*.kt" "\.validReview\(\)"

Length of output: 255


🏁 Script executed:

#!/bin/bash
# Description: ReadingRecordService.kt의 validReview() 호출 부분 확인

# 라인 28 주변 코드 보기 (context: 10줄)
echo "=== Line 28 context ==="
rg -n --glob="*.kt" -B5 -A5 "validReview\(\)" apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt | head -20

echo ""
echo "=== Full view of problematic method ==="
# ReadingRecordService.kt 전체 구조 파악
cat apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt

Length of output: 3998


🏁 Script executed:

#!/bin/bash
# Description: ReadingRecordDomainService의 review 파라미터 타입 확인

# ReadingRecordDomainService 찾기
find . -name "ReadingRecordDomainService.kt" -type f 2>/dev/null | head -5

# createReadingRecord, modifyReadingRecord 메서드 시그니처 확인
rg -n --glob="*.kt" -A10 "fun createReadingRecord|fun modifyReadingRecord" | grep -A10 "ReadingRecordDomainService" | head -30

Length of output: 3575


🏁 Script executed:

#!/bin/bash
# Description: 요청 DTO 파일들에서 review 필드 확인

echo "=== CreateReadingRecordRequest.kt ==="
cat apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/CreateReadingRecordRequest.kt

echo ""
echo "=== UpdateReadingRecordRequest.kt ==="
cat apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/UpdateReadingRecordRequest.kt

Length of output: 3252


apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt에서 컴파일 에러 수정 필요

validReview() 메서드가 제거되었지만, 서비스 레이어에서 여전히 호출되고 있습니다.

  • 라인 28: review = request.validReview()review = request.review 로 변경
  • 라인 67: review = request.validReview()review = request.review 로 변경

추가로, CreateReadingRecordRequestreviewString? (nullable)이지만 ReadingRecordDomainService.createReadingRecord()review: String (non-nullable)을 기대합니다. 도메인 서비스의 파라미터 타입도 함께 검토 필요합니다.

🤖 Prompt for AI Agents
In
apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt
around lines 28 and 67, replace the removed request.validReview() calls with
request.review and handle the nullable mismatch with the domain API: either (A)
update ReadingRecordDomainService.createReadingRecord(...) signature to accept
review: String? so it accepts the DTO's nullable review, or (B) add an explicit
null-check in the service before calling the domain (e.g., provide a default,
skip passing review, or throw a controlled validation exception) so you no
longer pass a nullable String into a parameter typed as non-nullable; also
ensure CreateReadingRecordRequest
(apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/CreateReadingRecordRequest.kt
line ~43) remains String? if you choose option A, or adjust DTO/validation if
you choose to keep domain non-nullable.

Comment on lines 38 to 42
fun validPageNumber(): Int = pageNumber!!
fun validQuote(): String = quote!!
fun validReview(): String = review!!

fun validEmotionTags(): List<String> = emotionTags!!
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

"!!" 사용으로 500(NPE) 위험 — 명시적 검증으로 대체 권장

PATCH DTO 특성상 필드가 null일 수 있는데, 현재 메서드들이 !!로 강제 해제합니다. 클라이언트 오류가 서버 500으로 번질 수 있습니다. requireNotNull 등으로 400 계열로 매핑되도록 바꾸세요.

다음과 같이 최소 수정 제안드립니다:

-    fun validPageNumber(): Int = pageNumber!!
-    fun validQuote(): String = quote!!
+    fun validPageNumber(): Int =
+        requireNotNull(pageNumber) { "pageNumber는 null일 수 없습니다." }
+    fun validQuote(): String =
+        requireNotNull(quote) { "quote는 null일 수 없습니다." }
-    fun validEmotionTags(): List<String> = emotionTags!!
+    fun validEmotionTags(): List<String> =
+        requireNotNull(emotionTags) { "emotionTags는 null일 수 없습니다." }

또는, 서비스/핸들러에서 null 여부를 분기 처리하고 이 유틸 메서드들은 제거하는 방안도 고려하세요.

📝 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
fun validPageNumber(): Int = pageNumber!!
fun validQuote(): String = quote!!
fun validReview(): String = review!!
fun validEmotionTags(): List<String> = emotionTags!!
}
fun validPageNumber(): Int =
requireNotNull(pageNumber) { "pageNumber는 null일 수 없습니다." }
fun validQuote(): String =
requireNotNull(quote) { "quote는 null일 수 없습니다." }
fun validEmotionTags(): List<String> =
requireNotNull(emotionTags) { "emotionTags는 null일 수 없습니다." }
}
🤖 Prompt for AI Agents
In
apis/src/main/kotlin/org/yapp/apis/readingrecord/dto/request/UpdateReadingRecordRequest.kt
around lines 38 to 42, the methods use the Kotlin non-null assertion operator
(!!) which will throw an NPE and surface as a 500; replace these with explicit
validation using requireNotNull(...) with a clear message (e.g., "pageNumber
must not be null") so they throw an IllegalArgumentException (400-level)
instead, or alternatively remove these helper methods and perform null checks
higher in the handler/service; update the three methods to call requireNotNull
with descriptive messages.

@move-hoon
Copy link
Member

CI 실패라서 체크 한번만 부탁드려요~~
코드레빗 Valid 메서드 리뷰도 한번만 검토해주세요 😄

@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

@minwoo1999 minwoo1999 merged commit 5fa446c into develop Oct 25, 2025
3 of 4 checks passed
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-377/refactor] 기본정렬을 UPDATE_AT으로 변경, 감상평은 Optional로 수정합니다.

3 participants