[FEAT] 카드뉴스 피드 조회#350
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new query and logic to fetch and map CARDNEWS feeds from specific source types (POLICY and CONTEST) that have associated card news images. Feedback focuses on improving the JPQL query by using IS NOT EMPTY instead of an exists subquery, and refactoring the DTO mapping logic in CommunityQueryServiceImpl to avoid redundant stream mapping and improve maintainability.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| and exists ( | ||
| select 1 | ||
| from CardnewsImageS3 ci | ||
| where ci.community = c | ||
| ) |
There was a problem hiding this comment.
| if (tab == CommunityTab.CARDNEWS) { | ||
| content = content.stream() | ||
| .map(item -> new CommunityFeedItemResDTO( | ||
| CommunityType.CARDNEWS, | ||
| item.communityId(), | ||
| item.pinId(), | ||
| item.title(), | ||
| item.content(), | ||
| item.thumbnailUrl(), | ||
| item.writerNickname(), | ||
| item.writerProfileUrl(), | ||
| item.detailAddress(), | ||
| item.viewCount(), | ||
| item.likeCount(), | ||
| item.discount(), | ||
| item.eventStartTime(), | ||
| item.eventEndTime() | ||
| )) | ||
| .toList(); | ||
| } |
There was a problem hiding this comment.
현재 tab == CommunityTab.CARDNEWS일 때, 이미 생성된 CommunityFeedItemResDTO 리스트를 다시 스트림으로 순회하며 모든 필드를 복사하고 kind만 CARDNEWS로 변경하고 있습니다. 이 방식은 다음과 같은 문제가 있습니다:
- 유지보수성 저하:
CommunityFeedItemResDTO에 새로운 필드가 추가되거나 기존 필드가 변경될 때, 14개의 인자를 가진 생성자를 호출하는 이 코드도 함께 수정해야 하므로 변경에 취약합니다. - 불필요한 객체 생성: 리스트를 두 번 매핑하면서 불필요한 DTO 객체들이 추가로 생성됩니다.
개선 제안:
toFeedItems 메서드가 CommunityType 오버라이드를 지원하도록 오버로딩하여, 처음부터 원하는 타입으로 DTO를 생성하도록 리팩토링하는 것을 권장합니다.
이를 위해 CommunityQueryServiceImpl 클래스 내부의 toFeedItems 및 toFeedItem 메서드를 다음과 같이 수정해 주세요:
private List<CommunityFeedItemResDTO> toFeedItems(List<Community> communities) {
return toFeedItems(communities, null);
}
private List<CommunityFeedItemResDTO> toFeedItems(List<Community> communities, CommunityType typeOverride) {
FeedItemContext context = buildFeedItemContext(communities);
return communities.stream()
.map(community -> toFeedItem(community, context, typeOverride))
.toList();
}
private CommunityFeedItemResDTO toFeedItem(Community community, FeedItemContext context, CommunityType typeOverride) {
Pin pin = community.getPin();
CommunityType type = typeOverride != null ? typeOverride : community.getCommunityType();
Long pinId = pin.getPinId();
EventPin eventPin = context.eventPinByPinId().get(pinId);
return new CommunityFeedItemResDTO(
type,
community.getCommunityId(),
pinId,
pin.getPinTitle(),
pin.getPinContent(),
resolveFeedThumbnailUrl(community, context).orElse(null),
resolveFeedWriterNickname(community.getCommunityType(), pin, eventPin, context),
resolveFeedWriterProfileUrl(community.getCommunityType(), pin, eventPin, context),
context.addressByPinId().get(pinId),
pin.getViewCount(),
pin.getLikeCount(),
eventPin != null ? eventPin.getDiscount() : null,
eventPin != null ? eventPin.getEventStartTime() : null,
eventPin != null ? eventPin.getEventEndTime() : null
);
} if (tab == CommunityTab.CARDNEWS) {
content = toFeedItems(pageItems, CommunityType.CARDNEWS);
}
🔗 Related Issue
✨ 작업 개요
체크리스트
📷 이미지 첨부 (선택)
🧐 집중 리뷰 요청