Skip to content

refactor(product): 상품 카드 조립 5벌 → 공용 매퍼 1벌, 필드명 통일 - #343

Merged
chanwoo7 merged 1 commit into
develop-msafrom
refactor/product-card-unify
Sep 14, 2026
Merged

chanwoo7 merged 1 commit into
develop-msafrom
refactor/product-card-unify

Conversation

@chanwoo7

Copy link
Copy Markdown
Member

배경

같은 상품이 화면마다 다른 코드로 조립되고 있었다. 대표 이미지 선택(sort_order 최소 1건)·할인율 산식·지역 표기가 5곳에 복제돼 있어, 한 곳만 고치면 같은 상품이 화면별로 다른 가격표를 달게 된다.

변경

toProductCardCore(id, product) 하나로 모았다. 카드 공통 9필드를 만든다.

id  storeId  name  thumbnailUrl  storeName  regionLabel
regularPrice  salePrice  discountRate

조인 행(찜·최근 본 상품)은 상품 id가 product_id로 한 단계 바깥에 있어 id를 따로 받는다.

교체한 호출부 5곳:

화면 위치
홈 인기 케이크 product-home-mappers.helper.ts
검색 결과 product-search-mappers.helper.ts
찜 목록 user-wishlist.service.ts
최근 본 상품 목록 user-recent-view.service.ts
마이페이지 개요 user-mypage.service.ts

마지막 하나는 애초 계획에 없었다. 출력 타입을 extends ProductCardCore로 바꾸자 컴파일러가 찾아낸 네 번째 복제본이다. 타입을 통일해 두면 다음 복제도 같은 방식으로 잡힌다.

SDL

user feature의 두 카드 타입만 별도 어휘를 쓰고 있었다. 상품 쪽 정본으로 맞췄다.

이전 이후
productId id
productName name
representativeImageUrl thumbnailUrl

RecentViewedProductSummarystoreId · discountRate · regionLabel이 새로 실린다. 상세 URL이 /store/{storeId}/products/{id}인데 storeId가 없어 이동이 막혀 있었다. recent_product_view select를 그만큼 넓혔고, 같은 store 조인이라 쿼리 수는 그대로다.

하지 않은 것 — SDL 타입 5개 → 1개

계획(Phase 0 항목 12)은 PopularCake · SearchProduct · StoreProduct · WishlistItemSummary · RecentViewedProductSummaryProductCard 1타입으로 합치는 것이었다. 하지 않았다.

GraphQL은 타입 간 필드 상속이 없다(인터페이스도 구현 타입에서 전부 재선언해야 한다). 한 타입으로 합치려면 화면마다 안 쓰는 필드를 이렇게 처리해야 한다.

  • ratingAverage · reviewCount — 홈 인기·최근 본 상품은 집계하지 않는다 → nullable로 풀거나 0을 채운다
  • isWishlisted — 홈 인기·검색 비로그인은 판정하지 않는다 → 같은 문제
  • rank — 인기 목록에만 있다 → nullable
  • StoreProductdescription · currency · categoryIds — 다른 4곳엔 없다

계약이 나빠진다. 중복의 실체는 SDL 타입 수가 아니라 조립 코드였고, 그건 이 PR에서 사라졌다. TypeScript 쪽은 extends ProductCardCore로 이미 단일 소스다.

테스트

  • product-card.helper.spec.ts 순수 단위 8건 — id 변환, "0" id(조인 행에서 실제로 나온다), 대표 이미지 없음, 할인가 없음, 지역 표기 4분기.
  • 최근 본 상품에 새로 실린 3필드 회귀 1건.

yarn validate 그린 — 275 suites / 2,837 tests.

FE-BREAKING

있음. 찜 목록·최근 본 상품·마이페이지 개요를 쓰는 화면이 전부 영향받는다.

WishlistItemSummary.productId → id
WishlistItemSummary.productName → name
WishlistItemSummary.representativeImageUrl → thumbnailUrl
RecentViewedProductSummary.productId → id
RecentViewedProductSummary.productName → name
RecentViewedProductSummary.representativeImageUrl → thumbnailUrl
RecentViewedProductSummary: storeId · discountRate · regionLabel 추가(비파괴)

같은 상품이 화면마다 다른 코드로 조립되고 있었다. 대표 이미지 선택(sort_order
최소 1건)·할인율 산식·지역 표기가 5곳에 복제돼 있어, 한 곳만 고치면 같은 상품이
화면별로 다른 가격표를 달게 된다.

