-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat] 내가 올린 스트리 조회 API 구현 #171
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
Conversation
Walkthrough내가 올린 스트리 조회를 위한 신규 엔드포인트(GET /api/stories/member)와 응답 DTO(StoriesInMemberResponse, StoryInMemberResponse)를 추가하고, 서비스·레포지토리 계층에 회원별 페이지네이션 조회를 구현했다. 컨트롤러들에 @validated가 적용되었고, 테스트 및 문서화가 이에 맞게 보강되었다. Changes
Sequence Diagram(s)sequenceDiagram
participant C as Client
participant SC as StoryController
participant SS as StoryService
participant SR as StoryRepository
participant DB as Database
C->>SC: GET /api/stories/member?page&size (Authorization)
SC->>SS: getPagedStoryByMemberId(memberId, page, size)
SS->>SR: findAllByMemberIdOrderByCreatedAtDesc(memberId, Pageable)
SR->>DB: Query stories by memberId (paged, desc)
DB-->>SR: List<Story>
SR-->>SS: List<Story>
SS-->>SC: StoriesInMemberResponse
SC-->>C: 200 OK + JSON
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ 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
Status, Documentation and Community
|
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.
Actionable comments posted: 1
🧹 Nitpick comments (10)
src/main/java/eatda/controller/story/StoryInMemberResponse.java (1)
3-3: NPE 방지: 편의 생성자에서 story null 체크 추가 제안
story가 null인 경우 즉시 NPE가 발생합니다. 방어적으로 null을 명시적으로 검증해두면 문제를 빨리 드러내고 디버깅에 도움이 됩니다.적용 제안(diff):
package eatda.controller.story; import eatda.domain.story.Story; +import java.util.Objects; public record StoryInMemberResponse( Long id, String imageUrl, String storeName ) { public StoryInMemberResponse(Story story, String imageUrl) { - this(story.getId(), imageUrl, story.getStoreName()); + this(Objects.requireNonNull(story, "story must not be null").getId(), + imageUrl, + story.getStoreName()); } }Also applies to: 11-13
src/main/java/eatda/controller/story/StoriesInMemberResponse.java (1)
5-6: 응답 불변성 강화를 위한 List 방어적 복사 제안호출자가
stories리스트를 변경할 수 없도록 불변성을 보장하면 예측 가능성이 높아집니다.적용 제안(diff):
public record StoriesInMemberResponse(List<StoryInMemberResponse> stories) { + public StoriesInMemberResponse { + // JDK 10+ : 불변 리스트로 방어적 복사 + stories = List.copyOf(stories); + } }JDK 8/9를 사용한다면 아래 대안도 고려 가능합니다(참고용):
public StoriesInMemberResponse { stories = Collections.unmodifiableList(new ArrayList<>(stories)); }src/main/java/eatda/controller/story/StoryController.java (1)
64-65: 사소한 개선:ResponseEntity.ok(...)사용으로 간결화동일한 의미이므로 더 간결한 형태를 권장합니다.
적용 제안(diff):
- return ResponseEntity.status(HttpStatus.OK) - .body(response); + return ResponseEntity.ok(response);src/test/java/eatda/service/story/StoryServiceTest.java (1)
273-319: 추가 케이스 제안: 타 회원 스토리 배제·범위 밖 페이지기능은 충분히 검증되지만, 아래 보완 테스트를 고려해보세요.
- 타 회원의 스토리가 섞여 있는 경우에도 지정 회원의 스토리만 반환되는지 확인
- 총 페이지 수를 초과하는 page 요청 시 빈 목록을 반환하는지 확인
원하시면 위 두 케이스를 포함한 테스트 메서드를 바로 추가해드릴게요.
src/main/java/eatda/service/story/StoryService.java (2)
63-69: Stream 매핑 구현 간결하고 명확함 + Projection 고려 여지현재 구현은 명확하고 충분히 읽기 좋습니다. 다만 트래픽/데이터량이 커질 경우, 리스트 엔드포인트에서 엔티티 전체를 로딩하기보다 JPA 인터페이스 기반 Projection(예: id, imageKey만)으로 조회한 후 URL 변환을 하는 방식이 성능에 유리할 수 있습니다.
원하시면 Story의 요약 Projection을 정의하고 Repository 메서드를 Projection으로 반환하도록 시그니처를 제안드릴 수 있습니다.
106-115: 회원별 페이지네이션 조회 구현 LGTM + 인덱스 권장구현과 응답 매핑이 요구사항에 부합합니다. 성능 측면에서 아래 개선을 고려해 주세요.
- DB 인덱스: WHERE member_id = ? AND ORDER BY created_at DESC 패턴을 위해 (member_id, created_at DESC) 복합 인덱스 추가 추천
- 네이밍: 반환 타입이 Page가 아닌 List wrapper이므로 메서드명에서 “Paged”를 빼는 것도 고려 가능 (선택 사항)
예시 (마이그레이션):
- Flyway: Vxxx__add_index_story_member_created_at.sql
CREATE INDEX idx_story_member_created_at_desc ON story (member_id, created_at DESC);원하시면 Flyway 마이그레이션 스크립트 템플릿을 생성해드릴게요.
src/main/java/eatda/repository/story/StoryRepository.java (1)
13-16: 새 쿼리 메서드 및 EntityGraph 적용 적절
- findAllByMemberIdOrderByCreatedAtDesc: 서비스 요구사항과 일치합니다.
- @entitygraph(member): 카카오ID 기반 상세 리스트에서 member 정보를 즉시 로딩해 N+1을 회피할 수 있어 적절합니다.
추가로, memberId + createdAt DESC 복합 인덱스를 DB에 추가하면 페이지네이션 성능을 더 확보할 수 있습니다.
src/test/java/eatda/document/story/StoryDocumentTest.java (1)
253-259: 응답 필드 네이밍 일관성 검토 제안회원별 목록에서 story id 필드를 stories[].id로, 다른 엔드포인트(예: 프리뷰/카카오ID)에서는 stories[].storyId를 사용합니다. 의도된 차별화라면 그대로 유지해도 되지만, 클라이언트 입장에서 동일 개념의 필드명이 통일되면 사용성이 좋아집니다.
이 네이밍 차이가 의도된 것인지 확인 부탁드립니다. 의도되었다면, API 문서에 차이를 명시해 두는 것도 방법입니다.
src/test/java/eatda/controller/story/StoryControllerTest.java (2)
16-16: HttpHeaders 상수 일관 사용 제안HttpHeaders.AUTHORIZATION를 임포트하셨으니, 본 파일 내 다른 테스트에서도 문자열 리터럴 "Authorization" 대신 상수를 통일해 쓰면 가독성과 오타 방지가 좋아집니다.
예: header(HttpHeaders.AUTHORIZATION, accessToken())
140-171: 중첩 클래스 구조 평탄화 제안GetStoriesByKakaoId가 GetStoriesByMemberId 내부에 중첩되어 있습니다. 기능 도메인이 다른 테스트 스위트는 동일 계층으로 두면 네이밍/탐색성이 좋아집니다.
원하시면 중첩 해제한 구조로 리팩터 제안 드릴게요.
📜 Review details
Configuration used: .coderabbit.yaml
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 (10)
src/main/java/eatda/controller/story/StoriesInMemberResponse.java(1 hunks)src/main/java/eatda/controller/story/StoryController.java(1 hunks)src/main/java/eatda/controller/story/StoryInMemberResponse.java(1 hunks)src/main/java/eatda/repository/story/StoryRepository.java(1 hunks)src/main/java/eatda/service/story/StoryService.java(3 hunks)src/test/java/eatda/controller/BaseControllerTest.java(1 hunks)src/test/java/eatda/controller/story/StoryControllerTest.java(2 hunks)src/test/java/eatda/document/story/StoryDocumentTest.java(3 hunks)src/test/java/eatda/service/BaseServiceTest.java(2 hunks)src/test/java/eatda/service/story/StoryServiceTest.java(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/test/java/eatda/service/story/StoryServiceTest.java (1)
src/test/java/eatda/document/story/StoryDocumentTest.java (5)
Nested(45-123)Nested(125-163)Nested(165-237)Nested(239-307)Nested(309-371)
src/test/java/eatda/controller/story/StoryControllerTest.java (1)
src/test/java/eatda/document/story/StoryDocumentTest.java (5)
Nested(45-123)Nested(125-163)Nested(165-237)Nested(239-307)Nested(309-371)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (11)
src/test/java/eatda/controller/BaseControllerTest.java (1)
136-138: 테스트 편의 메서드 추가 LGTM특정 멤버로 토큰 발급이 필요한 테스트 시나리오에 유용합니다. 단순·명확하며 기존 흐름과도 일관적입니다.
src/test/java/eatda/service/BaseServiceTest.java (1)
13-13: 스토리 픽스처 주입 LGTM
StoryGenerator주입으로 서비스 레벨 테스트 작성이 더 수월해졌습니다. 기존 픽스처 구성과도 자연스럽게 어우러집니다.Also applies to: 60-62
src/main/java/eatda/controller/story/StoryController.java (1)
57-66: 신규 “내가 올린 스트리 조회” 엔드포인트 설계 적절합니다
- 경로: GET /api/stories/member
- 파라미터 검증: page(최소 0), size(1~50, 기본 5)
- 로그인 회원 컨텍스트(LoginMember) 기반 조회
서비스 계층과 DTO 구성(StoriesInMemberResponse, StoryInMemberResponse)과도 일관됩니다.
src/test/java/eatda/service/story/StoryServiceTest.java (3)
276-292: 회원별 정렬·매핑 검증 테스트 LGTM동일 회원의 스토리를 createdAt DESC로 정렬하여 최신순으로 반환되는지, id와 storeName 필드가 정확히 매핑되는지 검증이 깔끔합니다.
294-309: 페이지네이션 동작 검증 LGTMpage=1, size=2에서 기대한 1건(story1)만 반환되는 케이스가 잘 잡혀 있습니다. 페이징 경계 조건을 확인하는 좋은 테스트입니다.
311-319: 존재하지 않는 회원 ID에 대한 빈 결과 검증 LGTM비존재 memberId 요청 시 빈 목록 반환을 명확히 보장합니다.
src/main/java/eatda/service/story/StoryService.java (1)
99-103: LGTM: toList()로 마무리하는 매핑기존 동작을 해치지 않으면서 가독성이 좋습니다.
src/test/java/eatda/document/story/StoryDocumentTest.java (3)
242-251: 요청 스펙 문서화 적절 (인증/페이징 파라미터)Authorization 헤더와 page/size 제약 설명이 명확합니다.
261-282: 성공 케이스 문서화 LGTMMockito stubbing과 RestDocs 문서화 흐름이 명확합니다. 페이지/사이즈 파라미터도 예시로 포함되어 재현성 좋습니다.
284-307: 에러 케이스 문서화 LGTM권한/토큰/회원ID 오류에 대한 파라미터화 테스트로 문서 일관성 보장 좋습니다.
src/test/java/eatda/controller/story/StoryControllerTest.java (1)
112-137: 회원의 스토리 목록 조회 컨트롤러 테스트 LGTM
- 인증 헤더 포함, page/size 쿼리 파라미터, 최신순 정렬 검증 모두 적절합니다.
- 응답 DTO(StoriesInMemberResponse)의 필드(id) 기준 검증도 계약과 일치합니다.
|
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.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/main/java/eatda/controller/store/StoreController.java (1)
19-19: 클래스 레벨 @validated 추가 적절 — 페이징 파라미터 공통화 제안각 컨트롤러에서 반복되는 page/size 제약을 공통 DTO(예: PagingParams)로 캡슐화하면 재사용성과 유지보수성이 좋아집니다. @PositiveOrZero / @positive 사용도 읽기성이 더 좋습니다.
예시:
// 공통 DTO public record PagingParams( @jakarta.validation.constraints.PositiveOrZero int page, @jakarta.validation.constraints.Positive @jakarta.validation.constraints.Max(50) int size ) {} // 사용 예시 public ResponseEntity<StoresResponse> getStores(PagingParams paging, @RequestParam(required = false) String category) { StoresResponse response = storeService.getStores(paging.page(), paging.size(), category); return ResponseEntity.ok(response); }
📜 Review details
Configuration used: .coderabbit.yaml
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 (3)
src/main/java/eatda/controller/cheer/CheerController.java(2 hunks)src/main/java/eatda/controller/store/StoreController.java(1 hunks)src/main/java/eatda/controller/story/StoryController.java(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/java/eatda/controller/story/StoryController.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/eatda/controller/store/StoreController.java (2)
src/main/java/eatda/controller/cheer/CheerController.java (1)
Validated(24-59)src/main/java/eatda/controller/story/StoryController.java (1)
Validated(24-78)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (2)
src/main/java/eatda/controller/cheer/CheerController.java (1)
15-15: 컨트롤러 수준 검증 활성화를 위한 @validated import 추가 적절클래스 레벨 검증을 위한 준비가 잘 되어 있습니다. 이 변경으로 메서드 파라미터의 Bean Validation 제약조건이 유효하게 동작합니다.
src/main/java/eatda/controller/store/StoreController.java (1)
13-13: 검증 활성화를 위한 @validated import 추가 적절메서드 파라미터 검증을 위한 필수 import가 반영되었습니다.
lvalentine6
left a comment
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.
이번 PR도 고생하셨습니다! 🍏
마이페이지 API가 추가되었으니
이미지 기능을 개선하는 작업에 여기도 포함을 해야겠군요... 😭
|
🎉 This PR is included in version 1.4.0-develop.87 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 1.8.0-develop.1 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 1.8.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |



✨ 개요
@EntityGraph를 이용한 조회 쿼리 횟수 최적화🧾 관련 이슈
closed #170
🔍 참고 사항 (선택)
Summary by CodeRabbit