-
Notifications
You must be signed in to change notification settings - Fork 1
refactor: 알라딘 외부 검색 API 호출 시 totalResult를 200개로 제한, lastPage 컬럼 값 추가 #89
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
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 | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,12 +19,6 @@ data class BookSearchResponse private constructor( | |||||||||||||||||||||
| @field:Schema(description = "검색 결과 제목", example = "데미안") | ||||||||||||||||||||||
| val title: String?, | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @field:Schema( | ||||||||||||||||||||||
| description = "검색 결과 링크", | ||||||||||||||||||||||
| example = "http://www.aladin.co.kr/shop/wsarch.aspx?SearchTarget=Book&query=%EC%95%84%EB%B0%94%EC%9D%98+%ED%95%B4%EB%B0%A9%EC%9D%BC%EC%A7%80&partner=openAPI" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| val link: String?, | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @field:Schema(description = "출간일", example = "2025-07-30") | ||||||||||||||||||||||
| val pubDate: String?, | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -46,6 +40,9 @@ data class BookSearchResponse private constructor( | |||||||||||||||||||||
| @field:Schema(description = "검색 카테고리 이름", example = "소설/시/희곡") | ||||||||||||||||||||||
| val searchCategoryName: String?, | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @field:Schema(description = "마지막 페이지 여부", example = "false") | ||||||||||||||||||||||
| val lastPage: Boolean, | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @field:Schema(description = "검색된 책 목록") | ||||||||||||||||||||||
| val books: List<BookSummary> | ||||||||||||||||||||||
| ) { | ||||||||||||||||||||||
|
|
@@ -54,26 +51,27 @@ data class BookSearchResponse private constructor( | |||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| companion object { | ||||||||||||||||||||||
| fun from(response: AladinSearchResponse): BookSearchResponse { | ||||||||||||||||||||||
| fun of(response: AladinSearchResponse, isLastPage: Boolean): BookSearchResponse { // Added isLastPage parameter | ||||||||||||||||||||||
| return BookSearchResponse( | ||||||||||||||||||||||
| version = response.version, | ||||||||||||||||||||||
| title = response.title, | ||||||||||||||||||||||
| link = response.link, | ||||||||||||||||||||||
| pubDate = response.pubDate, | ||||||||||||||||||||||
| totalResults = response.totalResults, | ||||||||||||||||||||||
| startIndex = response.startIndex, | ||||||||||||||||||||||
| itemsPerPage = response.itemsPerPage, | ||||||||||||||||||||||
| query = response.query, | ||||||||||||||||||||||
| searchCategoryId = response.searchCategoryId, | ||||||||||||||||||||||
| searchCategoryName = response.searchCategoryName, | ||||||||||||||||||||||
| lastPage = isLastPage, | ||||||||||||||||||||||
| books = response.item.map { | ||||||||||||||||||||||
| BookSummary.of( | ||||||||||||||||||||||
| isbn = it.isbn, | ||||||||||||||||||||||
| isbn13 = it.isbn13, | ||||||||||||||||||||||
| title = it.title, | ||||||||||||||||||||||
| author = AuthorExtractor.extractAuthors(it.author), | ||||||||||||||||||||||
| publisher = it.publisher, | ||||||||||||||||||||||
| coverImageUrl = it.cover | ||||||||||||||||||||||
| coverImageUrl = it.cover, | ||||||||||||||||||||||
| link = it.link | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
@@ -101,6 +99,12 @@ data class BookSearchResponse private constructor( | |||||||||||||||||||||
| ) | ||||||||||||||||||||||
| val coverImageUrl: String, | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @field:Schema( | ||||||||||||||||||||||
| description = "알라딘 도서 상세 페이지 링크", | ||||||||||||||||||||||
| example = "http://www.aladin.co.kr/shop/wproduct.aspx?ItemId=3680175" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| val link: String, // Added link field | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
Comment on lines
+102
to
+107
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. 🧹 Nitpick (assertive) BookSummary.link의 null 허용 또는 기본값 제공 검토 외부 링크가 누락될 수 있다면 nullable 또는 기본값이 안전합니다. 오픈API 문서에도 선택값임을 반영하세요. - val link: String, // Added link field
+ val link: String?, // 외부 응답 누락 대비📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| @field:Schema(description = "사용자의 책 상태", example = "BEFORE_REGISTRATION") | ||||||||||||||||||||||
| val userBookStatus: BookStatus | ||||||||||||||||||||||
| ) { | ||||||||||||||||||||||
|
|
@@ -115,7 +119,8 @@ data class BookSearchResponse private constructor( | |||||||||||||||||||||
| title: String?, | ||||||||||||||||||||||
| author: String?, | ||||||||||||||||||||||
| publisher: String?, | ||||||||||||||||||||||
| coverImageUrl: String | ||||||||||||||||||||||
| coverImageUrl: String, | ||||||||||||||||||||||
| link: String // Added link | ||||||||||||||||||||||
| ): BookSummary { | ||||||||||||||||||||||
|
Comment on lines
+122
to
124
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. 🧹 Nitpick (assertive) 팩토리 시그니처/구현을 null 허용에 맞추어 조정 위 제안과 함께 일관되게 처리하세요. - coverImageUrl: String,
- link: String // Added link
+ coverImageUrl: String?,
+ link: String?
): BookSummary {
require(!title.isNullOrBlank()) { "Title is required" }
return BookSummary(
isbn13 = isbn13 ?: IsbnConverter.toIsbn13(isbn)
?: throw IllegalArgumentException("Either isbn13 or isbn must be provided"),
title = title,
author = author,
publisher = publisher?.let { BookDataValidator.removeParenthesesFromPublisher(it) },
- coverImageUrl = coverImageUrl,
- link = link,
+ coverImageUrl = coverImageUrl ?: "",
+ link = link,
userBookStatus = BookStatus.BEFORE_REGISTRATION
)추가로, 커버 기본값(예: placeholder 이미지 URL)을 환경설정으로 관리하면 좋습니다. Also applies to: 134-135 🤖 Prompt for AI Agents |
||||||||||||||||||||||
| require(!title.isNullOrBlank()) { "Title is required" } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -126,6 +131,7 @@ data class BookSearchResponse private constructor( | |||||||||||||||||||||
| author = author, | ||||||||||||||||||||||
| publisher = publisher?.let { BookDataValidator.removeParenthesesFromPublisher(it) }, | ||||||||||||||||||||||
| coverImageUrl = coverImageUrl, | ||||||||||||||||||||||
| link = link, | ||||||||||||||||||||||
| userBookStatus = BookStatus.BEFORE_REGISTRATION | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,9 +9,10 @@ enum class BookErrorCode( | |||||||||||||||||||||||||
| private val message: String | ||||||||||||||||||||||||||
| ) : BaseErrorCode { | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /* 500 INTERNAL_SERVER_ERROR */ | ||||||||||||||||||||||||||
| ALADIN_API_SEARCH_FAILED(HttpStatus.INTERNAL_SERVER_ERROR, "BOOK_500_01", "알라딘 도서 검색 API 호출에 실패했습니다."), | ||||||||||||||||||||||||||
| ALADIN_API_LOOKUP_FAILED(HttpStatus.INTERNAL_SERVER_ERROR, "BOOK_500_02", "알라딘 도서 상세 조회 API 호출에 실패했습니다."); | ||||||||||||||||||||||||||
| /* 403 FORBIDDEN */ | ||||||||||||||||||||||||||
| ALADIN_API_SEARCH_FAILED(HttpStatus.FORBIDDEN, "BOOK_403_01", "알라딘 도서 검색 API 호출에 실패했습니다."), | ||||||||||||||||||||||||||
| ALADIN_API_LOOKUP_FAILED(HttpStatus.FORBIDDEN, "BOOK_403_02", "알라딘 도서 상세 조회 API 호출에 실패했습니다."), | ||||||||||||||||||||||||||
| ALADIN_API_RESULT_LIMIT(HttpStatus.FORBIDDEN, "BOOK_403_03", "검색 결과가 200개를 초과하여 모든 결과를 조회했습니다."); | ||||||||||||||||||||||||||
|
Comment on lines
+12
to
+15
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. 💡 Verification agent ❓ Verification inconclusiveALADIN_API_RESULT_LIMIT 메시지 수정 및 403 적용 타당성 검토 제안
적용 예시: - ALADIN_API_RESULT_LIMIT(HttpStatus.FORBIDDEN, "BOOK_403_03", "검색 결과가 200개를 초과하여 모든 결과를 조회했습니다.");
+ ALADIN_API_RESULT_LIMIT(
+ HttpStatus.FORBIDDEN,
+ "BOOK_403_03",
+ "검색 결과 상한(200개)을 초과하는 범위를 요청했습니다. 상위 200개까지만 조회 가능합니다."
+ );추가 권고:
ALADIN_API_RESULT_LIMIT 메시지 및 HTTP 상태 코드 검토 필요 ALADIN_API_RESULT_LIMIT 예외 메시지가 실제 동작(요청 범위 초과)과 불일치하며, 403 FORBIDDEN 적용 타당성도 재검토가 필요합니다. • 위치
• 제안된 수정 예시 - ALADIN_API_RESULT_LIMIT(HttpStatus.FORBIDDEN, "BOOK_403_03", "검색 결과가 200개를 초과하여 모든 결과를 조회했습니다.");
+ ALADIN_API_RESULT_LIMIT(
+ HttpStatus.FORBIDDEN,
+ "BOOK_403_03",
+ "검색 결과 상한(200개)을 초과하는 범위를 요청했습니다. 상위 200개까지만 조회 가능합니다."
+ );• 검토 사항
📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| override fun getHttpStatus(): HttpStatus = httpStatus | ||||||||||||||||||||||||||
| override fun getCode(): String = code | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,6 +22,7 @@ class AladinBookQueryService( | |||||||||||||||||||||||||||||||||
| private val aladinApi: AladinApi | ||||||||||||||||||||||||||||||||||
| ) : BookQueryService { | ||||||||||||||||||||||||||||||||||
| private val log = KotlinLogging.logger {} | ||||||||||||||||||||||||||||||||||
| private val MAX_ALADIN_RESULTS = 200 // Added constant | ||||||||||||||||||||||||||||||||||
|
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. 🧹 Nitpick (assertive) 상수는 companion object의 const로 승격 인스턴스별로 생성할 이유가 없고 컴파일 타임 상수로 적합합니다. - private val MAX_ALADIN_RESULTS = 200 // Added constant
+ companion object {
+ private const val MAX_ALADIN_RESULTS: Int = 200
+ }🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| override fun searchBooks(request: BookSearchRequest): BookSearchResponse { | ||||||||||||||||||||||||||||||||||
| log.info { "Service - Converting BookSearchRequest to AladinBookSearchRequest and calling Aladin API for book search." } | ||||||||||||||||||||||||||||||||||
|
|
@@ -50,23 +51,33 @@ class AladinBookQueryService( | |||||||||||||||||||||||||||||||||
| validIsbn13?.let { item.copy(isbn13 = it) } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| val cappedTotalResults = minOf(response.totalResults ?: 0, MAX_ALADIN_RESULTS) | ||||||||||||||||||||||||||||||||||
| val currentFetchedCount = (request.start ?: 1) * (response.itemsPerPage ?: 0) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (currentFetchedCount > MAX_ALADIN_RESULTS) { | ||||||||||||||||||||||||||||||||||
| throw BookException( | ||||||||||||||||||||||||||||||||||
| BookErrorCode.ALADIN_API_RESULT_LIMIT | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| val isLastPage = currentFetchedCount >= cappedTotalResults | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
Comment on lines
+54
to
+64
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. 💡 Verification agent 🧩 Analysis chain필터링 불일치로 인한 빈 페이지 문제: 점진적 개선안 ISBN 필터링으로 유효 아이템이 줄어 lastPage 계산과 실제 페이지네이션이 엇갈릴 수 있습니다. 현재 PR 범위에서는 정확한 총량을 즉시 알 수 없으므로, 다음 중 하나를 고려해 주세요.
비동기 모델을 추진할 경우, 필요 API/캐시 키 설계 초안을 함께 드릴 수 있습니다. 다음 스크립트로 🏁 Script executed: #!/bin/bash
rg "transformedItems" -n -C3 apis/src/main/kotlin/org/yapp/apis/book/service/AladinBookQueryService.ktLength of output: 687 알라딘 API 필터링 후 빈 페이지 문제: 점진적 개선 제안 File: ISBN 필터링으로 유효 아이템 수가 줄어들면,
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| val filteredResponse = AladinSearchResponse( | ||||||||||||||||||||||||||||||||||
| version = response.version, | ||||||||||||||||||||||||||||||||||
| title = response.title, | ||||||||||||||||||||||||||||||||||
| link = response.link, | ||||||||||||||||||||||||||||||||||
| pubDate = response.pubDate, | ||||||||||||||||||||||||||||||||||
| totalResults = transformedItems.size, | ||||||||||||||||||||||||||||||||||
| totalResults = response.totalResults, | ||||||||||||||||||||||||||||||||||
|
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 totalResults는 capped 값으로 노출(UX/정합성 일치) UI는 - totalResults = response.totalResults,
+ totalResults = cappedTotalResults,참고: 실제 전체 건수(200 초과)를 별도로 노출해야 한다면 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| startIndex = response.startIndex, | ||||||||||||||||||||||||||||||||||
| itemsPerPage = response.itemsPerPage, | ||||||||||||||||||||||||||||||||||
| query = response.query, | ||||||||||||||||||||||||||||||||||
| searchCategoryId = response.searchCategoryId, | ||||||||||||||||||||||||||||||||||
| searchCategoryName = response.searchCategoryName, | ||||||||||||||||||||||||||||||||||
| item = transformedItems | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| log.info { "After filtering - Full Response: $filteredResponse" } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| return BookSearchResponse.from(filteredResponse) | ||||||||||||||||||||||||||||||||||
| return BookSearchResponse.of(filteredResponse, isLastPage) // Passed isLastPage | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| override fun getBookDetail(request: BookDetailRequest): BookDetailResponse { | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestMapping | |||||
| import org.springframework.web.bind.annotation.RequestParam | ||||||
| import org.springframework.web.bind.annotation.RestController | ||||||
| import org.yapp.apis.readingrecord.dto.request.CreateReadingRecordRequest | ||||||
| import org.yapp.apis.readingrecord.dto.response.ReadingRecordPageResponse // Added import | ||||||
|
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. 🧹 Nitpick (assertive) 리뷰 잔재 주석 제거 프로덕션 코드에서 -import org.yapp.apis.readingrecord.dto.response.ReadingRecordPageResponse // Added import
+import org.yapp.apis.readingrecord.dto.response.ReadingRecordPageResponse📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| import org.yapp.apis.readingrecord.dto.response.ReadingRecordResponse | ||||||
| import org.yapp.apis.readingrecord.usecase.ReadingRecordUseCase | ||||||
| import org.yapp.domain.readingrecord.ReadingRecordSortType | ||||||
|
|
@@ -61,7 +62,7 @@ class ReadingRecordController( | |||||
| @RequestParam(required = false) sort: ReadingRecordSortType?, | ||||||
| @PageableDefault(size = 10, sort = ["createdAt"], direction = Sort.Direction.DESC) | ||||||
| pageable: Pageable | ||||||
| ): ResponseEntity<Page<ReadingRecordResponse>> { | ||||||
| ): ResponseEntity<ReadingRecordPageResponse> { | ||||||
| val response = readingRecordUseCase.getReadingRecordsByUserBookId( | ||||||
| userId = userId, | ||||||
| userBookId = userBookId, | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package org.yapp.apis.readingrecord.dto.response | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema | ||
| import org.springframework.data.domain.Page | ||
|
|
||
| @Schema( | ||
| name = "ReadingRecordPageResponse", | ||
| description = "독서 기록 페이징 조회 응답" | ||
| ) | ||
| data class ReadingRecordPageResponse private constructor( | ||
| @field:Schema(description = "마지막 페이지 여부", example = "false") | ||
| val lastPage: Boolean, | ||
|
|
||
| @field:Schema(description = "총 결과 개수", example = "42") | ||
| val totalResults: Int, | ||
|
|
||
|
Comment on lines
+10
to
+16
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 totalResults 다운캐스팅(Int)으로 인한 정보 손실 가능성 — Long 사용 권장
data class ReadingRecordPageResponse private constructor(
@field:Schema(description = "마지막 페이지 여부", example = "false")
val lastPage: Boolean,
- @field:Schema(description = "총 결과 개수", example = "42")
- val totalResults: Int,
+ @field:Schema(description = "총 결과 개수", example = "42")
+ val totalResults: Long,
@@
return ReadingRecordPageResponse(
lastPage = page.isLast,
- totalResults = page.totalElements.toInt(),
+ totalResults = page.totalElements,Also applies to: 27-31 🤖 Prompt for AI Agents |
||
| @field:Schema(description = "현재 페이지 번호 (0부터 시작)", example = "0") | ||
| val startIndex: Int, | ||
|
|
||
| @field:Schema(description = "한 페이지당 아이템 개수", example = "10") | ||
| val itemsPerPage: Int, | ||
|
|
||
|
Comment on lines
+17
to
+22
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. 💡 Verification agent 🧩 Analysis chainstartIndex 의미 명확화 필요: 필드명 vs 값 불일치 가능성 설명은 "현재 페이지 번호(0부터 시작)"인데, 필드명은 보통 "첫 항목의 시작 오프셋"을 연상시키는
대안 A(diff): - @field:Schema(description = "현재 페이지 번호 (0부터 시작)", example = "0")
- val startIndex: Int,
+ @field:Schema(description = "현재 페이지의 첫 결과 오프셋(0부터 시작)", example = "0")
+ val startIndex: Int,
@@
- startIndex = page.number,
+ startIndex = page.number * page.size,대안 B(diff): - @field:Schema(description = "현재 페이지 번호 (0부터 시작)", example = "0")
- val startIndex: Int,
+ @field:Schema(description = "현재 페이지 번호 (0부터 시작)", example = "0")
+ val pageIndex: Int,
@@
- startIndex = page.number,
+ pageIndex = page.number,확정하신 의도를 알려주시면 그에 맞춰 나머지 레이어(문서/클라이언트 영향 범위) 반영 패치도 도와드리겠습니다. Also applies to: 27-35 아래 스크립트를 실행하여 🏁 Script executed: #!/bin/bash
set -e
# 파일 위치 찾기
file=$(fd -e kt ReadingRecordPageResponse.kt)
echo "Found file: $file"
echo
echo "=== Fields (1~50 lines) ==="
sed -n '1,50p' "$file"
echo
echo "=== Mapping logic for startIndex ==="
rg -n 'startIndex' -C 3 "$file"Length of output: 2465 startIndex 필드명과 실제 매핑 불일치: 페이지 번호 vs 오프셋 의미 검토 및 수정 필요 현재 • 대상 파일 • 문제 위치
• 대안 A (오프셋 의미 유지, 매핑 수정)
@@ 17,18c17,18
- @field:Schema(description = "현재 페이지 번호 (0부터 시작)", example = "0")
+ @field:Schema(description = "현재 페이지의 첫 결과 오프셋(0부터 시작)", example = "0")
@@ 31c31
- startIndex = page.number,
+ startIndex = page.number * page.size,• 대안 B (페이지 번호 의미 유지, 필드명 변경)
@@ 17,18c17,18
- @field:Schema(description = "현재 페이지 번호 (0부터 시작)", example = "0")
- val startIndex: Int,
+ @field:Schema(description = "현재 페이지 번호 (0부터 시작)", example = "0")
+ val pageIndex: Int,
@@ 31,32c31,32
- startIndex = page.number,
+ pageIndex = page.number,위 중 적절한 의도를 선택해 알려주시면, 나머지 문서·클라이언트 레이어 반영도 도와드리겠습니다.
🤖 Prompt for AI Agents |
||
| @field:Schema(description = "독서 기록 목록") | ||
| val readingRecords: List<ReadingRecordResponse> | ||
| ) { | ||
|
Comment on lines
+23
to
+25
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. 🧹 Nitpick (assertive) 배열 스키마 명시로 문서 명확성 향상 권장 스웨거에서 제네릭 배열을 잘 추론하긴 하지만, 명시적으로 item 타입을 지정하면 문서 가독성이 좋아집니다. +import io.swagger.v3.oas.annotations.media.ArraySchema
@@
- @field:Schema(description = "독서 기록 목록")
- val readingRecords: List<ReadingRecordResponse>
+ @field:ArraySchema(arraySchema = Schema(description = "독서 기록 목록"), schema = Schema(implementation = ReadingRecordResponse::class))
+ val readingRecords: List<ReadingRecordResponse>🤖 Prompt for AI Agents |
||
| companion object { | ||
| fun from(page: Page<ReadingRecordResponse>): ReadingRecordPageResponse { | ||
| return ReadingRecordPageResponse( | ||
| lastPage = page.isLast, | ||
| totalResults = page.totalElements.toInt(), | ||
| startIndex = page.number, | ||
| itemsPerPage = page.size, | ||
| readingRecords = page.content | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -5,6 +5,7 @@ import org.springframework.data.domain.Pageable | |||||
| import org.springframework.transaction.annotation.Transactional | ||||||
| import org.yapp.apis.book.service.UserBookService | ||||||
| import org.yapp.apis.readingrecord.dto.request.CreateReadingRecordRequest | ||||||
| import org.yapp.apis.readingrecord.dto.response.ReadingRecordPageResponse // Added import | ||||||
|
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. 🧹 Nitpick (assertive) 리뷰 잔재 주석 제거 import 라인의 -import org.yapp.apis.readingrecord.dto.response.ReadingRecordPageResponse // Added import
+import org.yapp.apis.readingrecord.dto.response.ReadingRecordPageResponse📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| import org.yapp.apis.readingrecord.dto.response.ReadingRecordResponse | ||||||
| import org.yapp.apis.readingrecord.dto.response.SeedStatsResponse | ||||||
| import org.yapp.apis.readingrecord.service.ReadingRecordService | ||||||
|
|
@@ -55,15 +56,16 @@ class ReadingRecordUseCase( | |||||
| userBookId: UUID, | ||||||
| sort: ReadingRecordSortType?, | ||||||
| pageable: Pageable | ||||||
| ): Page<ReadingRecordResponse> { | ||||||
| ): ReadingRecordPageResponse { | ||||||
| userService.validateUserExists(userId) | ||||||
| userBookService.validateUserBookExists(userBookId, userId) | ||||||
|
|
||||||
| return readingRecordService.getReadingRecordsByDynamicCondition( | ||||||
| val page = readingRecordService.getReadingRecordsByDynamicCondition( // Stored in a variable | ||||||
| userBookId = userBookId, | ||||||
| sort = sort, | ||||||
| pageable = pageable | ||||||
| ) | ||||||
| return ReadingRecordPageResponse.from(page) // Converted to new DTO | ||||||
| } | ||||||
|
|
||||||
| fun getSeedStats( | ||||||
|
|
||||||
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.
🧹 Nitpick (assertive)
lastPage 필드 추가 LGTM — 스키마 설명에 200개 제한 정책을 명시 제안
필터링/상한(200개) 정책 하에서 lastPage는 총합과 불일치할 수 있음을 스키마 설명에 한 줄 보강하면 소비자 혼선을 줄일 수 있습니다.
🤖 Prompt for AI Agents