Skip to content

[FIX/#466] 리뷰 목록 조회 1-based 페이지 계약 복원 - #467

Merged
2ghrms merged 1 commit into
developfrom
fix/#466-review-pagination-one-indexed
Sep 13, 2026
Merged

2ghrms merged 1 commit into
developfrom
fix/#466-review-pagination-one-indexed

Conversation

@2ghrms

@2ghrms 2ghrms commented Sep 13, 2026

Copy link
Copy Markdown
Member

#️⃣연관된 이슈

close #466

📝작업 내용

#458(#457 수정)에서 발생한 회귀를 되돌립니다.

당시 리뷰 목록 조회 3종의 500 에러를 고치면서 PageRequest.of(pageable.getPageNumber() - 1, ...) 보정을 제거했습니다. 500은 해소됐지만 해당 API들만 0-based 페이징으로 바뀌어 프론트와의 기존 계약이 깨졌습니다. page=1을 보내면 첫 페이지가 아니라 두 번째 페이지가 반환되는 상태입니다.

#457 이슈 본문에 *"spring.data.web.pageable.one-indexed-parameters 설정도 없어 이 -1 보정을 정당화할 근거가 없다"*고 적었는데, 이 판단이 틀렸습니다. 이 저장소는 설정이 아니라 코드로 1-based 규약을 구현하고 있었습니다.

근거 위치
@CheckPage 기본 메시지 "페이지가 1보다 작을 수 없습니다" global/exception/annotation/CheckPage.java
CheckPageValidatorvalue > 0 검증, PAGE_UNDER_ONE 반환 global/exception/validator/CheckPageValidator.java
PageRequest.of(page - 1, size, ...) InquiryServiceImpl, BackofficeInquiryServiceImpl, NotificationQueryServiceImpl, BackofficeNotificationServiceImpl
Math.max(pageable.getPageNumber() - 1, 0) + "프론트에서 1-based 페이지를 보낸 경우 0-based 로 보정" 주석 StudentServiceImpl#getUnreviewedUsage

마지막 항목이 이번 문제의 정답 패턴이며 이미 같은 저장소에 있었습니다. 보정을 걷어내는 대신 이 패턴을 적용했어야 합니다.

🔎코드 설명(스크린샷(선택))

ReviewServiceImpltoZeroIndexed() 헬퍼를 두고 세 메서드 진입부에서 호출합니다.

private Pageable toZeroIndexed(Pageable pageable) {
    return PageRequest.of(
            Math.max(pageable.getPageNumber() - 1, 0),
            pageable.getPageSize(),
            pageable.getSort()
    );
}
요청 조회 인덱스 결과
?page=1 0 첫 페이지 — 프론트 계약 유지
page 생략 0 첫 페이지 — #457의 500 에러 해소 유지
?page=0 0 첫 페이지 — 관용 처리
?page=2 1 두 번째 페이지

Math.max가 핵심입니다. 단순 - 1page 생략 시 -1이 되어 #457의 500이 재발하고, 보정 제거는 계약을 깹니다. 두 요구를 동시에 만족시킵니다.

대상은 GET /reviews/student, GET /reviews/partner, GET /reviews/store/{storeId} 3개입니다. 프론트 앱 수정은 필요하지 않습니다.

테스트

ReviewServiceImplTestArgumentCaptor로 실제 조회 인덱스를 검증하는 케이스를 추가했습니다.

  • checkStudentReview_OneIndexedPage_QueriesFirstPage
  • checkStudentReview_PageOmitted_QueriesFirstPageWithoutError
  • checkStudentReview_SecondPage_QueriesIndexOne
  • checkStudentReview_PreservesSort

./gradlew test 전체 통과를 확인했습니다.

💬고민사항 및 리뷰 요구사항 (Optional)

배포 순서

이 PR이 main 배포 전에 develop에 머지되어야 합니다. 지금 상태로 배포하면 프론트에 불필요한 앱 수정을 요구하게 됩니다. 프론트 공유 문서에서도 해당 항목을 제거했습니다.

별건 — @CheckPage가 사용되지 않습니다

@CheckPageCheckPageValidator는 정의만 있고 실제 사용처가 0건입니다. 1-based 규약을 코드로 강제하려면 페이징 컨트롤러에 부착하는 게 맞고, 그럴 계획이 없다면 제거 대상입니다. 이번 범위 밖이라 손대지 않았는데, 어떻게 할지 의견 주시면 별도 이슈로 정리하겠습니다.

규약 문서화

이번 건의 근본 원인은 1-based 규약이 코드에만 흩어져 있고 어디에도 명시되어 있지 않다는 점입니다. CLAUDE.md에 페이징 규약을 한 줄 추가해두면 같은 실수가 반복되지 않을 것 같습니다.

비고 (Optional)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 버그 수정

    • 학생·파트너·매장 리뷰 조회 API가 프론트엔드의 1부터 시작하는 페이지 번호를 올바르게 처리합니다.
    • 기본 페이지 요청 시 음수 페이지가 생성되지 않도록 보정했습니다.
  • 테스트

    • 리뷰 조회의 페이지 번호 보정 동작에 대한 검증을 추가했습니다.

- #457에서 제거했던 페이지 번호 보정을 Math.max(page - 1, 0) 형태로 복원
- page=1은 첫 페이지로 유지되어 프론트 계약이 깨지지 않고,
  page 생략 시에도 음수가 되지 않아 #457의 500 에러는 그대로 해소
- 저장소 전반이 1-based 규약(@CheckPage, PageRequest.of(page - 1, ...))을
  따르고 있어 리뷰 API만 0-based로 엇갈리던 상태를 정리
- page=1 / 생략 / page=2 / 정렬 유지 케이스 테스트 추가

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Caution

Review failed

Failed to post review comments.

GitHub was unavailable or timed out while CodeRabbit was posting the review. Please request a new review later if the pull request still needs one. Use @coderabbitai full review to retry the review.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 1cb75c51-cbaf-47b4-adf9-6b19b8c3bcd3

📥 Commits

Reviewing files that changed from the base of the PR and between 6a05051 and c19cd4e.

📒 Files selected for processing (2)
  • src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java
  • src/test/java/com/assu/server/domain/review/service/ReviewServiceImplTest.java

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

🧰 Additional context used
📓 Path-based instructions (8)
**`@Transactional`**: 서비스 구현 클래스 레벨에 선언.

📄 CodeRabbit inference engine (GEMINI.md)

Files:

  • src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java
`@Transactional`은 **서비스 구현 클래스 레벨**에 선언.

📄 CodeRabbit inference engine (CLAUDE.md)

Files:

  • src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java
Use Java 17 with 4-space indentation.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java
테스트 메서드명은 **영어**로 작성.

📄 CodeRabbit inference engine (CLAUDE.md)

Files:

  • src/test/java/com/assu/server/domain/review/service/ReviewServiceImplTest.java
비즈니스 로직이 Service에 위치

📄 CodeRabbit inference engine (CLAUDE.md)

Files:

  • src/test/java/com/assu/server/domain/review/service/ReviewServiceImplTest.java
  • src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java
테스트 메서드명은 **영어**로 작성한다.

📄 CodeRabbit inference engine (GEMINI.md)

Files:

  • src/test/java/com/assu/server/domain/review/service/ReviewServiceImplTest.java
코드 블록 내 주석은 작성하지 않는다.

📄 CodeRabbit inference engine (CLAUDE.md)

Files:

  • src/test/java/com/assu/server/domain/review/service/ReviewServiceImplTest.java
  • src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java
import 시 와일드카드(`*`)를 사용하지 않는다.

📄 CodeRabbit inference engine (GEMINI.md)

Files:

  • src/test/java/com/assu/server/domain/review/service/ReviewServiceImplTest.java
  • src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java
📝 Walkthrough

Walkthrough

리뷰 조회 3종이 프론트의 1-based 페이지 번호를 0-based Pageable로 변환합니다. page=0은 첫 페이지로 보정합니다. 테스트는 페이지 번호, 크기, 정렬 조건을 검증합니다.

Changes

리뷰 페이지 보정

Layer / File(s) Summary
리뷰 조회 페이지 변환
src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java
학생, 파트너, 매장 리뷰 조회 전에 Pageable을 변환합니다. toZeroIndexed는 페이지 번호에서 1을 빼고 음수 결과를 0으로 보정합니다. 페이지 크기와 정렬 조건은 유지합니다.
페이지 보정 테스트
src/test/java/com/assu/server/domain/review/service/ReviewServiceImplTest.java
page=1, page=0, page=2의 변환 결과를 검증합니다. 변환 후 페이지 크기와 Sort.DESC "id" 정렬 조건도 검증합니다.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Severity of issue fixed: Medium

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 리뷰 목록 조회 API의 1-based 페이지 계약 복원이라는 주요 변경 사항을 정확하게 설명합니다. 간결하고 구체적이며 변경 내용과 일치합니다.
Linked Issues check ✅ Passed 직접 연결된 이슈 #466의 코딩 요구사항을 충족합니다. ReviewServiceImpltoZeroIndexed() 보정을 추가하고 checkStudentReview, checkPartnerReview, checkStoreReview에 적용했습니다. Math.max(page - 1, 0)으로 page=1, 생략, page=0
Out of Scope Changes check ✅ Passed 변경 범위는 ReviewServiceImpl의 세 리뷰 목록 API와 해당 서비스 테스트로 제한됩니다. 이 변경은 #466의 페이지 계약 복원과 회귀 방지 테스트에 직접 연결됩니다. 프론트 앱 수정이나 이슈에서 별건으로 분리한 @CheckPage 사용처 변경은 포함하지 않았습니다.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/#466-review-pagination-one-indexed

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.

@2ghrms
2ghrms merged commit 40d4789 into develop Sep 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FIX] 리뷰 목록 조회 3종이 0-based 페이징으로 바뀌어 프론트 계약이 깨짐

1 participant