Skip to content

chore: 릴리즈 — 찜 화면 API (매장 찜 목록·상품 찜 카드 확장·매장별 보기) - #215

Merged
chanwoo7 merged 7 commits into
mainfrom
develop
Aug 26, 2026
Merged

chore: 릴리즈 — 찜 화면 API (매장 찜 목록·상품 찜 카드 확장·매장별 보기)#215
chanwoo7 merged 7 commits into
mainfrom
develop

Conversation

@chanwoo7

@chanwoo7 chanwoo7 commented Aug 26, 2026

Copy link
Copy Markdown
Member

배경

찜 화면(상품 찜 목록 / 매장별 보기 / 매장별 찜 상품 / 매장 찜 목록) 백엔드 API 2건을 릴리즈합니다.

포함 PR

검증

  • 두 PR 모두 yarn validate 통과, Codex 👍, 필수 체크 전부 pass 후 develop에 머지되었습니다.

Summary by CodeRabbit

  • 새 기능

    • 매장 프로필 이미지 URL을 등록·수정·삭제할 수 있습니다.
    • 로그인한 사용자가 찜한 매장 목록을 조회하고, 이미지·평점·리뷰 수·지역·페이지 정보를 확인할 수 있습니다.
    • 찜한 상품을 매장별로 그룹화해 조회할 수 있으며, 매장 필터와 페이지네이션을 지원합니다.
    • 찜한 상품 목록에 할인율, 매장 정보, 지역, 평점 및 리뷰 수가 표시됩니다.
  • 개선

    • 찜 항목을 다시 추가해도 중복 없이 안정적으로 처리됩니다.
    • 비활성화되거나 삭제된 매장 및 상품은 찜 목록에서 제외됩니다.

찜 화면 시안(매장 찜 목록) 기준.
카드에 매장 프로필(로고)·매장명·평점(리뷰 수)·지역·대표 이미지 3장을 표시한다.
스펙 문서가 없어 정책은 사용자 문답으로 확정했다.

정책 결정(시안 외, 사용자 확정):
- 프로필 이미지는 Store 전용 컬럼(profile_image_url) 신설. 셀러 등록은 기존
  sellerUpdateStoreBasicInfo에 필드 추가로 처리(null 전달 시 제거, 미전달 시 유지).
- 카드 대표 이미지는 StoreImage sort_order asc 상위 3장(매장 상세 캐러셀과 동일 소스).
- 정렬은 찜 최신순, offset 페이지네이션(기존 myWishlist와 통일).
- 비활성·삭제 매장은 목록·카운트 제외(상품 찜 가시성 정책과 동일).
- 평점은 리뷰 없으면 0.0/0건, 소수 첫째 자리 반올림(PopularStore와 동일).

변경점:
- prisma: Store.profile_image_url(VarChar 2048, nullable) 마이그레이션 + 시드 반영
- SDL: myWishlistedStores 쿼리·MyWishlistedStoresConnection·WishlistedStoreSummary 신설,
  SellerStore/SellerUpdateStoreBasicInfoInput에 profileImageUrl 추가
- StoreWishlistRepository.findWishlistedStores: 단일 트랜잭션(목록+카운트),
  nested select에 deleted_at: null 명시
- StoreWishlistService.myWishlistedStores: aggregateReviewStats·buildRegionLabel 재사용
- StoreWishlistQueryResolver 신설, 모듈 등록
- store.factory에 profile_image_url override 추가

회귀 테스트 12건:
- service 6: 최신순 정렬·필드 매핑 / 이미지 3장 제한·삭제 이미지 제외 / 평점 집계·0건 0.0 /
  비활성·삭제 매장 및 soft-delete 찜 제외 / 타 사용자 격리 / 페이지네이션 경계
- resolver 2: 전체 경로 통합(목록 반환·빈 목록)
- input 5종·seller 3: profileImageUrl 등록/수정/제거/유지, DTO 검증

Claude-Session: https://claude.ai/code/session_01KfiGgWooJdsa4iPQPmqvBj
PR #213 Codex 리뷰 반영.
soft-delete 복원 시 created_at이 최초 찜 시점으로 남아
'찜 최신순' 정렬과 addedAt 표기가 재찜을 반영하지 못하는 문제 수정.
회귀 테스트 1건 추가(재찜 매장이 목록 최상단으로 온다).

Claude-Session: https://claude.ai/code/session_01KfiGgWooJdsa4iPQPmqvBj
PR #213 Codex 리뷰 2차 반영.
upsert update 브랜치가 active 찜에도 실행되어 더블 탭·재시도가
created_at을 리셋(목록 순서·addedAt 변경)하는 문제 수정.
복원(updateMany, deleted_at != null)과 신규 생성(create + P2002 멱등 처리)을
분리해 active 찜 중복 요청은 아무것도 변경하지 않는다.
회귀 테스트: 중복 추가 멱등 케이스에 created_at 불변 검증 추가.

Claude-Session: https://claude.ai/code/session_01KfiGgWooJdsa4iPQPmqvBj
feat(store): 찜한 매장 목록 조회(myWishlistedStores)와 매장 프로필 이미지
찜 화면 시안(상품 찜 목록·매장별 보기) 기준.
상품 카드에 지역 뱃지·상품 평점(리뷰 수)·할인율을 표시하고,
'매장별 보기'는 찜 상품을 매장 단위로 묶어 프로필·찜 상품 수를 보여준다.
스펙 문서가 없어 정책은 사용자 문답으로 확정했다.

정책 결정(시안 외, 사용자 확정):
- 특정 매장의 찜 상품 화면은 별도 쿼리 대신 MyWishlistInput.storeId 옵션 필터로 처리.
- 매장 그룹 정렬은 찜 상품 수 desc, 동점 시 최근 찜 순.
- 상품 평점은 리뷰 없으면 0.0/0건, 소수 첫째 자리 반올림(매장 평점 표기와 동일).
- 할인율은 서버 제공(discountRate 0~100) — PopularCake 등 기존 카드 컨벤션과 통일.
- 가시성(비활성·삭제 상품/매장 제외)은 기존 visibleWishlistWhere를 그룹핑에도 공유해
  상품 찜 목록 totalCount와 그룹 카운트 합이 일치한다.

변경점:
- SDL: WishlistItemSummary에 storeId·discountRate·regionLabel·ratingAverage·reviewCount 추가,
  MyWishlistInput에 storeId 추가, myWishlistStoreGroups 쿼리·타입 신설
- UserRepository: visibleWishlistWhere에 storeId 필터, findWishlistItems select 확장,
  findVisibleWishlistItemsForGrouping 신설 (WishlistItem에 store_id가 없어 groupBy 불가
  → 최소 필드 조회 후 service 그룹핑, 찜은 사용자당 소규모 전제)
- UserWishlistService: 카드 매핑 확장(aggregateProductReviewStats·calcDiscountRate·
  buildRegionLabel 재사용), myWishlistStoreGroups 구현
- product 배럴에 calcDiscountRate 공개(기존 aggregateProductReviewStats는 그대로 재사용)

회귀 테스트 11건:
- service 8: 카드 필드 매핑 / 평점 0건 / storeId 필터 / 그룹 집계·정렬 / 동점 최근 찜 순 /
  가시성 일치(그룹 합 == 목록 totalCount) / 그룹 페이지네이션 / 빈 목록
- resolver 통합 1: myWishlistStoreGroups 전체 경로
- input spec 2: storeId 검증 + 상속 페이지네이션

Claude-Session: https://claude.ai/code/session_01KfiGgWooJdsa4iPQPmqvBj
PR #213 Codex 리뷰(매장 찜 동일 이슈 2건)를 상품 찜에도 반영.
- soft-delete 복원 시 created_at이 최초 찜 시점으로 남아 '찜 최신순' 정렬과
  addedAt 표기가 재찜을 반영하지 못하는 문제 수정.
