Conversation
- ClubMonthlyStatusQuery, ClubMonthlyStatusResponse DTO 생성 - FeedRankingService에 getClubMonthlyStatus, getClubMonthlyStatusByClubId 추가 - GeneralFeedRankingService에 구현 (기존 getClubFeedRanking 재사용) - score=0인 동아리는 rank=0으로 반환 (미활동 동아리 구분) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ClubFeedApi에 GET /server/central/feeds/status 엔드포인트 추가 - ClubFeedController에 getFeedStatus() 구현 (PrincipalDetails → userId) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AdminFeedApi base path를 /server/admin으로 변경
- GET /server/admin/clubs/{clubId}/feeds/ranking/status 엔드포인트 추가
- AdminFeedController에 getClubMonthlyStatus() 구현 (clubId path variable)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ClubFeedStatusE2ETest: E2E 5개 시나리오 (성공/rank/동점/피드없음/미인증) - GeneralFeedRankingServiceTest: 단위 테스트 3개 추가 (피드있음/없음/rank 정확성) - UserFixture에 createClubUser(authId, encode) 오버로드 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ClubFeedController에 @validated 추가 (@Min/@max 검증 활성화) - AdminFeedControllerE2ETest에 동아리 이달의 현황 조회 E2E 테스트 2개 추가 - Admin 성공 조회 / CLUB 권한 403 검증 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Walkthrough클럽의 월별 피드 상태 조회 기능을 추가합니다. 새로운 API 엔드포인트를 통해 특정 년도와 월의 클럽 피드 통계(순위, 피드 수, 조회 수, 좋아요, 댓글, 점수)를 반환하며, Controller, Service, DTO 계층 전반에 걸쳐 구현됩니다. Changes
Sequence DiagramsequenceDiagram
participant Client
participant Controller as ClubFeedController
participant Service as FeedRankingService
participant ClubSvc as ClubService
participant Repo as Repository
participant DB as Database
Client->>Controller: GET /feeds/status?year=2025&month=2
activate Controller
Controller->>Service: getClubMonthlyStatus(userId, year, month)
activate Service
Service->>ClubSvc: getUserClub(userId)
activate ClubSvc
ClubSvc->>Repo: findClubByUser(userId)
activate Repo
Repo->>DB: Query club
DB-->>Repo: Club entity
deactivate Repo
deactivate ClubSvc
ClubSvc-->>Service: Club
Service->>Service: getClubFeedRanking(year, month)
Service->>Repo: Query feed ranking data
activate Repo
Repo->>DB: Query rankings, feeds, stats
DB-->>Repo: Results
deactivate Repo
Service->>Service: Filter for user's club with score
Service-->>Controller: ClubMonthlyStatusQuery
deactivate Service
Controller->>Controller: ClubMonthlyStatusResponse.from(query)
Controller-->>Client: HTTP 200 + JSON response
deactivate Controller
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
- ClubFeedStatusE2ETest: rank/동점/피드없음 테스트 제거 (단위 테스트에서 커버) - 남은 E2E: 성공 조회(200) + 미인증(401) 2개 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Tip For best results, initiate chat on the files or code changes.
이 PR과 관련하여 다음과 같은 도움을 드릴 수 있습니다:
무엇이 필요하신지 말씀해 주세요! 😊 |
|
리뷰해줘 |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
src/main/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingService.java (1)
73-83: 전체 랭킹을 재계산하여 단일 클럽 조회 — 성능 개선 여지 있음
getClubMonthlyStatusByClubId는 단일 클럽의 현황을 구하기 위해getClubFeedRanking(year, month)를 호출합니다. 이 메서드는 DB에서 전체 클럽 목록을 조회하고 O(N log N) 정렬 후 랭킹을 계산하는데, 최종적으로는 그 중 하나만 사용됩니다.클럽 수가 증가할 경우 불필요한 DB 부하가 생길 수 있습니다. 장기적으로는 특정 클럽의 피드 통계와 해당 클럽보다 높은 점수를 가진 클럽 수만 조회하는 전용 쿼리로 대체하는 것을 권장합니다.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingService.java` around lines 73 - 83, getClubMonthlyStatusByClubId currently calls getClubFeedRanking(year, month) which computes and sorts all clubs; replace that heavy path with targeted DB queries: in GeneralFeedRankingService.getClubMonthlyStatusByClubId, stop calling getClubFeedRanking and instead fetch only the requested club's aggregated monthly score (e.g., repository method like findClubMonthlyScoreByClubId(year, month, clubId)) and then fetch the number of clubs with a strictly higher score (e.g., repository method like countClubsWithScoreGreaterThan(year, month, score)) to compute rank; if no score exists return ClubMonthlyStatusQuery.createEmpty(year, month) and otherwise build ClubMonthlyStatusQuery.from(year, month, clubId, score, rank).src/test/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingServiceTest.java (1)
332-356:getClubMonthlyStatus_withFeeds—LocalDate.now()의존성
getClubMonthlyStatus_noFeeds는 고정된 과거 날짜(year=2000, month=1)를 사용해 다른 테스트 데이터와 격리가 잘 됩니다. 반면getClubMonthlyStatus_withFeeds도 현재 연/월 데이터를 사용하므로, 다른 테스트에서 저장한 동점(score=20) 클럽들이 존재하더라도 동점이면 rank=1이라 어서션은 통과합니다. 그러나noFeeds처럼 안전한 고정 날짜를 사용하는 방식이 더 견고하며,rankAccuracy와 동일한 전략으로 일관성을 유지할 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingServiceTest.java` around lines 332 - 356, The test getClubMonthlyStatus_withFeeds depends on LocalDate.now(), making it non-deterministic; change it to use the same fixed year/month as the other test (e.g., year=2000, month=1) and ensure the saved feeds are created with timestamps in that month by using the FeedFixture.createImageFeed overload that accepts a createdAt (or add one) when calling feedRepository.save(FeedFixture.createImageFeed(club, "피드1", createdAt)) and for "피드2", so the query for feedRankingService.getClubMonthlyStatus(user.getId(), year, month) reliably returns rank 1 and feedCount 2.src/main/java/ddingdong/ddingdongBE/domain/feed/api/AdminFeedApi.java (1)
54-58:clubId경로 변수에 양수 제약 조건 추가 고려
year와month에는@Min/@Max가 붙어 있지만clubId에는 아무 제약이 없어 0 또는 음수 값이 서비스 레이어까지 통과합니다.✨ 제안: `@Positive` 추가
- `@PathVariable`("clubId") Long clubId, + `@PathVariable`("clubId") `@Positive`(message = "clubId는 1 이상이어야 합니다.") Long clubId,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/ddingdong/ddingdongBE/domain/feed/api/AdminFeedApi.java` around lines 54 - 58, The clubId path variable in AdminFeedApi.getClubMonthlyStatus lacks validation and can pass zero/negative values; add `@Positive` (e.g., `@Positive`(message = "clubId는 양수여야 합니다.")) to the Long clubId parameter and import the corresponding javax.validation.constraints.Positive so invalid IDs are rejected before reaching the service layer.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/main/java/ddingdong/ddingdongBE/domain/feed/api/AdminFeedApi.java`:
- Around line 54-58: The clubId path variable in
AdminFeedApi.getClubMonthlyStatus lacks validation and can pass zero/negative
values; add `@Positive` (e.g., `@Positive`(message = "clubId는 양수여야 합니다.")) to the
Long clubId parameter and import the corresponding
javax.validation.constraints.Positive so invalid IDs are rejected before
reaching the service layer.
In
`@src/main/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingService.java`:
- Around line 73-83: getClubMonthlyStatusByClubId currently calls
getClubFeedRanking(year, month) which computes and sorts all clubs; replace that
heavy path with targeted DB queries: in
GeneralFeedRankingService.getClubMonthlyStatusByClubId, stop calling
getClubFeedRanking and instead fetch only the requested club's aggregated
monthly score (e.g., repository method like findClubMonthlyScoreByClubId(year,
month, clubId)) and then fetch the number of clubs with a strictly higher score
(e.g., repository method like countClubsWithScoreGreaterThan(year, month,
score)) to compute rank; if no score exists return
ClubMonthlyStatusQuery.createEmpty(year, month) and otherwise build
ClubMonthlyStatusQuery.from(year, month, clubId, score, rank).
In
`@src/test/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingServiceTest.java`:
- Around line 332-356: The test getClubMonthlyStatus_withFeeds depends on
LocalDate.now(), making it non-deterministic; change it to use the same fixed
year/month as the other test (e.g., year=2000, month=1) and ensure the saved
feeds are created with timestamps in that month by using the
FeedFixture.createImageFeed overload that accepts a createdAt (or add one) when
calling feedRepository.save(FeedFixture.createImageFeed(club, "피드1", createdAt))
and for "피드2", so the query for
feedRankingService.getClubMonthlyStatus(user.getId(), year, month) reliably
returns rank 1 and feedCount 2.
|
잠시만 기다려주세요. 🔍 ✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 Nitpick comments (4)
src/main/java/ddingdong/ddingdongBE/domain/feed/api/AdminFeedApi.java (1)
54-58:clubId에@Min(1)유효성 검증 추가를 고려하세요.
year,month에는@Min/@Max제약이 적용되어 있지만,clubId에는 없습니다. 0 이하 값이 들어올 경우 서비스 계층까지 전달되어 의미없는 DB 조회가 발생합니다.@Min(1)추가로 컨트롤러 레벨에서 400 Bad Request를 빠르게 반환할 수 있습니다.✨ clubId 유효성 검증 추가 제안
ClubMonthlyStatusResponse getClubMonthlyStatus( - `@PathVariable`("clubId") Long clubId, + `@PathVariable`("clubId") `@Min`(value = 1, message = "clubId는 1 이상이어야 합니다.") Long clubId, `@RequestParam`("year") `@Min`(value = 2000, message = "year는 2000 이상이어야 합니다.") `@Max`(value = 2100, message = "year는 2100 이하여야 합니다.") int year, `@RequestParam`("month") `@Min`(value = 1, message = "month는 1 이상이어야 합니다.") `@Max`(value = 12, message = "month는 12 이하여야 합니다.") int month );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/ddingdong/ddingdongBE/domain/feed/api/AdminFeedApi.java` around lines 54 - 58, AdminFeedApi의 getClubMonthlyStatus 메서드에서 PathVariable인 clubId에 유효성 검증이 빠져 있어 0 이하 값이 서비스로 넘어가는 문제가 있습니다; clubId 파라미터에 `@Min`(value = 1, message = "clubId는 1 이상이어야 합니다.") 어노테이션을 추가하고 필요한 경우 javax.validation.constraints.Min를 임포트해 컨트롤러 레벨에서 400 Bad Request가 반환되도록 수정하세요.src/test/java/ddingdong/ddingdongBE/domain/feed/controller/AdminFeedControllerE2ETest.java (1)
206-208: 순위 단언이 지나치게 느슨합니다.
isGreaterThan(0)은 score > 0임을 보장하지만, 다른 테스트에서 현재 월에 더 높은 score를 가진 클럽이 남아있어 rank가 2 이상이 되더라도 테스트가 통과됩니다.NonTxTestContainerSupport가 테스트 간 데이터를 정리한다면isEqualTo(1)로 강화하여 랭킹 로직 오류를 더 정확히 검출할 수 있습니다.✨ 순위 단언 개선 제안
- assertThat(((Number) response.get("rank")).intValue()).isGreaterThan(0); + assertThat(((Number) response.get("rank")).intValue()).isEqualTo(1);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/ddingdong/ddingdongBE/domain/feed/controller/AdminFeedControllerE2ETest.java` around lines 206 - 208, The rank assertion in AdminFeedControllerE2ETest is too loose: replace the assertion using response.get("rank") from isGreaterThan(0) to isEqualTo(1) so the test expects the created club to be top-ranked; update the assertion line that currently reads something like assertThat(((Number) response.get("rank")).intValue()).isGreaterThan(0) to assert equality to 1 and keep using the same response extraction logic to locate the change.src/test/java/ddingdong/ddingdongBE/domain/feed/controller/ClubFeedStatusE2ETest.java (1)
94-102:viewCount필드에 대한 검증이 누락되었습니다.응답의 다른 모든 필드(
year,month,feedCount,likeCount,commentCount,score,rank)는 검증하고 있으나,viewCount만 빠져 있습니다.🧪 제안: viewCount 검증 추가
assertSoftly(softly -> { softly.assertThat(response.get("year")).isEqualTo(year); softly.assertThat(response.get("month")).isEqualTo(month); softly.assertThat(((Number) response.get("feedCount")).longValue()).isEqualTo(2L); + softly.assertThat(((Number) response.get("viewCount")).longValue()).isEqualTo(0L); softly.assertThat(((Number) response.get("likeCount")).longValue()).isEqualTo(1L); softly.assertThat(((Number) response.get("commentCount")).longValue()).isEqualTo(1L); softly.assertThat(((Number) response.get("score")).longValue()).isEqualTo(28L); softly.assertThat(((Number) response.get("rank")).intValue()).isEqualTo(1); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/ddingdong/ddingdongBE/domain/feed/controller/ClubFeedStatusE2ETest.java` around lines 94 - 102, Add an assertion for the missing viewCount in the ClubFeedStatusE2ETest soft assertions: inside the assertSoftly block that currently asserts year, month, feedCount, likeCount, commentCount, score, and rank (using the response map), add a softly.assertThat for response.get("viewCount") converting to Number and comparing to the expected long value (same style as feedCount/likeCount assertions) so viewCount is validated alongside the other fields.src/main/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingService.java (1)
73-83: 전체 랭킹 조회 후 필터링하는 방식의 성능 참고 사항
getClubMonthlyStatusByClubId가 단일 동아리 조회를 위해getClubFeedRanking()으로 전체 동아리 랭킹을 매번 계산합니다. 현재 동아리 수 규모에서는 문제 없겠지만, 향후 동아리 수가 크게 증가하거나 해당 API 호출 빈도가 높아지면 개별 동아리 전용 쿼리 최적화를 고려해 볼 수 있습니다.또한 현재 로직에서
.filter(rankingQuery -> rankingQuery.score() > 0)조건은, 랭킹 리스트에 포함된 동아리는 최소feedCount >= 1(score >= 10)이므로 실질적으로 방어 코드 역할입니다. 의도가 명확하다면 현재 구조로 충분합니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingService.java` around lines 73 - 83, Currently getClubMonthlyStatusByClubId calls getClubFeedRanking(year, month) and then filters the full ranking list to find one club, which can be inefficient as club count grows; modify the service to use a dedicated query that fetches only the target club's monthly ranking instead of computing the whole ranking each time—either add a repository/service method like findClubFeedRankingByClubId(Long clubId, int year, int month) or overload getClubFeedRanking to accept an optional clubId and return a single ClubFeedRankingQuery; keep the existing score>0 guard and map to ClubMonthlyStatusQuery.from(...) or ClubMonthlyStatusQuery.createEmpty(...) as now.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/main/java/ddingdong/ddingdongBE/domain/feed/api/AdminFeedApi.java`:
- Around line 54-58: AdminFeedApi의 getClubMonthlyStatus 메서드에서 PathVariable인
clubId에 유효성 검증이 빠져 있어 0 이하 값이 서비스로 넘어가는 문제가 있습니다; clubId 파라미터에 `@Min`(value = 1,
message = "clubId는 1 이상이어야 합니다.") 어노테이션을 추가하고 필요한 경우
javax.validation.constraints.Min를 임포트해 컨트롤러 레벨에서 400 Bad Request가 반환되도록 수정하세요.
In
`@src/main/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingService.java`:
- Around line 73-83: Currently getClubMonthlyStatusByClubId calls
getClubFeedRanking(year, month) and then filters the full ranking list to find
one club, which can be inefficient as club count grows; modify the service to
use a dedicated query that fetches only the target club's monthly ranking
instead of computing the whole ranking each time—either add a repository/service
method like findClubFeedRankingByClubId(Long clubId, int year, int month) or
overload getClubFeedRanking to accept an optional clubId and return a single
ClubFeedRankingQuery; keep the existing score>0 guard and map to
ClubMonthlyStatusQuery.from(...) or ClubMonthlyStatusQuery.createEmpty(...) as
now.
In
`@src/test/java/ddingdong/ddingdongBE/domain/feed/controller/AdminFeedControllerE2ETest.java`:
- Around line 206-208: The rank assertion in AdminFeedControllerE2ETest is too
loose: replace the assertion using response.get("rank") from isGreaterThan(0) to
isEqualTo(1) so the test expects the created club to be top-ranked; update the
assertion line that currently reads something like assertThat(((Number)
response.get("rank")).intValue()).isGreaterThan(0) to assert equality to 1 and
keep using the same response extraction logic to locate the change.
In
`@src/test/java/ddingdong/ddingdongBE/domain/feed/controller/ClubFeedStatusE2ETest.java`:
- Around line 94-102: Add an assertion for the missing viewCount in the
ClubFeedStatusE2ETest soft assertions: inside the assertSoftly block that
currently asserts year, month, feedCount, likeCount, commentCount, score, and
rank (using the response map), add a softly.assertThat for
response.get("viewCount") converting to Number and comparing to the expected
long value (same style as feedCount/likeCount assertions) so viewCount is
validated alongside the other fields.
- AdminFeedApi에서 /clubs/{clubId}/feeds/ranking/status 엔드포인트 제거
- AdminFeedController에서 getClubMonthlyStatus 구현 제거
- FeedRankingService에서 getClubMonthlyStatusByClubId 인터페이스 메서드 제거
- GeneralFeedRankingService에서 로직을 getClubMonthlyStatus에 인라인
- AdminFeedApi 베이스 경로 /server/admin/feeds로 복원
- AdminFeedControllerE2ETest에서 관련 테스트 2개 제거
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingService.java`:
- Around line 67-78: getClubMonthlyStatus currently calls
getClubFeedRanking(year, month) which loads and sorts all clubs; instead, add
repository-level queries to fetch only the target club's monthly score and its
rank. Replace the in-memory approach in getClubMonthlyStatus (and keep using
clubService.getByUserId and ClubMonthlyStatusQuery.from/createEmpty) by calling
new feedRepository methods such as findMonthlyScoreByClubId(year, month, clubId)
to get the club's score and countClubsWithHigherScore(year, month, score) (or a
single query that returns both score and rank); then construct and return
ClubMonthlyStatusQuery.from(year, month, /* build from score+rank */) or
createEmpty when no score, avoiding getClubFeedRanking entirely. Ensure
repository/query method names match the feedRepository interface used by
GeneralFeedRankingService.
| @Override | ||
| public ClubMonthlyStatusQuery getClubMonthlyStatus(Long userId, int year, int month) { | ||
| Club club = clubService.getByUserId(userId); | ||
| List<ClubFeedRankingQuery> rankings = getClubFeedRanking(year, month); | ||
|
|
||
| return rankings.stream() | ||
| .filter(rankingQuery -> rankingQuery.clubId().equals(club.getId())) | ||
| .findFirst() | ||
| .filter(rankingQuery -> rankingQuery.score() > 0) | ||
| .map(rankingQuery -> ClubMonthlyStatusQuery.from(year, month, rankingQuery)) | ||
| .orElse(ClubMonthlyStatusQuery.createEmpty(year, month)); | ||
| } |
There was a problem hiding this comment.
전체 랭킹 조회를 통한 단일 동아리 조회 — 성능 문제
getClubMonthlyStatus가 내부적으로 getClubFeedRanking(year, month)를 호출함으로써, 단 하나의 동아리 상태를 반환하기 위해 해당 월의 모든 동아리 피드 데이터를 DB에서 fetch하고, 전체를 인메모리에서 정렬(O(n log n))한 뒤, 순위를 재계산합니다. 동아리 수(n)가 증가할수록 이 API의 응답 시간이 선형 이상으로 증가합니다.
feedRepository에 특정 동아리의 월별 피드 카운트를 직접 조회하는 쿼리를 추가하고, 순위는 해당 점수보다 높은 동아리 수를 COUNT하는 서브쿼리(또는 별도 쿼리)로 계산하는 방식으로 DB 레벨에서 처리하는 것을 권장합니다.
♻️ 개선 방향 예시 (Repository 쿼리 기반)
`@Override`
public ClubMonthlyStatusQuery getClubMonthlyStatus(Long userId, int year, int month) {
Club club = clubService.getByUserId(userId);
- List<ClubFeedRankingQuery> rankings = getClubFeedRanking(year, month);
-
- return rankings.stream()
- .filter(rankingQuery -> rankingQuery.clubId().equals(club.getId()))
- .findFirst()
- .filter(rankingQuery -> rankingQuery.score() > 0)
- .map(rankingQuery -> ClubMonthlyStatusQuery.from(year, month, rankingQuery))
- .orElse(ClubMonthlyStatusQuery.createEmpty(year, month));
+ // 1. 해당 동아리의 월별 피드 통계를 단일 쿼리로 조회
+ Optional<MonthlyFeedRankingDto> statOpt =
+ feedRepository.findMonthlyRankingByClubId(club.getId(), year, month);
+ if (statOpt.isEmpty()) {
+ return ClubMonthlyStatusQuery.createEmpty(year, month);
+ }
+ MonthlyFeedRankingDto stat = statOpt.get();
+ long score = calculateScore(stat);
+ if (score == 0) {
+ return ClubMonthlyStatusQuery.createEmpty(year, month);
+ }
+ // 2. 점수보다 높은 동아리 수를 COUNT하여 순위 계산
+ int rank = feedRepository.countClubsWithHigherScore(year, month, score) + 1;
+ return ClubMonthlyStatusQuery.from(year, month,
+ ClubFeedRankingQuery.of(rank, stat, score));
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/ddingdong/ddingdongBE/domain/feed/service/GeneralFeedRankingService.java`
around lines 67 - 78, getClubMonthlyStatus currently calls
getClubFeedRanking(year, month) which loads and sorts all clubs; instead, add
repository-level queries to fetch only the target club's monthly score and its
rank. Replace the in-memory approach in getClubMonthlyStatus (and keep using
clubService.getByUserId and ClubMonthlyStatusQuery.from/createEmpty) by calling
new feedRepository methods such as findMonthlyScoreByClubId(year, month, clubId)
to get the club's score and countClubsWithHigherScore(year, month, score) (or a
single query that returns both score and rank); then construct and return
ClubMonthlyStatusQuery.from(year, month, /* build from score+rank */) or
createEmpty when no score, avoiding getClubFeedRanking entirely. Ensure
repository/query method names match the feedRepository interface used by
GeneralFeedRankingService.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> (cherry picked from commit 0cf16f4)
🚀 작업 내용
동아리 회장이 자신의 동아리의 해당 월 피드 활동 집계와 전체 동아리 중 순위를 조회하는 API 구현
엔드포인트
/server/central/feeds/status?year=&month=응답 필드
year,month,rank,feedCount,viewCount,likeCount,commentCount,score핵심 로직
getClubFeedRanking()재사용하여 전체 랭킹 계산 후 내 동아리 필터링변경 파일
ClubMonthlyStatusQuery,ClubMonthlyStatusResponseFeedRankingService,GeneralFeedRankingService,ClubFeedApi,ClubFeedController🤔 고민했던 내용
💬 리뷰 중점사항
✅ 테스트
🤖 Generated with Claude Code
Summary by CodeRabbit
새로운 기능