Skip to content

Conversation

@leegwichan
Copy link
Member

@leegwichan leegwichan commented Jul 31, 2025

✨ 개요

  • 가게 상세 페이지에서 보여줄 "스토리 목록"을 위한 API 구현

🧾 관련 이슈

🔍 참고 사항 (선택)

image

Summary by CodeRabbit

  • 신규 기능
    • 카카오 ID로 특정 매장의 스토리 목록을 조회할 수 있는 API 엔드포인트가 추가되었습니다.
    • 스토리 상세 정보(스토리 ID, 이미지 URL, 작성자 ID 및 닉네임)를 포함한 응답이 제공됩니다.
  • 테스트
    • 신규 API 엔드포인트 및 서비스 로직에 대한 단위 테스트와 문서화 테스트가 추가되었습니다.
    • 다양한 정상 및 실패 케이스를 검증합니다.

@coderabbitai
Copy link

coderabbitai bot commented Jul 31, 2025

Walkthrough

스토리의 상세 목록을 카카오 ID 기준으로 페이징 조회하는 새로운 API 엔드포인트와 응답 레코드, 서비스 계층, 레포지토리 메서드가 추가되었습니다. 이에 대한 단위 테스트, 문서화 테스트, 컨트롤러 테스트가 함께 도입되어 전체적인 기능 검증과 문서화가 이루어졌습니다.

Changes

Cohort / File(s) Change Summary
컨트롤러 및 응답 객체 추가
src/main/java/eatda/controller/story/StoryController.java, src/main/java/eatda/controller/story/StoriesDetailResponse.java
카카오 ID로 스토리 상세 목록을 조회하는 GET 엔드포인트 및 응답 레코드(StoriesDetailResponse, 내부에 StoryDetailResponse) 추가
서비스 및 레포지토리 확장
src/main/java/eatda/service/story/StoryService.java, src/main/java/eatda/repository/story/StoryRepository.java
카카오 ID와 size로 스토리 목록을 페이징 조회하는 서비스 메서드와, 이를 위한 레포지토리 쿼리 메서드 추가
컨트롤러 테스트
src/test/java/eatda/controller/story/StoryControllerTest.java
새로운 엔드포인트에 대한 정상 동작 테스트 케이스 추가
문서화 테스트
src/test/java/eatda/document/story/StoryDocumentTest.java
API 문서 자동화를 위한 성공/실패 케이스 및 REST Docs 명세 테스트 추가
서비스 단위 테스트
src/test/java/eatda/service/story/StoryServiceTest.java
서비스 계층의 페이징 조회 기능 검증을 위한 단위 테스트 케이스 2종 추가 및 비공개 클래스 전환

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant Repository
    participant ImageStorage

    Client->>Controller: GET /api/stories/kakao/{kakaoId}?size={size}
    Controller->>Service: getPagedStoryDetails(kakaoId, size)
    Service->>Repository: findAllByStoreKakaoIdOrderByCreatedAtDesc(kakaoId, pageable)
    Repository-->>Service: List<Story>
    loop for each Story
        Service->>ImageStorage: getPresignedUrl(imageKey)
        ImageStorage-->>Service: imageUrl
    end
    Service-->>Controller: StoriesDetailResponse
    Controller-->>Client: 200 OK + StoriesDetailResponse
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • lvalentine6

Poem

🐰
새로운 이야기, 카카오로 모여
토끼 귀 쫑긋, 스토리 찾아가네
멤버 이름, 사진까지 척척
테스트와 문서도 빠짐없이
코드밭에 풍성한 이야기
오늘도 리뷰하며 깡총!
🥕

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 03ca575 and 1491297.

📒 Files selected for processing (1)
  • src/test/java/eatda/service/story/StoryServiceTest.java (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/test/java/eatda/service/story/StoryServiceTest.java
⏰ 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
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/get-stories-kakaoId

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a 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 (2)
src/test/java/eatda/document/story/StoryDocumentTest.java (1)

281-298: 실패 테스트에서 오직 하나의 에러 코드만 테스트하는 것이 제한적입니다.

@EnumSource를 사용하여 PRESIGNED_URL_GENERATION_FAILED 에러만 테스트하고 있는데, 실제로는 이 API에서 더 많은 에러 상황이 발생할 수 있습니다 (예: 잘못된 카카오 ID, 권한 없음 등).

더 포괄적인 에러 테스트를 위해 다음과 같이 수정하는 것을 고려해보세요:

-@EnumSource(value = BusinessErrorCode.class, names = {"PRESIGNED_URL_GENERATION_FAILED"})
+@EnumSource(value = BusinessErrorCode.class, names = {"PRESIGNED_URL_GENERATION_FAILED", "INVALID_REQUEST", "UNAUTHORIZED"})

또는 각각을 개별 테스트로 분리하여 더 명확한 시나리오를 테스트할 수 있습니다.

src/test/java/eatda/service/story/StoryServiceTest.java (1)

192-272: 테스트 커버리지를 더 향상시킬 수 있습니다.

현재 테스트는 기본적인 필터링 기능은 잘 검증하고 있지만, 다음과 같은 추가 시나리오들을 고려해볼 수 있습니다:

추가 테스트 케이스들:

  • 존재하지 않는 카카오 ID로 조회했을 때 빈 목록 반환
  • 페이지 크기 제한이 올바르게 적용되는지 검증
  • 생성 날짜 순으로 정렬되는지 검증 (최신순)
  • 외부 이미지 스토리지에서 예외 발생 시 처리

예시:

@Test
void 존재하지_않는_카카오ID로_조회하면_빈_목록을_반환한다() {
    String nonExistentKakaoId = "non-existent";
    
    var response = storyService.getPagedStoryDetails(nonExistentKakaoId, 5);
    
    assertThat(response.stories()).isEmpty();
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0db5d62 and 03ca575.

📒 Files selected for processing (7)
  • src/main/java/eatda/controller/story/StoriesDetailResponse.java (1 hunks)
  • src/main/java/eatda/controller/story/StoryController.java (1 hunks)
  • src/main/java/eatda/repository/story/StoryRepository.java (1 hunks)
  • src/main/java/eatda/service/story/StoryService.java (2 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/story/StoryServiceTest.java (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 컨트롤러 테스트에서 mockitobean으로 의존성을 모킹한 경우, 상세한 비즈니스 로직 검증보다는 컨트롤러 계층의 동작(라우팅, 파라미터 처리, 응답 구조 등)을 검증하는 것이 ...
Learnt from: leegwichan
PR: YAPP-Github/26th-Web-Team-1-BE#60
File: src/test/java/eatda/controller/store/StoreControllerTest.java:10-32
Timestamp: 2025-07-09T07:56:50.612Z
Learning: 컨트롤러 테스트에서 MockitoBean으로 의존성을 모킹한 경우, 상세한 비즈니스 로직 검증보다는 컨트롤러 계층의 동작(라우팅, 파라미터 처리, 응답 구조 등)을 검증하는 것이 더 적절합니다. 모킹된 데이터에 대한 상세 검증은 의미가 없기 때문입니다.

Applied to files:

  • src/test/java/eatda/service/story/StoryServiceTest.java
  • src/test/java/eatda/controller/story/StoryControllerTest.java
🔇 Additional comments (12)
src/main/java/eatda/repository/story/StoryRepository.java (1)

12-12: LGTM! 메서드 시그니처가 적절합니다.

Spring Data JPA 네이밍 컨벤션을 잘 따르고 있으며, 페이징과 정렬을 지원하는 적절한 구현입니다.

src/main/java/eatda/service/story/StoryService.java (2)

6-6: LGTM! 새로운 응답 DTO 임포트가 적절합니다.


118-129: DB 레벨의 N+1 쿼리는 발생하지 않습니다
imageStorage.getPreSignedUrl() 호출은 JPA를 통해 추가 쿼리를 발생시키지 않으며, 내부적으로 AWS SDK의 S3Presigner를 이용해 로컬에서 URL을 서명만 할 뿐입니다.

  • storyRepository.findAllBy… 로 한 번에 모든 Story를 조회하므로 DB 쿼리는 1회 실행됩니다.
  • getPreSignedUrl() 은 캐시 확인 후 없으면 S3Presigner.presignGetObject() 만 수행해, DB 호출과 무관합니다.

따라서 // TODO: N+1 문제 해결 주석은 제거해도 무방하며, 필요하다면 추후 성능 모니터링 지표를 통해 확인하는 방식으로 관리해주세요.

Likely an incorrect or invalid review comment.

src/main/java/eatda/controller/story/StoryController.java (1)

46-53: LGTM! REST API 엔드포인트가 잘 설계되었습니다.

구현이 우수합니다:

  • RESTful 경로 구조가 명확함
  • 파라미터 검증이 적절함 (@min, @max)
  • 기본값 설정이 합리적임
  • 기존 엔드포인트 패턴과 일관성 있음
src/main/java/eatda/controller/story/StoriesDetailResponse.java (1)

1-24: LGTM! 응답 DTO 설계가 깔끔하고 적절합니다.

Record 설계가 우수합니다:

  • 모던 Java record 문법을 적절히 활용
  • 명확하고 설명적인 필드명
  • 중첩 record 구조가 논리적임
  • 도메인 객체를 받는 생성자가 편리함
  • 불변성 보장 (record의 특성)
src/test/java/eatda/controller/story/StoryControllerTest.java (2)

11-11: LGTM! 필요한 임포트가 적절히 추가되었습니다.


144-176: LGTM! 컨트롤러 테스트가 적절히 작성되었습니다.

컨트롤러 계층의 동작을 올바르게 검증하고 있습니다:

  • 엔드포인트 라우팅 검증
  • 파라미터 처리 검증 (pathParam, queryParam)
  • 응답 구조 및 상태 코드 검증
  • 서비스 계층의 적절한 모킹
  • 기존 테스트 패턴과의 일관성

이전 학습 내용에 따라 모킹된 데이터에 대한 상세 검증보다는 컨트롤러 계층의 핵심 동작에 집중한 좋은 테스트입니다.

src/test/java/eatda/document/story/StoryDocumentTest.java (3)

8-8: 새로운 imports 추가가 적절합니다.

새 API를 위한 필요한 import들이 정확히 추가되었습니다 - ARRAY 타입, 새로운 응답 클래스들, 그리고 매개변수화된 테스트를 위한 어노테이션들입니다.

Also applies to: 15-16, 34-35


236-258: API 문서화 설정이 잘 구현되었습니다.

REST Docs 문서화 설정이 기존 패턴을 잘 따르고 있으며, 경로 매개변수와 쿼리 매개변수, 응답 필드 문서화가 명확하게 정의되어 있습니다. 특히 배열 타입과 각 필드의 데이터 타입이 명시적으로 지정된 점이 좋습니다.


259-279: 성공 테스트 케이스가 적절히 구현되었습니다.

서비스 메서드를 모킹하고 응답을 검증하는 로직이 올바르게 작성되었습니다. Authorization 헤더와 쿼리 매개변수가 포함된 점도 좋습니다.

src/test/java/eatda/service/story/StoryServiceTest.java (2)

11-11: 새로운 응답 클래스 import가 적절합니다.

새 API의 응답 구조를 위한 StoriesDetailResponse import가 정확히 추가되었습니다.


192-232: 첫 번째 테스트가 잘 구현되었습니다.

동일한 카카오 ID를 가진 여러 스토리가 모두 반환되는지 검증하는 테스트가 적절히 작성되었습니다. 외부 이미지 스토리지 모킹과 응답 검증도 올바르게 구현되어 있습니다.

Copy link
Member

@lvalentine6 lvalentine6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번 PR도 고생하셨습니다! 🌮
나중에 엔드포인트 로직에 대해서 한번 깔끔하게 정리하면 좋을것 같은데
지금은 일단 이렇게 가시죠~

@sonarqubecloud
Copy link

@leegwichan leegwichan merged commit ed43e3d into develop Jul 31, 2025
4 checks passed
@leegwichan leegwichan deleted the feat/get-stories-kakaoId branch July 31, 2025 16:06
@github-actions
Copy link

🎉 This PR is included in version 1.4.0-develop.41 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@github-actions
Copy link

github-actions bot commented Aug 1, 2025

🎉 This PR is included in version 1.6.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants