Skip to content

feat(store): 구매자 매장 후기 목록 조회(storeReviews)와 좋아요 집계#159

Merged
chanwoo7 merged 3 commits into
developfrom
feat/store-detail-reviews
Jun 23, 2026
Merged

feat(store): 구매자 매장 후기 목록 조회(storeReviews)와 좋아요 집계#159
chanwoo7 merged 3 commits into
developfrom
feat/store-detail-reviews

Conversation

@chanwoo7

Copy link
Copy Markdown
Member

Summary

구매자 매장 후기 탭 조회 API를 신설한다. 매장 상세 화면의 후기 영역(공개 리뷰 목록 · 평점 · 사진 · 좋아요 · 빈 상태)을 담당한다. store-detail 도메인 작업의 3단계(마지막).

Scope

  • 신규 Query storeReviews(input: StoreReviewsInput!): StoreReviewConnection! (public, OptionalJwtAuthGuard)
    • 매장 공개 리뷰 목록(최신순 · 커서), totalCount(후기 탭 카운트, 0이면 빈 상태)
    • 리뷰: rating · content · media(이미지/영상) · authorNickname · productName(주문 시점 스냅샷) · createdAt
    • 좋아요 수 집계 + isLiked(로그인 사용자 기준, 비로그인 false)
  • 매장 공개 리뷰 조회를 store feature가 소유: StoreReviewRepository 신설
    • 근거: 기존 ReviewRepository는 user feature의 "본인 리뷰 작성/관리" 전용. store가 직접 import하면 cross-feature 내부 import 위반. 같은 테이블을 읽어도 "매장 공개 리뷰 + 좋아요 집계"는 매장 조회 유스케이스로 응집
    • 좋아요 mutation(likeReview)은 user feature 그대로, store는 집계/isLiked 읽기만
  • ReviewMediaType enum은 기존 user-review SDL 정의를 재사용

진행 상황

Impact

  • 신규 조회 API 추가. 스키마 변경 없음(기존 review/review_like/review_media 모델 사용)
  • 기존 동작/계약 변경 없음

Test plan

  • 단위(mapper): rating Decimal→number · media 매핑 · authorNickname null(프로필 없음) · likeCount/isLiked 반영
  • 통합(service, real DB): 빈 상태(totalCount 0) · 닉네임/상품명/평점/미디어 · 좋아요 수 집계 + 로그인/비로그인 isLiked · soft-delete 제외 · 최신순 커서 페이지네이션
  • 통합(resolver, real DB): 위임 · JwtUser isLiked
  • yarn validate 전체 통과(dto:check·arch:check·커버리지 포함)

- storeReviews(input): 매장 공개 리뷰 목록(최신순·커서), totalCount(후기 탭 카운트), media·작성자 닉네임·연결 상품명(주문 스냅샷)
- 리뷰 좋아요 수 집계 + isLiked(OptionalJwtAuthGuard, 비로그인 false)
- 매장 공개 리뷰 조회를 store feature가 소유(StoreReviewRepository 신설). user의 ReviewRepository(본인 리뷰 작성/관리)와 책임 분리, cross-feature 경계 준수
- 단위(mapper)·통합(service/resolver) 테스트 11건
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f54d76d7-d948-474e-b306-cc655aad7fe1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/store-detail-reviews

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

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

🧹 knip — dead-code 리포트

요약 항목 없음
전체 리포트
(knip 출력 없음 — 이슈 0이거나 실행 실패)

청소 후보(오탐 가능) · 기준 docs/guide/architecture-conventions.md

@github-actions

Copy link
Copy Markdown

🩺 NestJS Doctor — 89/100 (Good)

진단 258건 (error 0).

Category error warning info
architecture 0 0 13
correctness 0 108 0
performance 0 24 16
schema 0 0 84
security 0 13 0
architecture / security 상위 항목
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal type 'IAuditLogRepository'.
  • warning security/security/no-exposed-env-vars: Direct 'process.env.NODE_ENV' access in 'AuthController'. Use ConfigService instead.
  • warning security/security/require-guards-on-endpoints: Endpoint 'start' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'callback' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'refresh' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'logout' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'sellerLogin' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'sellerRefresh' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'sellerLogout' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'devIssueToken' has no @UseGuards() at class or method level.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal module '@/features/conversation/repositories/conversation.repository'.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal type 'ConversationRepository'.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal module '@/features/order/repositories/order.repository'.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal type 'OrderRepository'.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal module '@/features/product/repositories/product.repository'.

오탐 포함 가능 · 기준 docs/guide/architecture-conventions.md

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f737eeb5a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +42 to +43
store_id: args.storeId,
deleted_at: null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restrict storeReviews to active stores

When a store is soft-deleted or marked inactive, storeDetail hides it via findStoreDetailById (is_active: true, deleted_at: null), but this new public review query only filters reviews by store_id. Anyone who still knows that store ID can call storeReviews and receive the review content/media and totalCount; add the same active-store relation filter or an existence check, and mirror it in countStoreReviews.

Useful? React with 👍 / 👎.

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 97.46% 3985/4089
🟢 Branches 93.24% 1242/1332
🟢 Functions 94.8% 748/789
🟢 Lines 97.87% 3635/3714

Test suite run success

1376 tests passing in 165 suites.

Report generated by 🧪jest coverage report action from fa88dc1

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.11321% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ures/store/repositories/store-review.repository.ts 92.30% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

비활성/삭제 매장의 store_id를 알면 storeReviews로 리뷰 내용·미디어·totalCount가 노출되던 문제를 수정한다. listStoreReviews·countStoreReviews where에 store active/deleted 술어를 추가해 storeDetail의 가드와 일치시킨다. (Codex P2 반영)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 847f8acdb0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +53 to +55
account: {
select: { user_profile: { select: { nickname: true } } },
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Hide nicknames for deleted review authors

When a user deletes their account after writing a review, softDeleteAccount marks userProfile.deleted_at and overwrites the nickname to deleted_<accountId> (src/features/user/repositories/user.repository.ts), but this nested select still reads the profile without checking deleted_at (the soft-delete extension only patches the root review.findMany). As a result, the public storeReviews response exposes authorNickname: "deleted_123" for deleted users instead of anonymizing it; select deleted_at and map deleted profiles to null or filter the relation.

Useful? React with 👍 / 👎.

탈퇴(soft-delete) 시 nickname이 deleted_<id>로 덮어써지는데, soft-delete extension은 nested user_profile에 deleted_at을 주입하지 않아 storeReviews가 deleted_<id>를 그대로 노출했다. user_profile.deleted_at을 함께 select하고 매퍼에서 탈퇴 프로필은 authorNickname=null로 익명화한다. (Codex P2 :55 반영)
@chanwoo7 chanwoo7 merged commit 7583830 into develop Jun 23, 2026
11 checks passed
@chanwoo7 chanwoo7 deleted the feat/store-detail-reviews branch June 23, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant