feat: 콘텐츠 관리 - 콘텐츠 조회 구현#206
Conversation
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughQueryDSL 의존성을 빌드 설정에 추가하고 Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/java/com/codeit/team5/mopl/content/controller/api/ContentApi.java`:
- Around line 65-67: The multipart update wrapper currently exposes the wrong
DTO type, so the OpenAPI schema for `ContentUpdateMultipartRequest` does not
match the actual `patchContent` contract. Update the `request` field in
`ContentUpdateMultipartRequest` to use `ContentUpdateRequest` instead of
`ContentCreateRequest`, keeping the wrapper and the `patchContent` method
signature aligned for schema generation and docs.
In
`@src/main/java/com/codeit/team5/mopl/content/dto/request/ContentCursorRequest.java`:
- Around line 20-21: The `ContentCursorRequest` limit binding currently uses
`@NotNull int limit`, but query-bound requests aren’t being validated in
`getContents()`, so invalid values can still reach `request.limit()` and
`subList(...)`. Update the `ContentCursorRequest` record field to use a
validation setup that actually applies to request binding, such as `Integer`
with `@NotNull `@Positive``, and ensure the controller/request handler that
consumes `ContentCursorRequest` enables validation. If keeping `int`, remove
`@NotNull` and enforce positivity with active request validation.
In `@src/main/java/com/codeit/team5/mopl/content/entity/ContentSortByType.java`:
- Around line 9-22: `ContentSortByType`의 공개 sortBy 계약이 요구사항과 맞지 않아
`sortBy=rank`가 실패하고 응답 값도 달라집니다. `ContentSortByType.from()`과 enum 상수 정의를 확인해
`RATE`의 외부 값이 `rank`가 되도록 수정하고, 기존 클라이언트 호환이 필요하면 `from()`에서 `rank`와 `rate`를 모두
허용하도록 처리하세요.
In `@src/main/java/com/codeit/team5/mopl/content/entity/ContentType.java`:
- Around line 23-26: ContentType.from() only matches the serialized value
string, so uppercase enum names like MOVIE and TV_SERIES now fail to bind and
cause 400s. Update ContentType.from(String) to accept both the enum’s value
field and its name() (case-sensitive as needed) so existing requests remain
backward compatible. Keep the fix localized to ContentType.from and preserve the
current matching for movie, tvSeries, and sport.
In
`@src/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentRepositoryImpl.java`:
- Around line 106-143: `applyCursor` is silently skipping pagination when only
one of `cursor` or `idAfter` is present, and malformed values can still bubble
up as parsing exceptions. Move validation for the cursor pair and its format out
of `ContentRepositoryImpl.applyCursor` and into `ContentCursorRequest` or the
service layer so the repository only receives already-validated values. Ensure
invalid or partial cursor input is rejected as a request error instead of
falling back to the first page or throwing raw parse errors from
`UUID.fromString`, `Instant.parse`, `Long.parseLong`, or `Double.parseDouble`.
- Around line 133-154: The RATE sort is using stats.ratingSum instead of the
average rating exposed by ContentResponse, so the ordering and cursor semantics
are inconsistent. Update ContentRepositoryImpl.buildOrder and the RATE branch of
the cursor condition to sort and compare using the same average-rating
expression (or a dedicated persisted average field if you choose that approach),
and keep the tie-breaker on content.id. Also update ContentMapper.toCursor(...)
so its RATE cursor value is generated from the same metric, ensuring pagination
remains stable.
In `@src/main/java/com/codeit/team5/mopl/content/service/ContentService.java`:
- Around line 111-117: The pagination logic in ContentService.findContents
assumes request.limit() is at least 1, so add a lower-bound constraint to the
ContentCursorRequest.limit field and keep the service’s fetch/page calculation
unchanged. Update the request contract by annotating limit with a positive
minimum such as `@Min`(1) or `@Positive`, so ContentService.findContents,
fetchLimit, hasNext, and the subList paging logic never run with a zero limit.
In
`@src/test/java/com/codeit/team5/mopl/content/controller/ContentControllerTest.java`:
- Around line 645-651: The `typeEqual` test case is still using the enum
constant name instead of the public query value, so it does not verify the
frontend-facing mapping added in this PR. Update the `ContentControllerTest`
request in the `get("/api/contents")` scenario to use the actual
`ContentType.getValue()`-style value (for example, the lowercase public value)
or add a separate assertion that explicitly exercises that mapping. Keep the
focus on the `typeEqual` parameter path so this test fails if the converter or
query-parameter translation is missing.
- Around line 607-611: The controller test is asserting a different
sortDirection contract than the actual cursor mapping used by
ContentMapper.toCursor(...), so align them to one format only. Update the
response expectation in ContentControllerTest to match the real API contract
returned by the service path, and make the test data around the CursorResponse
construction use the same ASCENDING/DESCENDING vs ASC/DESC convention everywhere
it appears. If the intended contract is the service output, adjust the test
assertions and any related documentation/comments to expect that exact value
consistently.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: af4fbecd-a0de-49aa-afe0-6a94eb919758
📒 Files selected for processing (23)
build.gradlesrc/main/java/com/codeit/team5/mopl/config/QueryDslConfig.javasrc/main/java/com/codeit/team5/mopl/config/WebConfig.javasrc/main/java/com/codeit/team5/mopl/content/controller/ContentController.javasrc/main/java/com/codeit/team5/mopl/content/controller/api/ContentApi.javasrc/main/java/com/codeit/team5/mopl/content/dto/request/ContentCursorRequest.javasrc/main/java/com/codeit/team5/mopl/content/entity/Content.javasrc/main/java/com/codeit/team5/mopl/content/entity/ContentSortByType.javasrc/main/java/com/codeit/team5/mopl/content/entity/ContentType.javasrc/main/java/com/codeit/team5/mopl/content/exception/ContentIncorrectSortByException.javasrc/main/java/com/codeit/team5/mopl/content/mapper/ContentMapper.javasrc/main/java/com/codeit/team5/mopl/content/repository/ContentRepository.javasrc/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentRepositoryCustom.javasrc/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentRepositoryImpl.javasrc/main/java/com/codeit/team5/mopl/content/service/ContentService.javasrc/main/java/com/codeit/team5/mopl/global/exception/InvalidSortDirectionException.javasrc/test/java/com/codeit/team5/mopl/content/controller/ContentControllerTest.javasrc/test/java/com/codeit/team5/mopl/content/service/ContentServiceTest.javasrc/test/java/com/codeit/team5/mopl/follow/repository/FollowRepositoryTest.javasrc/test/java/com/codeit/team5/mopl/global/support/base/BaseRepositoryTest.javasrc/test/java/com/codeit/team5/mopl/global/support/config/QueryDslTestConfig.javasrc/test/java/com/codeit/team5/mopl/notification/repository/NotificationRepositoryTest.javasrc/test/java/com/codeit/team5/mopl/user/repository/UserRepositoryTest.java
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/com/codeit/team5/mopl/content/controller/api/ContentApi.java (1)
113-122: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win목록 조회 200 응답에도 응답 스키마를 명시해주세요.
현재
getContents의 성공 응답은description만 있어서 OpenAPI 문서/클라이언트 생성 시 실제CursorResponse<ContentResponse>계약이 비어 보일 수 있습니다. 단건 조회처럼 성공 응답의 content schema를 붙이면 API 사용자가 응답 구조를 바로 확인할 수 있습니다.🔧 제안 수정
- `@ApiResponse`(responseCode = "200", description = "성공"), + `@ApiResponse`(responseCode = "200", description = "성공", + content = `@Content`(schema = `@Schema`(implementation = CursorResponse.class))),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/codeit/team5/mopl/content/controller/api/ContentApi.java` around lines 113 - 122, The 200 success response in ContentApi#getContents is missing an explicit response schema, so add the content/schema declaration for the successful ApiResponse to match the actual CursorResponse<ContentResponse> contract. Update the OpenAPI annotations in ContentApi so the 200 response includes the response body type, similar to the other documented endpoints, while keeping the existing error response schemas unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/main/java/com/codeit/team5/mopl/content/dto/request/ContentCursorRequest.java`:
- Around line 21-23: `ContentCursorRequest`의 `limit`은 `@Positive`만으로는 너무 큰 값이
허용되므로, 커서 페이지네이션 계약에 맞는 최대값 제약을 추가하세요. `limit` 필드에 상한 검증 어노테이션을 붙이거나 별도 검증을 넣어
`request.limit() + 1`와 QueryDSL `limit(...)`로 전달되기 전에 큰 요청을 차단하세요.
`ContentCursorRequest`와 이를 사용하는 커서 조회 로직에서 동일한 최대 페이지 크기 기준이 적용되도록 맞춰주세요.
In
`@src/main/java/com/codeit/team5/mopl/content/exception/InvalidCursorException.java`:
- Around line 7-8: The InvalidCursorException constructor currently appends the
raw cursor value into the BusinessException message, which can reflect invalid
input back to clients. Update InvalidCursorException so the super(...) message
is a fixed, generic BAD_REQUEST string without concatenating cursor, and if
needed log the cursor separately in the server-side handling path instead of
exposing it in the response.
In `@src/main/java/com/codeit/team5/mopl/content/service/ContentService.java`:
- Around line 214-219: The cursor parsing in ContentService’s switch for sortBy
RATE currently accepts non-finite values like NaN and Infinity, which can break
paging comparisons against stats.averageRating. Update the RATE branch to
validate the parsed double with Double.isFinite(...) after
Double.parseDouble(cursor), and reject or handle invalid values consistently
with the existing cursor parsing path. Keep the change localized to the cursor
parsing logic in ContentService.
In
`@src/main/resources/db/migration/V12__add_average_rating_to_content_stats.sql`:
- Line 1: The migration only adds average_rating with a default, so existing
content_stats rows are never backfilled and legacy data will stay at 0. Update
the V12__add_average_rating_to_content_stats.sql migration to populate
average_rating from rating_sum and review_count for existing rows before
enforcing NOT NULL/default, using the content_stats table so read paths like
averageRating and RATE sorting reflect stored historical ratings correctly.
---
Outside diff comments:
In `@src/main/java/com/codeit/team5/mopl/content/controller/api/ContentApi.java`:
- Around line 113-122: The 200 success response in ContentApi#getContents is
missing an explicit response schema, so add the content/schema declaration for
the successful ApiResponse to match the actual CursorResponse<ContentResponse>
contract. Update the OpenAPI annotations in ContentApi so the 200 response
includes the response body type, similar to the other documented endpoints,
while keeping the existing error response schemas unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 4371d1cc-bf42-40fb-ac46-76e5650d1223
📒 Files selected for processing (11)
src/main/java/com/codeit/team5/mopl/content/controller/ContentController.javasrc/main/java/com/codeit/team5/mopl/content/controller/api/ContentApi.javasrc/main/java/com/codeit/team5/mopl/content/dto/request/ContentCursorRequest.javasrc/main/java/com/codeit/team5/mopl/content/entity/ContentStats.javasrc/main/java/com/codeit/team5/mopl/content/exception/CursorIdAfterNotTogetherException.javasrc/main/java/com/codeit/team5/mopl/content/exception/InvalidCursorException.javasrc/main/java/com/codeit/team5/mopl/content/mapper/ContentMapper.javasrc/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentRepositoryImpl.javasrc/main/java/com/codeit/team5/mopl/content/service/ContentService.javasrc/main/resources/db/migration/V12__add_average_rating_to_content_stats.sqlsrc/test/java/com/codeit/team5/mopl/content/controller/ContentControllerTest.java
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/main/java/com/codeit/team5/mopl/notification/event/FollowingUserWatchingEvent.java`:
- Around line 5-11: The FollowingUserWatchingEvent record currently allows null
values for required notification fields, so add validation in the record itself
using a compact constructor to fail fast when receiverId, userNickname, or
contentName are missing. Keep the checks inside FollowingUserWatchingEvent so
onFollowingUserActivity() and NotificationService.create(...) can assume valid
inputs and avoid late failures or “null” text in notifications.
In
`@src/main/java/com/codeit/team5/mopl/notification/event/PlaylistSubscribedEvent.java`:
- Around line 5-11: `PlaylistSubscribedEvent` should enforce its construction
contract the same way `DirectMessageSentEvent` does, because empty or null
`receiverId`, `subscriberNickname`, or `playlistName` can slip through and fail
later in listeners. Add creation-time validation inside the
`PlaylistSubscribedEvent` record so these fields cannot be blank or null when
the event is instantiated, using the record’s constructor/validation logic
rather than relying on downstream handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: ef5d2a49-162e-4f57-898b-0a18a7e3d7f3
📒 Files selected for processing (15)
src/main/java/com/codeit/team5/mopl/notification/event/DirectMessageSentEvent.javasrc/main/java/com/codeit/team5/mopl/notification/event/FollowingUserWatchingEvent.javasrc/main/java/com/codeit/team5/mopl/notification/event/NotificationCreatedEvent.javasrc/main/java/com/codeit/team5/mopl/notification/event/PlaylistSubscribedEvent.javasrc/main/java/com/codeit/team5/mopl/notification/event/PlaylistUpdatedEvent.javasrc/main/java/com/codeit/team5/mopl/notification/event/RoleChangedEvent.javasrc/main/java/com/codeit/team5/mopl/notification/event/UserFollowedEvent.javasrc/main/java/com/codeit/team5/mopl/notification/eventlistener/NotificationEventListener.javasrc/main/java/com/codeit/team5/mopl/notification/eventlistener/SseNotificationListener.javasrc/main/java/com/codeit/team5/mopl/notification/exception/InvalidContentException.javasrc/main/java/com/codeit/team5/mopl/notification/exception/InvalidNicknameException.javasrc/main/java/com/codeit/team5/mopl/notification/exception/InvalidReceiverIdException.javasrc/test/java/com/codeit/team5/mopl/notification/event/DirectMessageSentEventTest.javasrc/test/java/com/codeit/team5/mopl/notification/eventlistener/NotificationEventListenerIntegrationTest.javasrc/test/java/com/codeit/team5/mopl/notification/eventlistener/NotificationEventListenerTest.java
- ContentRepositoryCustom: 구현체를 위한 인터페이스 - ContentRepositoryImpl: QueryDsl Repository 구현체 - ContentRepository: ContentRepositoryCustom 상속으로 QueryDsl Repository 메서드 사용 가능
- fetchLimit, hasNext, page, totalCount를 Mapper로 전달
- 파라미터를 받아 CursorResponse로 변환하여 반환 # Conflicts: # src/main/java/com/codeit/team5/mopl/content/mapper/ContentMapper.java
- BaseRepositoryTest, NotificationRepositoryTest, UserRepositoryTest import 추가
- QueryDsl Repository 클래스명 변경 - ContentQueryRepositoryImpl: applyFilters 메서드 리펙토링 - ContentStats: averageRating 필드 제거 - ContentMapper: 중복 메서드 제거
82f09ba to
53a45db
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/java/com/codeit/team5/mopl/content/entity/ContentStats.java`:
- Around line 39-42: `ContentStats.updateRating()` currently accepts invalid
aggregate state, so enforce the domain invariants at this boundary before
assigning `ratingSum` and `reviewCount`. Add validation in `updateRating` to
reject negative `newReviewCount`, reject non-finite or negative `newRatingSum`,
and require `newReviewCount == 0` only when `newRatingSum == 0`; keep the checks
close to `getAverageRating()` and the `ContentStats` entity so bad values cannot
flow into rating-based pagination metadata.
In
`@src/main/java/com/codeit/team5/mopl/content/exception/ContentIncorrectSortByException.java`:
- Around line 8-9: `ContentIncorrectSortByException` 생성자에서
`Map.of("incorrectSortBy", sortBy)`가 `sortBy`가 null일 때 NPE를 일으키는 문제가 있습니다.
`ContentIncorrectSortByException(String sortBy)`에서 details를 만들 때 null이면 빈 map을
사용하거나 `Map<String, Object>`를 조건적으로 구성하도록 바꿔서, `BaseException` 호출이 항상
`BAD_REQUEST`로 정상 생성되게 수정하세요.
In
`@src/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentQueryRepositoryImpl.java`:
- Around line 123-129: Fix the rating sort/cursor logic in
ContentQueryRepositoryImpl so queries do not divide by zero when reviewCount is
0. Extract a shared helper used by both applyCursor and buildOrder that returns
a NumberExpression<Double> matching ContentStats.getAverageRating() semantics,
i.e. 0.0 when reviewCount is zero and ratingSum / reviewCount otherwise. Update
the cursor comparison and ordering expressions to use this helper instead of
directly dividing stats.ratingSum by stats.reviewCount.doubleValue(), so the
sort order and next cursor stay consistent.
In
`@src/main/java/com/codeit/team5/mopl/global/exception/InvalidSortDirectionException.java`:
- Around line 7-8: The error message in InvalidSortDirectionException does not
match the actual accepted values handled by the sort conversion logic. Update
the exception message in InvalidSortDirectionException to reflect the real
allowed inputs used by WebConfig’s sort-direction mapping, including ASC/DESC if
they are valid, or otherwise standardize the parsing so the message and
conversion rules use the same canonical values. Keep the message aligned with
the behavior of the sort direction converter so callers get accurate guidance.
In `@src/test/java/com/codeit/team5/mopl/content/service/ContentServiceTest.java`:
- Around line 466-468: `ContentServiceTest`의 `CursorResponse` 픽스처가 실제
`ContentMapper.toCursor(...)` 계약과 불일치합니다. `expectedResponse`를 만드는 테스트들에서
`sortDirection` 값을 `"DESC"` 대신 실제 반환값인 `"DESCENDING"`(필요 시 `"ASCENDING"`도 동일
기준)으로 맞추거나, 서비스 슬라이싱만 검증하도록 해당 문자열 비교를 덜 구체적으로 조정해 `ContentMapper.toCursor`의 계약과
테스트 기대값이 일치하도록 수정하세요.
- Around line 453-542: `findContents()` 테스트에 커서 검증 실패 경로를 추가해, 잘못된
`cursor`/`idAfter` 조합이 들어오면 `validateCursor(request)`에서 예외가 발생하고
`contentRepository`가 호출되지 않는 계약을 확인하세요. `ContentServiceTest`의 `findContents()`
관련 테스트들 옆에 음수 케이스를 넣고, `contentService.findContents(request)` 호출 시 예외를 assert 한
뒤 `verify(contentRepository, never())`로 조회가 차단되는지 검증하면 됩니다. `validateCursor`,
`findContents`, `ContentCursorRequest`를 기준으로 위치를 찾으면 됩니다.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6a9aed0a-4953-44ec-8a28-fbcaf5d88987
📒 Files selected for processing (28)
build.gradlesrc/main/java/com/codeit/team5/mopl/config/QueryDslConfig.javasrc/main/java/com/codeit/team5/mopl/config/WebConfig.javasrc/main/java/com/codeit/team5/mopl/content/controller/ContentController.javasrc/main/java/com/codeit/team5/mopl/content/controller/api/ContentApi.javasrc/main/java/com/codeit/team5/mopl/content/dto/request/ContentCursorRequest.javasrc/main/java/com/codeit/team5/mopl/content/entity/Content.javasrc/main/java/com/codeit/team5/mopl/content/entity/ContentSortByType.javasrc/main/java/com/codeit/team5/mopl/content/entity/ContentStats.javasrc/main/java/com/codeit/team5/mopl/content/entity/ContentType.javasrc/main/java/com/codeit/team5/mopl/content/exception/ContentIncorrectSortByException.javasrc/main/java/com/codeit/team5/mopl/content/exception/CursorIdAfterNotTogetherException.javasrc/main/java/com/codeit/team5/mopl/content/exception/InvalidCursorException.javasrc/main/java/com/codeit/team5/mopl/content/mapper/ContentMapper.javasrc/main/java/com/codeit/team5/mopl/content/repository/ContentRepository.javasrc/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentQueryRepository.javasrc/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentQueryRepositoryImpl.javasrc/main/java/com/codeit/team5/mopl/content/service/ContentService.javasrc/main/java/com/codeit/team5/mopl/global/exception/InvalidSortDirectionException.javasrc/main/java/com/codeit/team5/mopl/notification/exception/InvalidCursorException.javasrc/main/java/com/codeit/team5/mopl/notification/service/NotificationService.javasrc/test/java/com/codeit/team5/mopl/content/controller/ContentControllerTest.javasrc/test/java/com/codeit/team5/mopl/content/service/ContentServiceTest.javasrc/test/java/com/codeit/team5/mopl/follow/repository/FollowRepositoryTest.javasrc/test/java/com/codeit/team5/mopl/global/support/base/BaseRepositoryTest.javasrc/test/java/com/codeit/team5/mopl/global/support/config/QueryDslTestConfig.javasrc/test/java/com/codeit/team5/mopl/notification/repository/NotificationRepositoryTest.javasrc/test/java/com/codeit/team5/mopl/user/repository/UserRepositoryTest.java
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/java/com/codeit/team5/mopl/content/controller/api/ContentApi.java`:
- Around line 132-133: `ContentApi`의 `sortDirection` Swagger `@Schema` 허용값이 실제
변환 계약보다 좁게 정의되어 있습니다. `WebConfig`의 정렬 파서가 `ASC`/`DESC`도 받아들이는 만큼, `ContentApi`의
`sortDirection` 문서도 `ASC`, `DESC`, `ASCENDING`, `DESCENDING`을 모두 반영하거나, 반대로 실제
파서를 문서와 동일하게 긴 형식만 허용하도록 맞춰서 계약을 하나로 통일해 주세요.
In
`@src/main/java/com/codeit/team5/mopl/content/dto/request/ValidCursorValidator.java`:
- Around line 15-20: `ValidCursorValidator`에서 `cursor`만 있고 `idAfter`가 없을 때
`UUID.fromString(idAfter)`가 NPE를 낼 수 있습니다. `isValid` 로직에서 파싱 전에
`cursor`/`idAfter`가 둘 다 비어 있거나 둘 다 존재하는지 먼저 검증하고, `idAfter`가 null이면 false를 반환하도록
처리해 `UUID.fromString`은 항상 non-null 입력만 받게 수정하세요.
In
`@src/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentQueryRepositoryImpl.java`:
- Around line 23-24: The TODO in ContentQueryRepositoryImpl should be replaced
with real integration coverage before merge. Add `@DataJpaTest` tests backed by
Testcontainers PostgreSQL for the query logic that uses CaseBuilder, cursor
comparisons, and UUID tie-breaking, and verify CREATED_AT, WATCHER_COUNT, and
RATE sorting with first page, next page, tie-break, and reviewCount = 0
scenarios. Focus the tests on the repository behavior in
ContentQueryRepositoryImpl so DB-specific ordering and pagination semantics are
locked in.
- Around line 37-44: `ContentQueryRepositoryImpl.findContents(...)` currently
fetch-joins only `stats`, but `ContentMapper.toDto(...)` also reads
`thumbnail.url` and `thumbnail.uploadStatus`, causing N+1 on list mapping.
Update the query to eagerly load the single-valued `thumbnail` association as
well (alongside `stats`) so the list API doesn’t trigger per-row selects, while
keeping collection associations like tags out of this fetch path and handling
them via batch fetching or a separate step if needed.
In
`@src/main/java/com/codeit/team5/mopl/notification/service/NotificationService.java`:
- Around line 65-68: The cursor parsing in NotificationService currently throws
a new InvalidCursorException without preserving the DateTimeParseException
cause, so add an InvalidCursorException(String cursor, Throwable cause) overload
and use it in the catch block to keep the original stack trace and cursor
context. Update InvalidCursorException to store the cursor in its message and
link the cause via initCause(cause), matching the exception-wrapping pattern
used by other lower-level errors. Reference the NotificationService cursor
parsing logic and the InvalidCursorException constructors when making the
change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 90815b04-ff8e-410e-8e59-628ea016a14b
📒 Files selected for processing (30)
build.gradlesrc/main/java/com/codeit/team5/mopl/config/QueryDslConfig.javasrc/main/java/com/codeit/team5/mopl/config/WebConfig.javasrc/main/java/com/codeit/team5/mopl/content/controller/ContentController.javasrc/main/java/com/codeit/team5/mopl/content/controller/api/ContentApi.javasrc/main/java/com/codeit/team5/mopl/content/dto/request/ContentCursorRequest.javasrc/main/java/com/codeit/team5/mopl/content/dto/request/ValidCursor.javasrc/main/java/com/codeit/team5/mopl/content/dto/request/ValidCursorValidator.javasrc/main/java/com/codeit/team5/mopl/content/entity/Content.javasrc/main/java/com/codeit/team5/mopl/content/entity/ContentSortByType.javasrc/main/java/com/codeit/team5/mopl/content/entity/ContentStats.javasrc/main/java/com/codeit/team5/mopl/content/entity/ContentType.javasrc/main/java/com/codeit/team5/mopl/content/exception/ContentIncorrectSortByException.javasrc/main/java/com/codeit/team5/mopl/content/exception/InvalidContentStatsException.javasrc/main/java/com/codeit/team5/mopl/content/mapper/ContentMapper.javasrc/main/java/com/codeit/team5/mopl/content/repository/ContentRepository.javasrc/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentQueryRepository.javasrc/main/java/com/codeit/team5/mopl/content/repository/querydsl/ContentQueryRepositoryImpl.javasrc/main/java/com/codeit/team5/mopl/content/service/ContentService.javasrc/main/java/com/codeit/team5/mopl/global/exception/InvalidSortDirectionException.javasrc/main/java/com/codeit/team5/mopl/notification/exception/InvalidCursorException.javasrc/main/java/com/codeit/team5/mopl/notification/service/NotificationService.javasrc/test/java/com/codeit/team5/mopl/content/controller/ContentControllerTest.javasrc/test/java/com/codeit/team5/mopl/content/dto/request/ValidCursorValidatorTest.javasrc/test/java/com/codeit/team5/mopl/content/service/ContentServiceTest.javasrc/test/java/com/codeit/team5/mopl/follow/repository/FollowRepositoryTest.javasrc/test/java/com/codeit/team5/mopl/global/support/base/BaseRepositoryTest.javasrc/test/java/com/codeit/team5/mopl/global/support/config/QueryDslTestConfig.javasrc/test/java/com/codeit/team5/mopl/notification/repository/NotificationRepositoryTest.javasrc/test/java/com/codeit/team5/mopl/user/repository/UserRepositoryTest.java
|
Caution Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted. Error details |
1 similar comment
|
Caution Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted. Error details |
관련 이슈
작업 내용
변경 사항
테스트 내용
체크리스트
리뷰 포인트
스크린샷 / 참고 자료
🔗 관련 이슈
#측정하지않음📝 작업 내용
주요 변경사항
hasNext/다음 커서 계산 로직을 서비스와 매퍼에 반영했습니다.📊 변경 효과 요약 (가능한 경우에만)