- `toProductCardCore(id, product)` 신설(product feature). 카드 공통 9필드
  (id·storeId·name·thumbnailUrl·storeName·regionLabel·regularPrice·salePrice·
  discountRate)를 한 곳에서 만든다. 조인 행(찜·최근 본 상품)은 상품 id가
  `product_id`로 한 단계 바깥에 있어 id를 따로 받는다.
- 호출부 5곳으로 교체: 홈 인기 케이크, 검색 결과, 찜 목록, 최근 본 상품 목록,
  마이페이지 개요. 마지막 하나는 타입 통일 과정에서 컴파일러가 찾아낸 네 번째
  복제본이다.
- 출력 타입은 `extends ProductCardCore`로 바꿔 필드 누락이 타입 오류가 되게 했다.

SDL: user feature의 두 카드 타입이 쓰던 별도 어휘를 상품 쪽 정본으로 맞췄다.
productId → id, productName → name, representativeImageUrl → thumbnailUrl.
RecentViewedProductSummary에는 storeId·discountRate·regionLabel이 새로 실린다 —
상세 URL이 /store/{storeId}/products/{id}라 storeId 없이는 이동이 막혔다.
recent_product_view select도 그만큼 넓혔다(같은 store 조인이라 쿼리 수는 그대로).

테스트: 매퍼 순수 단위 spec 8건(id 변환·"0" id·대표 이미지 없음·할인가 없음·
지역 표기 4분기) + 새 필드 회귀 1건.

5개 SDL 타입을 ProductCard 1타입으로 합치는 건 하지 않았다. GraphQL은 타입 간
필드 상속이 없어 한 타입으로 합치려면 화면마다 안 쓰는 필드
(ratingAverage·isWishlisted·rank)를 nullable로 풀거나 가짜 값을 채워야 한다 —
계약이 나빠진다. 중복의 실체는 조립 코드였고 그건 이 PR에서 사라졌다.
@coderabbitai

coderabbitai Bot commented Sep 14, 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: Advanced

Run ID: 8b8bd621-792e-4bc6-9539-de0430a4e055

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

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

🩺 NestJS Doctor — 89/100 (Good)

진단 385건 (error 0).

Category error warning info
architecture 0 0 14
correctness 0 237 0
performance 0 26 17
schema 0 0 75
security 0 16 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.
  • warning security/security/require-guards-on-endpoints: Endpoint 'adminLogin' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'adminRefresh' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'adminLogout' 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'.

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

@github-actions

Copy link
Copy Markdown

🧹 knip — dead-code 리포트

Unresolved imports (225)
Unused exports (1)
Unused exported types (5)
Duplicate exports (1)
전체 리포트
Unresolved imports (225)
@/generated/prisma/client  prisma/seed.ts:14:30                                                              
@/generated/prisma/client  src/common/utils/decimal-parser.ts:2:24                                           
@/generated/prisma/client  src/features/admin/repositories/admin.repository.ts:20:8                          
@/generated/prisma/client  src/features/admin/resolvers/admin-account.resolver.spec.ts:9:35                  
@/generated/prisma/client  src/features/admin/resolvers/admin-content.resolver.spec.ts:9:35                  
@/generated/prisma/client  src/features/admin/resolvers/admin-dashboard.resolver.spec.ts:9:35                
@/generated/prisma/client  src/features/admin/resolvers/admin-moderation.resolver.spec.ts:9:35               
@/generated/prisma/client  src/features/admin/resolvers/admin-notification.resolver.spec.ts:8:35             
@/generated/prisma/client  src/features/admin/resolvers/admin-order.resolver.spec.ts:10:35                   
@/generated/prisma/client  src/features/admin/resolvers/admin-product.resolver.spec.ts:9:35                  
@/generated/prisma/client  src/features/admin/resolvers/admin-region.resolver.spec.ts:9:35                   
@/generated/prisma/client  src/features/admin/resolvers/admin-seller.resolver.spec.ts:9:35                   
@/generated/prisma/client  src/features/admin/resolvers/admin-store.resolver.spec.ts:9:35                    
@/generated/prisma/client  src/features/admin/resolvers/admin-taxonomy.resolver.spec.ts:9:35                 
@/generated/prisma/client  src/features/admin/resolvers/admin-user.resolver.spec.ts:9:35                     
@/generated/prisma/client  src/features/admin/services/admin-account.service.spec.ts:13:35                   
@/generated/prisma/client  src/features/admin/services/admin-audit.service.spec.ts:5:35                      
@/generated/prisma/client  src/features/admin/services/admin-banner.service.spec.ts:7:35                     
@/generated/prisma/client  src/features/admin/services/admin-banner.service.ts:39:8                          
@/generated/prisma/client  src/features/admin/services/admin-base.service.ts:4:29                            
@/generated/prisma/client  src/features/admin/services/admin-content-mappers.helper.ts:2:29                  
@/generated/prisma/client  src/features/admin/services/admin-dashboard.service.spec.ts:8:35                  
@/generated/prisma/client  src/features/admin/services/admin-media-url-ownership.spec.ts:6:35                
@/generated/prisma/client  src/features/admin/services/admin-moderation.service.spec.ts:7:35                 
@/generated/prisma/client  src/features/admin/services/admin-notification.service.spec.ts:7:35               
@/generated/prisma/client  src/features/admin/services/admin-notification.service.ts:23:50                   
@/generated/prisma/client  src/features/admin/services/admin-order.service.spec.ts:8:35                      
@/generated/prisma/client  src/features/admin/services/admin-order.service.ts:33:29                          
@/generated/prisma/client  src/features/admin/services/admin-product.service.spec.ts:7:35                    
@/generated/prisma/client  src/features/admin/services/admin-product.service.ts:28:50                        
@/generated/prisma/client  src/features/admin/services/admin-region.service.spec.ts:8:35                     
@/generated/prisma/client  src/features/admin/services/admin-region.service.ts:30:8                          
@/generated/prisma/client  src/features/admin/services/admin-seller.service.spec.ts:9:35                     
@/generated/prisma/client  src/features/admin/services/admin-seller.service.ts:48:50                         
@/generated/prisma/client  src/features/admin/services/admin-store-mappers.helper.ts:6:28                    
@/generated/prisma/client  src/features/admin/services/admin-store.service.spec.ts:7:35                      
@/generated/prisma/client  src/features/admin/services/admin-store.service.ts:35:8                           
@/generated/prisma/client  src/features/admin/services/admin-taxonomy.service.spec.ts:7:35                   
@/generated/prisma/client  src/features/admin/services/admin-taxonomy.service.ts:43:8                        
@/generated/prisma/client  src/features/admin/services/admin-user.service.spec.ts:11:35                      
@/generated/prisma/client  src/features/admin/services/admin-user.service.ts:30:8                            
@/generated/prisma/client  src/features/admin/types/admin-output.type.ts:14:8                                
@/generated/prisma/client  src/features/audit-log/repositories/audit-log.repository.interface.ts:6:8         
@/generated/prisma/client  src/features/audit-log/repositories/audit-log.repository.spec.ts:2:35             
@/generated/prisma/client  src/features/audit-log/repositories/audit-log.repository.ts:11:8                  
@/generated/prisma/client  src/features/auth/repositories/account-credential.repository.interface.ts:1:29    
@/generated/prisma/client  src/features/auth/repositories/account-credential.repository.spec.ts:2:35         
@/generated/prisma/client  src/features/auth/repositories/account.repository.interface.ts:1:47               
@/generated/prisma/client  src/features/auth/repositories/account.repository.spec.ts:6:34                    
@/generated/prisma/client  src/features/auth/repositories/account.repository.ts:17:8                         
@/generated/prisma/client  src/features/auth/repositories/refresh-session.repository.interface.ts:1:41       
@/generated/prisma/client  src/features/auth/repositories/refresh-session.repository.spec.ts:5:35            
@/generated/prisma/client  src/features/auth/repositories/refresh-session.repository.ts:6:49                 
@/generated/prisma/client  src/features/auth/services/credential-auth.service.interface.ts:3:36              
@/generated/prisma/client  src/features/auth/services/credential-auth.service.spec.ts:27:29                  
@/generated/prisma/client  src/features/auth/services/credential-auth.service.ts:30:50                       
@/generated/prisma/client  src/features/auth/services/oidc-client.service.spec.ts:5:34                       
@/generated/prisma/client  src/features/auth/services/oidc-client.service.ts:13:34                           
@/generated/prisma/client  src/features/auth/strategies/jwt-bearer.strategy.spec.ts:7:35                     
@/generated/prisma/client  src/features/conversation/repositories/conversation.repository.spec.ts:2:35       
@/generated/prisma/client  src/features/conversation/repositories/conversation.repository.ts:7:8             
@/generated/prisma/client  src/features/conversation/resolvers/conversation-center.resolver.spec.ts:10:35    
@/generated/prisma/client  src/features/conversation/resolvers/conversation-inquiry.resolver.spec.ts:9:35    
@/generated/prisma/client  src/features/conversation/services/conversation-center.service.spec.ts:5:35       
@/generated/prisma/client  src/features/conversation/services/conversation-inquiry.service.spec.ts:12:35     
@/generated/prisma/client  src/features/conversation/services/conversation-inquiry.service.ts:29:8           
@/generated/prisma/client  src/features/conversation/services/conversation-subscription.service.spec.ts:12:35
@/generated/prisma/client  src/features/conversation/types/conversation-output.type.ts:4:8                   
@/generated/prisma/client  src/features/notification/constants/notification-messages.ts:1:29                 
@/generated/prisma/client  src/features/notification/services/notification-payloads.helper.spec.ts:9:8       
@/generated/prisma/client  src/features/notification/services/notification-payloads.helper.ts:10:8           
@/generated/prisma/client  src/features/order/policies/order-status-transition.policy.spec.ts:4:29           
@/generated/prisma/client  src/features/order/policies/order-status-transition.policy.ts:4:29                
@/generated/prisma/client  src/features/order/repositories/order.repository.spec.ts:2:35                     
@/generated/prisma/client  src/features/order/repositories/order.repository.ts:10:8                          
@/generated/prisma/client  src/features/order/resolvers/order-checkout-mutation.resolver.spec.ts:9:35        
@/generated/prisma/client  src/features/order/services/order-checkout.service.spec.ts:23:8                   
@/generated/prisma/client  src/features/order/services/order-checkout.service.ts:15:24                       
@/generated/prisma/client  src/features/order/types/create-order-output.type.ts:1:34                         
@/generated/prisma/client  src/features/product/repositories/product-review.repository.ts:4:24               
@/generated/prisma/client  src/features/product/repositories/product.repository.spec.ts:2:35                 
@/generated/prisma/client  src/features/product/repositories/product.repository.ts:8:8                       
@/generated/prisma/client  src/features/product/resolvers/product-category-query.resolver.spec.ts:4:35       
@/generated/prisma/client  src/features/product/resolvers/product-detail-query.resolver.spec.ts:6:35         
@/generated/prisma/client  src/features/product/resolvers/product-home-query.resolver.spec.ts:7:35           
@/generated/prisma/client  src/features/product/resolvers/product-review-query.resolver.spec.ts:7:35         
@/generated/prisma/client  src/features/product/resolvers/product-search-query.resolver.spec.ts:6:35         
@/generated/prisma/client  src/features/product/resolvers/product-storefront-query.resolver.spec.ts:4:35     
@/generated/prisma/client  src/features/product/services/product-best-seller.service.spec.ts:10:8            
@/generated/prisma/client  src/features/product/services/product-category.service.spec.ts:3:35               
@/generated/prisma/client  src/features/product/services/product-detail.service.spec.ts:5:35                 
@/generated/prisma/client  src/features/product/services/product-home.service.spec.ts:6:51                   
@/generated/prisma/client  src/features/product/services/product-review.service.spec.ts:6:52                 
@/generated/prisma/client  src/features/product/services/product-search.service.spec.ts:7:51                 
@/generated/prisma/client  src/features/product/services/product-storefront.service.spec.ts:3:35             
@/generated/prisma/client  src/features/region/resolvers/region-query.resolver.spec.ts:6:35                  
@/generated/prisma/client  src/features/region/services/region.service.spec.ts:5:35                          
@/generated/prisma/client  src/features/review/repositories/review-listing.repository.ts:10:24               
@/generated/prisma/client  src/features/review/types/review-listing.type.ts:1:38                             
@/generated/prisma/client  src/features/search/repositories/search.repository.spec.ts:2:35                   
@/generated/prisma/client  src/features/search/repositories/search.repository.ts:4:24                        
@/generated/prisma/client  src/features/search/resolvers/search-entry-query.resolver.spec.ts:12:35           
@/generated/prisma/client  src/features/search/resolvers/search-result-query.resolver.spec.ts:10:35          
@/generated/prisma/client  src/features/search/services/search-entry.service.spec.ts:7:35                    
@/generated/prisma/client  src/features/search/services/search-keyword-rank.service.spec.ts:6:35             
@/generated/prisma/client  src/features/search/services/search-result.service.spec.ts:11:35                  
@/generated/prisma/client  src/features/seller/repositories/seller.repository.spec.ts:5:48                   
@/generated/prisma/client  src/features/seller/repositories/seller.repository.ts:8:8                         
@/generated/prisma/client  src/features/seller/resolvers/seller-content.resolver.spec.ts:12:35               
@/generated/prisma/client  src/features/seller/resolvers/seller-conversation.resolver.spec.ts:12:35          
@/generated/prisma/client  src/features/seller/resolvers/seller-order.resolver.spec.ts:10:35                 
@/generated/prisma/client  src/features/seller/resolvers/seller-product.resolver.spec.ts:36:35               
@/generated/prisma/client  src/features/seller/resolvers/seller-store.resolver.spec.ts:14:35                 
@/generated/prisma/client  src/features/seller/services/seller-audit.service.spec.ts:8:43                    
@/generated/prisma/client  src/features/seller/services/seller-audit.service.ts:22:33                        
@/generated/prisma/client  src/features/seller/services/seller-base.service.spec.ts:11:35                    
@/generated/prisma/client  src/features/seller/services/seller-base.service.ts:11:24                         
@/generated/prisma/client  src/features/seller/services/seller-content-mappers.helper.ts:9:46                
@/generated/prisma/client  src/features/seller/services/seller-conversation.service.spec.ts:10:35            
@/generated/prisma/client  src/features/seller/services/seller-conversation.service.ts:43:8                  
@/generated/prisma/client  src/features/seller/services/seller-custom-template.service.spec.ts:8:44          
@/generated/prisma/client  src/features/seller/services/seller-custom-template.service.ts:31:50              
@/generated/prisma/client  src/features/seller/services/seller-faq.service.spec.ts:7:35                      
@/generated/prisma/client  src/features/seller/services/seller-faq.service.ts:21:50                          
@/generated/prisma/client  src/features/seller/services/seller-media-url-ownership.spec.ts:10:35             
@/generated/prisma/client  src/features/seller/services/seller-option.service.spec.ts:8:44                   
@/generated/prisma/client  src/features/seller/services/seller-option.service.ts:37:50                       
@/generated/prisma/client  src/features/seller/services/seller-order.service.spec.ts:12:48                   
@/generated/prisma/client  src/features/seller/services/seller-order.service.ts:25:29                        
@/generated/prisma/client  src/features/seller/services/seller-product-image.service.spec.ts:8:35            
@/generated/prisma/client  src/features/seller/services/seller-product-image.service.ts:27:50                
@/generated/prisma/client  src/features/seller/services/seller-product-lifecycle.service.spec.ts:8:35        
@/generated/prisma/client  src/features/seller/services/seller-product-lifecycle.service.ts:36:8             
@/generated/prisma/client  src/features/seller/services/seller-product-query.service.spec.ts:12:35           
@/generated/prisma/client  src/features/seller/services/seller-product-taxonomy.service.spec.ts:8:35         
@/generated/prisma/client  src/features/seller/services/seller-product-taxonomy.service.ts:18:50             
@/generated/prisma/client  src/features/seller/services/seller-store-hours.service.spec.ts:7:35              
@/generated/prisma/client  src/features/seller/services/seller-store-hours.service.ts:35:50                  
@/generated/prisma/client  src/features/seller/services/seller-store-mappers.helper.ts:7:24                  
@/generated/prisma/client  src/features/seller/services/seller-store-policy.service.spec.ts:7:35             
@/generated/prisma/client  src/features/seller/services/seller-store-policy.service.ts:39:50                 
@/generated/prisma/client  src/features/seller/services/seller-store-profile.service.spec.ts:8:35            
@/generated/prisma/client  src/features/seller/services/seller-store-profile.service.ts:15:50                
@/generated/prisma/client  src/features/store/repositories/store-review.repository.ts:4:24                   
@/generated/prisma/client  src/features/store/repositories/store-wishlist.repository.ts:3:24                 
@/generated/prisma/client  src/features/store/repositories/store.repository.ts:5:47                          
@/generated/prisma/client  src/features/store/resolvers/store-detail-query.resolver.spec.ts:8:35             
@/generated/prisma/client  src/features/store/resolvers/store-pickup-schedule-query.resolver.spec.ts:5:35    
@/generated/prisma/client  src/features/store/resolvers/store-query.resolver.spec.ts:6:35                    
@/generated/prisma/client  src/features/store/resolvers/store-review-query.resolver.spec.ts:5:35             
@/generated/prisma/client  src/features/store/resolvers/store-search-query.resolver.spec.ts:8:35             
@/generated/prisma/client  src/features/store/resolvers/store-today-pickup-query.resolver.spec.ts:8:35       
@/generated/prisma/client  src/features/store/resolvers/store-wishlist-mutation.resolver.spec.ts:8:35        
@/generated/prisma/client  src/features/store/resolvers/store-wishlist-query.resolver.spec.ts:8:35           
@/generated/prisma/client  src/features/store/services/store-basic-info.helper.spec.ts:4:24                  
@/generated/prisma/client  src/features/store/services/store-basic-info.helper.ts:21:47                      
@/generated/prisma/client  src/features/store/services/store-detail-mappers.helper.spec.ts:6:24              
@/generated/prisma/client  src/features/store/services/store-detail.service.spec.ts:7:35                     
@/generated/prisma/client  src/features/store/services/store-listing.service.spec.ts:5:35                    
@/generated/prisma/client  src/features/store/services/store-pickup-schedule.service.spec.ts:11:8            
@/generated/prisma/client  src/features/store/services/store-review-mappers.helper.spec.ts:3:24              
@/generated/prisma/client  src/features/store/services/store-review.service.spec.ts:6:35                     
@/generated/prisma/client  src/features/store/services/store-search.service.spec.ts:9:42                     
@/generated/prisma/client  src/features/store/services/store-today-pickup.service.spec.ts:7:42               
@/generated/prisma/client  src/features/store/services/store-wishlist.service.spec.ts:11:35                  
@/generated/prisma/client  src/features/user/dto/inputs/my-orders.input.spec.ts:7:29                         
@/generated/prisma/client  src/features/user/dto/inputs/my-orders.input.ts:4:29                              
@/generated/prisma/client  src/features/user/repositories/review-report.repository.ts:7:8                    
@/generated/prisma/client  src/features/user/repositories/review.repository.ts:4:46                          
@/generated/prisma/client  src/features/user/repositories/user.repository.spec.ts:3:35                       
@/generated/prisma/client  src/features/user/repositories/user.repository.ts:10:8                            
@/generated/prisma/client  src/features/user/resolvers/user-engagement.resolver.spec.ts:6:35                 
@/generated/prisma/client  src/features/user/resolvers/user-mypage.resolver.spec.ts:6:35                     
@/generated/prisma/client  src/features/user/resolvers/user-notification.resolver.spec.ts:7:35               
@/generated/prisma/client  src/features/user/resolvers/user-order.resolver.spec.ts:6:35                      
@/generated/prisma/client  src/features/user/resolvers/user-profile.resolver.spec.ts:7:35                    
@/generated/prisma/client  src/features/user/resolvers/user-recent-view.resolver.spec.ts:9:35                
@/generated/prisma/client  src/features/user/resolvers/user-report.resolver.spec.ts:7:35                     
@/generated/prisma/client  src/features/user/resolvers/user-review.resolver.spec.ts:6:35                     
@/generated/prisma/client  src/features/user/resolvers/user-search.resolver.spec.ts:7:35                     
@/generated/prisma/client  src/features/user/resolvers/user-wishlist.resolver.spec.ts:9:35                   
@/generated/prisma/client  src/features/user/services/user-account-policy.helper.ts:1:29                     
@/generated/prisma/client  src/features/user/services/user-base.service.spec.ts:9:35                         
@/generated/prisma/client  src/features/user/services/user-engagement.service.spec.ts:11:35                  
@/generated/prisma/client  src/features/user/services/user-mypage.service.spec.ts:5:29                       
@/generated/prisma/client  src/features/user/services/user-notification.service.spec.ts:9:35                 
@/generated/prisma/client  src/features/user/services/user-order.service.spec.ts:5:35                        
@/generated/prisma/client  src/features/user/services/user-order.service.ts:12:29                            
@/generated/prisma/client  src/features/user/services/user-profile.service.spec.ts:10:35                     
@/generated/prisma/client  src/features/user/services/user-recent-view.service.spec.ts:7:35                  
@/generated/prisma/client  src/features/user/services/user-report.service.spec.ts:11:35                      
@/generated/prisma/client  src/features/user/services/user-report.service.ts:19:35                           
@/generated/prisma/client  src/features/user/services/user-review.service.spec.ts:11:35                      
@/generated/prisma/client  src/features/user/services/user-review.service.ts:19:46                           
@/generated/prisma/client  src/features/user/services/user-search.service.spec.ts:5:35                       
@/generated/prisma/client  src/features/user/services/user-wishlist.service.spec.ts:7:35                     
@/generated/prisma/client  src/features/user/types/user-mypage-output.type.ts:2:34                           
@/generated/prisma/client  src/features/user/types/user-order-output.type.ts:1:34                            
@/generated/prisma/client  src/features/user/types/user-output.type.ts:6:8                                   
@/generated/prisma/client  src/prisma/prisma.service.ts:3:30                                                 
@/generated/prisma/client  src/prisma/soft-delete.middleware.spec.ts:4:24                                    
@/generated/prisma/client  src/prisma/soft-delete.middleware.ts:2:24                                         
@/generated/prisma/client  src/test/db/db-clock.ts:1:35                                                      
@/generated/prisma/client  src/test/db/prisma-test-client.ts:8:30                                            
@/generated/prisma/client  src/test/factories/account.factory.ts:6:8                                         
@/generated/prisma/client  src/test/factories/auth.factory.ts:9:8                                            
@/generated/prisma/client  src/test/factories/category.factory.ts:5:8                                        
@/generated/prisma/client  src/test/factories/notification.factory.ts:6:8                                    
@/generated/prisma/client  src/test/factories/order.factory.ts:7:8                                           
@/generated/prisma/client  src/test/factories/product.factory.ts:1:44                                        
@/generated/prisma/client  src/test/factories/recent-product-view.factory.ts:4:8                             
@/generated/prisma/client  src/test/factories/region.factory.ts:1:43                                         
@/generated/prisma/client  src/test/factories/review-report.factory.ts:6:8                                   
@/generated/prisma/client  src/test/factories/review.factory.ts:1:43                                         
@/generated/prisma/client  src/test/factories/search-event.factory.ts:1:48                                   
@/generated/prisma/client  src/test/factories/search-history.factory.ts:1:50                                 
@/generated/prisma/client  src/test/factories/search-keyword-rank-snapshot.factory.ts:1:35                   
@/generated/prisma/client  src/test/factories/seller.factory.ts:6:8                                          
@/generated/prisma/client  src/test/factories/store-wishlist.factory.ts:4:8                                  
@/generated/prisma/client  src/test/factories/store.factory.ts:1:42                                          
@/generated/prisma/client  src/test/factories/tag.factory.ts:1:40                                            
@/generated/prisma/client  src/test/factories/user-profile.factory.ts:1:48                                   
@/generated/prisma/client  src/test/modules/testing-module.builder.ts:4:35                                   
@/generated/prisma/client  src/test/sample.real-db.spec.ts:3:35                                              
@/generated/prisma/client  test/app.e2e-spec.ts:12:29                                                        
Unused exports (1)
RANKING_VALID_ORDER_STATUSES  src/features/store/index.ts:7:3
Unused exported types (5)
ProductCardFields  type  src/features/product/index.ts:13:8
ReviewLikeRankRow  type  src/features/review/index.ts:10:3 
ReviewLikesScope   type  src/features/review/index.ts:11:3 
ReviewStat         type  src/features/review/index.ts:13:3 
ReviewStatKey      type  src/features/review/index.ts:14:3 
Duplicate exports (1)
KEYWORD_RANK_SNAPSHOT_SIZE|MAX_POPULAR_KEYWORDS_LIMIT  src/features/search/constants/search.constants.ts

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

@github-actions

Copy link
Copy Markdown

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 97.62% 7756/7945
🟢 Branches 92.43% 2953/3195
🟢 Functions 96.15% 1522/1583
🟢 Lines 98.21% 7083/7212

Test suite run success

2837 tests passing in 275 suites.

Report generated by 🧪jest coverage report action from b9f50b3

@chanwoo7
chanwoo7 merged commit 28480aa into develop-msa Sep 14, 2026
11 checks passed
@chanwoo7
chanwoo7 deleted the refactor/product-card-unify branch September 14, 2026 22:47
@codecov

codecov Bot commented Sep 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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