refactor: 피드 조회 api dto 수정#79
Hidden character warning
Conversation
Walkthrough피드 응답 DTO를 단일 형태(FeedResponse)로 추가하고 Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Client
participant Controller as FeedController
participant Service as FeedService
participant DiaryRepo as DiaryRepository
participant AvatarRepo as AvatarPostRepository
Client->>Controller: GET /feed?filter=...&page=...&size=...
Controller->>Service: getFeed(userUuid, filter, page, size)
alt following filter
Service->>DiaryRepo: findDiariesOfFollowing(candidatePageable, excludeBlocked)
DiaryRepo-->>Service: List<Diary>
Service->>AvatarRepo: findAvatarPostsOfFollowing(candidatePageable, excludeBlocked)
AvatarRepo-->>Service: List<AvatarPost>
else all/non-following
Service->>DiaryRepo: findDiaries(candidatePageable, excludeBlocked)
DiaryRepo-->>Service: List<Diary>
Service->>AvatarRepo: findAvatarPosts(candidatePageable, excludeBlocked)
AvatarRepo-->>Service: List<AvatarPost>
end
Service->>Service: map to FeedResponse (from)
Service->>Service: merge streams & sort by createdAt desc
Service->>Service: slice (start=page*size, end=min(start+size,total))
Service-->>Controller: List<FeedResponse>
Controller-->>Client: 200 OK ApiResponse<List<FeedResponse>>
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (14)
src/main/java/com/example/cp_main_be/domain/social/feed/dto/response/PostType.java (1)
3-6: 네이밍/위치 소폭 제안:AVATAR_POSTvsAVATAR, 패키지 레이어링
- 향후 아바타 관련 포스트 외 타입이 늘 경우,
AVATAR_POST보다AVATAR가 더 일반적일 수 있습니다.- 응답 DTO 패키지(
dto.response)에 enum 이 위치하면 재사용 범위가 DTO 레이어로 한정됩니다. 도메인 전역에서 참조될 가능성이 있으면 공용 패키지(예:domain.social.feed.model또는domain.common)로 이동을 고려해도 좋습니다.src/main/java/com/example/cp_main_be/domain/social/feed/dto/response/FeedResponse.java (2)
12-14:createdAt에@JsonIgnore적용 — 페이징/정렬 확장성 관점 점검 필요현재는 서버 측에서만 정렬/슬라이싱하므로 문제는 없지만, 추후 클라이언트 측 무한스크롤(커서 기반) 또는 정합성 검증(“다음 페이지 유효성”)이 필요하면
createdAt또는 별도cursor값이 응답에 포함되어야 합니다. 최소한 스펙에 "클라이언트로는 createdAt 미노출"임을 명시하거나,cursor필드 도입을 고려해주세요.
15-18: 이미지 매핑 NPE 방어는 OK — 다중 이미지/썸네일 정책 확인 권장
diary.getDiaryImage()단건 기준 매핑은 깔끔합니다. 다만 다중 이미지가 허용되는 모델이라면 대표 이미지(썸네일) 선택 규칙이 필요할 수 있습니다. 현 모델이 단건 보장인지 확인 부탁드립니다.src/main/java/com/example/cp_main_be/domain/social/feed/presentation/FeedController.java (4)
28-33: 페이지 파라미터 검증 추가 제안(DoS/메모리 급증 방지)
size무제한/대형 값 요청을 차단하기 위해 Bean Validation을 붙이는 것을 권장합니다(예:size <= 100).
아래처럼 컨트롤러 파라미터에 직접 부착하면 간단합니다.- public ResponseEntity<ApiResponse<List<FeedResponse>>> getFeed( + public ResponseEntity<ApiResponse<List<FeedResponse>>> getFeed( @AuthenticationPrincipal User user, // 인증된 사용자 정보 - @RequestParam(required = false) String filter, - @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "20") int size) { + @RequestParam(required = false) String filter, + @RequestParam(defaultValue = "0") @jakarta.validation.constraints.PositiveOrZero int page, + @RequestParam(defaultValue = "20") @jakarta.validation.constraints.Positive @jakarta.validation.constraints.Max(100) int size) {추가로, 아래 import가 필요합니다(파일 상단):
+import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero;
35-35: 인증 컨텍스트 가정 확인
@AuthenticationPrincipal User user가 null 일 수 있는 경로(익명 접근)가 완전히 차단되어 있는지 확인 부탁드립니다. 미보장 시user.getUuid()에서 NPE 발생합니다. 시큐리티 설정으로 엔드포인트 보호 또는 널 가드/401 응답 처리를 권장합니다.
37-37: 주석 타입 명시 오탈자주석의
FeedItemResponse는 현재 타입과 불일치합니다.FeedResponse로 교정해주세요.- // List<Object>가 아닌 List<FeedItemResponse>로 응답 타입을 명확히 합니다. + // List<Object>가 아닌 List<FeedResponse>로 응답 타입을 명확히 합니다.
26-27: API 문서화에 필터 값/기본값 명시 권장
filter가"following"만 특별 취급됨을 스펙에 명시하고, 가능한 값(예:following|all)을 OpenAPI@Operation/@Parameter로 표시하면 클라이언트 통합이 수월합니다.src/main/java/com/example/cp_main_be/domain/social/feed/service/FeedService.java (7)
35-41: (성능) 소스별(page+1)*size후보 수집은 안전하지만 상한선 필요딥 페이지네이션 시 두 소스에서 2배 데이터를 메모리에 적재합니다. 컨트롤러 단
size상한(+ 서버 프로퍼티로 튜너블) 적용을 권장합니다. 추후 트래픽 증가 시 커서 기반(Keyset)으로의 전환을 고려해 주세요.
49-50: 차단 정책 보강 제안: ‘내가 차단한 유저’뿐 아니라 ‘나를 차단한 유저’도 배제현재는
blockedUserIdsByBlocker(currentUser)만 제외합니다. 일반적인 블록 의미론(양방향 차단)이라면 “나를 차단한 유저”도 제외해야 합니다. 리포지토리 메서드가 있다면 병합해 주세요.
54-57: 팔로잉 필터에서 ‘자기 자신’ 포함 여부 확인일반적으로 팔로잉 피드에는 자신의 포스트도 함께 보이는 경우가 많습니다. 현재 구현은
followingUsers만 포함하므로 자기 자신 게시물이 제외됩니다. 요구사항에 맞는지 확인 바랍니다.
83-87: 동일 시각 게시물의 결정적 정렬 보장
createdAt동일 시 타이브레이커가 없어 페이지 경계에서 불안정할 수 있습니다.postId(또는 소스+ID)로 2차 정렬을 추가해 결정성을 높이세요.- .sorted(Comparator.comparing(FeedResponse::createdAt).reversed()) + .sorted( + Comparator.<FeedResponse, java.time.LocalDateTime>comparing(FeedResponse::createdAt) + .reversed() + .thenComparing(Comparator.comparing(FeedResponse::postId).reversed()))
35-97: 테스트 커버리지 제안다음 케이스 단위/통합 테스트를 추가하면 회귀 방지에 유효합니다.
- 팔로잉/전체 모드 각각에서 차단된 유저의 포스트 미포함 검증
page/size경계값(0, 1, 최대치) 및 범위 초과 시 빈 리스트 반환createdAt동일한 아이템의 결정적 정렬(타이브레이커 적용 후)- Diary 이미지 null/존재 케이스 매핑 결과
filter미지정/대소문자 혼용(following,Following) 동작
35-41: 추가 아키텍처 제안: 커서(키셋) 기반 통합 정렬현재는 소스별 페이지블 + 메모리 병합 정렬 구조입니다. 트래픽 규모가 커지면 DB 레벨에서 “소스 통합 뷰(UNION ALL) + 인덱스(created_at, user_id, is_public)” 또는 커서 기반(최신
createdAt, id) 페이징이 유리합니다. 중장기 로드맵에 반영을 권장합니다.
58-69: 파생 쿼리 메서드 존재 확인 및 JDK 설정
- 아래 4가지 파생 메서드는 DiaryRepository·AvatarPostRepository에 모두 정상으로 선언되어 있습니다.
- Gradle toolchain에서 Java 17(
languageVersion = JavaLanguageVersion.of(17))을 사용 중임을 확인했습니다.다만, JPA의
NotIn연산에 빈 컬렉션을 넘겼을 때 DB 벤더(MySQL, PostgreSQL 등) 및 JPA 구현체(Hibernate 등)마다
- 전체 반환
- 예외 발생
로 동작이 달라질 수 있으므로,
blockedUserIds가 빈 리스트일 경우에는
- 별도 분기 처리해 쿼리를 생략하거나
NotIn대신 다른 쿼리(예:In+ 전체 제외 등)
방안을 검토하실 것을 권장드립니다.적용 위치:
- src/main/java/com/example/cp_main_be/domain/social/feed/service/FeedService.java (58–69, 74–81)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
src/main/java/com/example/cp_main_be/domain/social/feed/dto/response/FeedResponse.java(1 hunks)src/main/java/com/example/cp_main_be/domain/social/feed/dto/response/PostType.java(1 hunks)src/main/java/com/example/cp_main_be/domain/social/feed/presentation/FeedController.java(2 hunks)src/main/java/com/example/cp_main_be/domain/social/feed/service/FeedService.java(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/com/example/cp_main_be/domain/social/feed/service/FeedService.java (1)
src/main/java/com/example/cp_main_be/global/exception/UserNotFoundException.java (1)
UserNotFoundException(3-7)
🔇 Additional comments (2)
src/main/java/com/example/cp_main_be/domain/social/feed/dto/response/PostType.java (1)
3-6: Enum 추가 적절 — 단일 피드 타입 식별자 도입은 👍피드 통합에 필요한 최소한의 타입만 노출되어 단순하고 명확합니다.
src/main/java/com/example/cp_main_be/domain/social/feed/service/FeedService.java (1)
90-97: JDK 버전 호환성 확인:Stream#toList()+subList
Stream.toList()는 JDK 16+ 필요합니다. 현재 빌드 타깃이 JDK 17(스프링 부트 3.x 권장)이라면 OK입니다. 또한toList()결과는 불변 리스트이지만subList는 읽기 전용 뷰를 반환하므로 사용 자체는 문제 없습니다. 빌드 JDK 버전만 확인해 주세요.
| public static FeedResponse from(AvatarPost avatarPost) { | ||
| // AvatarPost에 imageUrl 필드가 있다고 가정합니다. 필드명은 실제 코드에 맞게 수정해주세요. | ||
| return new FeedResponse( | ||
| avatarPost.getId(), | ||
| PostType.AVATAR_POST, | ||
| avatarPost.getImageUrl(), | ||
| avatarPost.getCreatedAt()); | ||
| } |
There was a problem hiding this comment.
컴파일 리스크: AvatarPost#getImageUrl() 존재 가정 주석
주석대로 실제 필드/메서드명이 다르면 컴파일 실패합니다. 해당 엔터티의 정확한 접근자에 맞춰 즉시 수정이 필요합니다. 주석은 제거하시고, 불확실하면 Mapper 계층으로 위임하는 것도 방법입니다.
가능하면 AvatarPost 엔티티 시그니처 공유해 주시면 정확한 매핑 코드로 패치 드리겠습니다.
🤖 Prompt for AI Agents
In
src/main/java/com/example/cp_main_be/domain/social/feed/dto/response/FeedResponse.java
around lines 20-27, remove the placeholder comment and replace the assumed
avatarPost.getImageUrl() call with the actual accessor for the AvatarPost entity
(e.g., getImage(), getImagePath(), getThumbnailUrl, etc.) or call a dedicated
mapper method (e.g., AvatarPostMapper.toFeedResponse(avatarPost)) if the field
name is uncertain; update the constructor arguments accordingly so the code
compiles, and if you cannot confirm the entity signature, add a TODO to delegate
mapping to a mapper and create that mapper to read the correct field.
| import com.example.cp_main_be.domain.social.diary.domain.Diary; | ||
| import com.example.cp_main_be.domain.social.diary.domain.Repository.DiaryRepository; | ||
| import com.example.cp_main_be.domain.social.diary.dto.response.DiaryFeedItemResponse; | ||
| import com.example.cp_main_be.domain.social.feed.dto.response.FeedResponse; |
There was a problem hiding this comment.
컴파일 오류 가능: DiaryRepository 패키지 경로 오타 의심
다른 리포지토리와 달리 domain.social.diary.domain.Repository.DiaryRepository 처럼 대문자 Repository 를 사용하고 있습니다. 일반적으로는 ...domain.social.diary.domain.repository.DiaryRepository 입니다. 아래처럼 수정해주세요.
-import com.example.cp_main_be.domain.social.diary.domain.Repository.DiaryRepository;
+import com.example.cp_main_be.domain.social.diary.domain.repository.DiaryRepository;🤖 Prompt for AI Agents
In
src/main/java/com/example/cp_main_be/domain/social/feed/service/FeedService.java
around line 8, the import for DiaryRepository likely uses an incorrect package
segment with capital "Repository"; change the import to use the lowercase
package path
(com.example.cp_main_be.domain.social.diary.domain.repository.DiaryRepository),
verify the target package and class name exist, and update any other references
if necessary so the project compiles.
* ddd * refactor: 피드 조회 api dto 수정 (#79) * refactor: 피드 조회 api dto 수정 * spotless apply * spotless apply * spotless apply * spotless apply * ddd --------- Co-authored-by: 이태경 <161710171+xoruddl@users.noreply.github.com>
📝 개요
피드 조회 dto 수정
💻 작업 내용
이번 PR에서 작업한 내용을 상세히 설명해 주세요.
작업 내용 1
작업 내용 2
...
✅ PR 체크리스트
PR을 보내기 전에 아래 체크리스트를 확인해 주세요.
커밋 메시지는 포맷에 맞게 작성했나요?
스스로 코드를 다시 한번 검토했나요?
관련 이슈를 연결했나요?
빌드 및 테스트가 로컬에서 성공했나요?
🔗 관련 이슈
이번 PR과 관련된 이슈 번호를 기재해 주세요. 예: Closes #75
스크린샷 (선택)
UI 변경 사항이 있다면 스크린샷을 첨부해 주세요.
Summary by CodeRabbit