- 단, active 찜에 대한 중복 요청(더블 탭·재시도)은 created_at을 건드리지 않도록
  복원(updateMany, deleted_at != null)과 신규 생성(create + P2002 멱등 처리)을 분리.
회귀 테스트 2건: 재찜 상품 최상단 정렬 / 중복 추가 시 created_at 불변.

Claude-Session: https://claude.ai/code/session_01KfiGgWooJdsa4iPQPmqvBj
feat(user): 찜 목록 카드 확장(매장별 필터·평점·할인율)과 매장별 그룹 조회
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 50 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d77b862a-02af-473b-b911-fcc5e595ed51

📥 Commits

Reviewing files that changed from the base of the PR and between 1752ce1 and 579e1fa.

📒 Files selected for processing (33)
  • prisma/migrations/20260826171140_add_store_profile_image_url/migration.sql
  • prisma/schema.prisma
  • prisma/seed/stores.ts
  • src/features/product/index.ts
  • src/features/seller/dto/inputs/seller-update-store-basic-info.input.spec.ts
  • src/features/seller/dto/inputs/seller-update-store-basic-info.input.ts
  • src/features/seller/seller-store.graphql
  • src/features/seller/services/seller-store-mappers.helper.ts
  • src/features/seller/services/seller-store-profile.service.spec.ts
  • src/features/seller/services/seller-store-profile.service.ts
  • src/features/seller/types/seller-output.type.ts
  • src/features/store/constants/store-wishlist.constants.ts
  • src/features/store/dto/inputs/my-wishlisted-stores.input.spec.ts
  • src/features/store/dto/inputs/my-wishlisted-stores.input.ts
  • src/features/store/repositories/store-wishlist.repository.ts
  • src/features/store/resolvers/store-wishlist-query.resolver.spec.ts
  • src/features/store/resolvers/store-wishlist-query.resolver.ts
  • src/features/store/services/store-wishlist.service.spec.ts
  • src/features/store/services/store-wishlist.service.ts
  • src/features/store/store-wishlist.graphql
  • src/features/store/store.module.ts
  • src/features/store/types/store-wishlist-output.type.ts
  • src/features/user/dto/inputs/my-wishlist-store-groups.input.ts
  • src/features/user/dto/inputs/my-wishlist.input.spec.ts
  • src/features/user/dto/inputs/my-wishlist.input.ts
  • src/features/user/repositories/user.repository.ts
  • src/features/user/resolvers/user-wishlist-query.resolver.ts
  • src/features/user/resolvers/user-wishlist.resolver.spec.ts
  • src/features/user/services/user-wishlist.service.spec.ts
  • src/features/user/services/user-wishlist.service.ts
  • src/features/user/types/user-wishlist-output.type.ts
  • src/features/user/user-wishlist.graphql
  • src/test/factories/store.factory.ts
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

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)

진단 283건 (error 0).

Category error warning info
architecture 0 0 13
correctness 0 130 0
performance 0 24 17
schema 0 0 86
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

@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 97.65% 5029/5150
🟢 Branches 94.02% 2058/2189
🟢 Functions 96.23% 969/1007
🟢 Lines 98.2% 4576/4660

Test suite run success

1635 tests passing in 190 suites.

Report generated by 🧪jest coverage report action from 579e1fa

@chanwoo7
chanwoo7 merged commit a1cba52 into main Aug 26, 2026
15 checks passed
@chanwoo7
chanwoo7 deleted the develop branch August 26, 2026 18:03
chanwoo7 added a commit that referenced this pull request Aug 27, 2026
chore: 릴리즈 — 찜 화면 API (매장 찜 목록·상품 찜 카드 확장·매장별 보기)
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