-
Notifications
You must be signed in to change notification settings - Fork 3
feat: 기존 피드 조회 API 4종에 카운트 필드 추가 #388
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 4 commits
68fa532
27d64ab
9e40dc5
0fd363b
78b0fe9
e3c0fe8
ed2b9f4
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 |
|---|---|---|
|
|
@@ -7,7 +7,16 @@ | |
| import java.util.List; | ||
| import lombok.Builder; | ||
|
|
||
| @Builder | ||
| public record MyFeedPageResponse( | ||
| @Schema(description = "총 피드 수", example = "15") | ||
| long feedCount, | ||
| @Schema(description = "총 조회수", example = "1200") | ||
| long totalViewCount, | ||
| @Schema(description = "이미지 피드 수", example = "10") | ||
| long imageCount, | ||
| @Schema(description = "영상 피드 수", example = "5") | ||
| long videoCount, | ||
|
||
| @ArraySchema(schema = @Schema(name = "동아리 피드 정보", implementation = MyFeedListResponse.class)) | ||
| List<MyFeedListResponse> clubFeeds, | ||
| @Schema(name = "피드 페이지 정보", implementation = PagingResponse.class) | ||
|
|
@@ -18,8 +27,14 @@ public static MyFeedPageResponse from(MyFeedPageQuery myFeedPageQuery) { | |
| List<MyFeedListResponse> clubFeeds = myFeedPageQuery.feedListQueries().stream() | ||
| .map(MyFeedListResponse::from) | ||
| .toList(); | ||
| return new MyFeedPageResponse(clubFeeds, | ||
| PagingResponse.from(myFeedPageQuery.pagingQuery())); | ||
| return MyFeedPageResponse.builder() | ||
| .feedCount(myFeedPageQuery.feedCount()) | ||
| .totalViewCount(myFeedPageQuery.totalViewCount()) | ||
| .imageCount(myFeedPageQuery.imageCount()) | ||
| .videoCount(myFeedPageQuery.videoCount()) | ||
| .clubFeeds(clubFeeds) | ||
| .pagingInfo(PagingResponse.from(myFeedPageQuery.pagingQuery())) | ||
| .build(); | ||
| } | ||
|
|
||
| @Builder | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package ddingdong.ddingdongBE.domain.feed.repository.dto; | ||
|
|
||
| public interface FeedCountDto { | ||
|
|
||
| Long getFeedId(); | ||
|
|
||
| Long getCnt(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package ddingdong.ddingdongBE.domain.feed.repository.dto; | ||
|
|
||
| public interface MyFeedStatDto { | ||
|
|
||
| Long getFeedCount(); | ||
|
|
||
| Long getTotalViewCount(); | ||
|
|
||
| Long getImageCount(); | ||
|
|
||
| Long getVideoCount(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,8 @@ | |
| import ddingdong.ddingdongBE.domain.club.entity.Club; | ||
| import ddingdong.ddingdongBE.domain.club.service.ClubService; | ||
| import ddingdong.ddingdongBE.domain.feed.entity.Feed; | ||
| import ddingdong.ddingdongBE.domain.feed.repository.FeedRepository; | ||
| import ddingdong.ddingdongBE.domain.feed.repository.dto.MyFeedStatDto; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.command.CreateFeedCommand; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.command.UpdateFeedCommand; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.query.FeedListQuery; | ||
|
|
@@ -17,6 +19,7 @@ | |
| import ddingdong.ddingdongBE.sse.service.dto.SseEvent; | ||
| import ddingdong.ddingdongBE.sse.service.dto.SseVodProcessingNotificationDto; | ||
| import java.time.LocalDateTime; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
|
|
@@ -36,6 +39,7 @@ public class FacadeClubFeedServiceImpl implements FacadeClubFeedService { | |
| private final VodProcessingJobService vodProcessingJobService; | ||
| private final SseConnectionService sseConnectionService; | ||
| private final FeedFileService feedFileService; | ||
| private final FeedRepository feedRepository; | ||
|
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 | 🟠 Major
🤖 Prompt for AI Agents |
||
|
|
||
| @Override | ||
| @Transactional | ||
|
|
@@ -74,17 +78,18 @@ public void delete(Long feedId) { | |
| @Override | ||
| public MyFeedPageQuery getMyFeedPage(User user, int size, Long currentCursorId) { | ||
| Club club = clubService.getByUserId(user.getId()); | ||
| MyFeedStatDto stat = feedRepository.findMyFeedStat(club.getId()); | ||
| Slice<Feed> feedPage = feedService.getFeedPageByClubId(club.getId(), size, currentCursorId); | ||
| if (feedPage == null) { | ||
| return MyFeedPageQuery.createEmpty(); | ||
| return MyFeedPageQuery.of(stat, Collections.emptyList(), PagingQuery.createEmpty()); | ||
| } | ||
| List<Feed> completeFeeds = feedPage.getContent(); | ||
| List<FeedListQuery> feedListQueries = completeFeeds.stream() | ||
| .map(feedFileService::extractFeedThumbnailInfo) | ||
| .toList(); | ||
| PagingQuery pagingQuery = PagingQuery.of(currentCursorId, completeFeeds, feedPage.hasNext()); | ||
|
|
||
| return MyFeedPageQuery.of(feedListQueries, pagingQuery); | ||
| return MyFeedPageQuery.of(stat, feedListQueries, pagingQuery); | ||
| } | ||
|
|
||
| private void checkVodProcessingJobAndNotify(Feed feed) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,21 @@ | ||
| package ddingdong.ddingdongBE.domain.feed.service; | ||
|
|
||
| import ddingdong.ddingdongBE.domain.feed.entity.Feed; | ||
| import ddingdong.ddingdongBE.domain.feed.repository.FeedCommentRepository; | ||
| import ddingdong.ddingdongBE.domain.feed.repository.FeedLikeRepository; | ||
| import ddingdong.ddingdongBE.domain.feed.repository.dto.FeedCountDto; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.query.ClubFeedPageQuery; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.query.ClubProfileQuery; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.query.FeedCommentQuery; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.query.FeedFileInfoQuery; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.query.FeedListQuery; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.query.FeedQuery; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.query.FeedPageQuery; | ||
| import ddingdong.ddingdongBE.domain.feed.service.dto.query.PagingQuery; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.stream.Collectors; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.data.domain.Slice; | ||
| import org.springframework.stereotype.Service; | ||
|
|
@@ -21,16 +28,18 @@ public class FacadeFeedService { | |
|
|
||
| private final FeedService feedService; | ||
| private final FeedFileService feedFileService; | ||
| private final FeedLikeService feedLikeService; | ||
| private final FeedCommentService feedCommentService; | ||
| private final FeedLikeRepository feedLikeRepository; | ||
| private final FeedCommentRepository feedCommentRepository; | ||
|
Comment on lines
+33
to
+34
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 | 🟠 Major Facade에서 Repository 직접 의존은 DDD 레이어링 위반입니다.
벌크 카운트 메서드( ♻️ 제안 public class FacadeFeedService {
private final FeedService feedService;
private final FeedFileService feedFileService;
private final FeedLikeService feedLikeService;
private final FeedCommentService feedCommentService;
- private final FeedLikeRepository feedLikeRepository;
- private final FeedCommentRepository feedCommentRepository;그리고 // FeedLikeService
List<FeedCountDto> countsByFeedIds(List<Long> feedIds);
// FeedCommentService
List<FeedCountDto> countsByFeedIds(List<Long> feedIds);🤖 Prompt for AI Agents |
||
|
|
||
| public ClubFeedPageQuery getFeedPageByClub(Long clubId, int size, Long currentCursorId) { | ||
| Slice<Feed> feedPage = feedService.getFeedPageByClubId(clubId, size, currentCursorId); | ||
| if (feedPage == null) { | ||
| return ClubFeedPageQuery.createEmpty(); | ||
| } | ||
| List<Feed> completeFeeds = feedPage.getContent(); | ||
| List<FeedListQuery> feedListQueries = completeFeeds.stream() | ||
| .map(feedFileService::extractFeedThumbnailInfo) | ||
| .toList(); | ||
| List<FeedListQuery> feedListQueries = buildFeedListQueriesWithCounts(completeFeeds); | ||
| PagingQuery pagingQuery = PagingQuery.of(currentCursorId, completeFeeds, feedPage.hasNext()); | ||
|
|
||
| return ClubFeedPageQuery.of(feedListQueries, pagingQuery); | ||
|
|
@@ -42,9 +51,7 @@ public FeedPageQuery getAllFeedPage(int size, Long currentCursorId) { | |
| return FeedPageQuery.createEmpty(); | ||
| } | ||
| List<Feed> completeFeeds = feedPage.getContent(); | ||
|
|
||
| List<FeedListQuery> feedListQueries = completeFeeds.stream().map(feedFileService::extractFeedThumbnailInfo) | ||
| .toList(); | ||
| List<FeedListQuery> feedListQueries = buildFeedListQueriesWithCounts(completeFeeds); | ||
| PagingQuery pagingQuery = PagingQuery.of(currentCursorId, completeFeeds, feedPage.hasNext()); | ||
|
|
||
| return FeedPageQuery.of(feedListQueries, pagingQuery); | ||
|
|
@@ -56,7 +63,39 @@ public FeedQuery getById(Long feedId) { | |
| Feed feed = feedService.getById(feedId); | ||
| ClubProfileQuery clubProfileQuery = feedFileService.extractClubInfo(feed.getClub()); | ||
| FeedFileInfoQuery feedFileInfoQuery = feedFileService.extractFeedFileInfo(feed); | ||
| return FeedQuery.of(feed, clubProfileQuery, feedFileInfoQuery); | ||
| long likeCount = feedLikeService.countByFeedId(feedId); | ||
| long commentCount = feedCommentService.countByFeedId(feedId); | ||
| List<FeedCommentQuery> comments = feedCommentService.getAllByFeedId(feedId); | ||
| return FeedQuery.of(feed, clubProfileQuery, feedFileInfoQuery, likeCount, commentCount, comments); | ||
| } | ||
|
|
||
| private List<FeedListQuery> buildFeedListQueriesWithCounts(List<Feed> feeds) { | ||
| List<FeedListQuery> feedListQueries = feeds.stream() | ||
| .map(feedFileService::extractFeedThumbnailInfo) | ||
| .toList(); | ||
|
|
||
| List<Long> feedIds = feeds.stream().map(Feed::getId).toList(); | ||
| if (feedIds.isEmpty()) { | ||
| return feedListQueries; | ||
| } | ||
|
|
||
| Map<Long, Long> likeCountMap = feedLikeRepository.countsByFeedIds(feedIds).stream() | ||
| .collect(Collectors.toMap(FeedCountDto::getFeedId, FeedCountDto::getCnt)); | ||
| Map<Long, Long> commentCountMap = feedCommentRepository.countsByFeedIds(feedIds).stream() | ||
| .collect(Collectors.toMap(FeedCountDto::getFeedId, FeedCountDto::getCnt)); | ||
|
|
||
| return feedListQueries.stream() | ||
| .map(q -> FeedListQuery.builder() | ||
| .id(q.id()) | ||
| .thumbnailCdnUrl(q.thumbnailCdnUrl()) | ||
| .thumbnailOriginUrl(q.thumbnailOriginUrl()) | ||
| .feedType(q.feedType()) | ||
| .thumbnailFileName(q.thumbnailFileName()) | ||
| .viewCount(q.viewCount()) | ||
| .likeCount(likeCountMap.getOrDefault(q.id(), 0L)) | ||
| .commentCount(commentCountMap.getOrDefault(q.id(), 0L)) | ||
| .build()) | ||
| .toList(); | ||
| } | ||
|
|
||
| } | ||
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.
현 api 명세에 해당 필드는 제거해도 될 것 같아