배경
상품 리뷰(product-review)와 매장 리뷰(store-review)가 repository·service·상수·DTO까지 병렬 구현되어 있다. jscpd 클론 42건 중 최대 클러스터(7건)가 이 쌍이다.
- repository:
aggregateLikeCounts/findLikedReviewIds는 바이트 단위 동일(둘 다 reviewLike 대상). 좋아요순 keyset raw SQL은 JOIN 대상(product 경유 vs store 직결)만 다르고 주석까지 동일. publicReviewWhere도 쌍.
- service:
fetchReviewIdPage/parseLikesCursor/hydrateReviews 구조·주석 동일 (product-review.service:136-210 ↔ store-review.service:62-140).
- 상수/DTO:
INVALID_LIKES_CURSOR 동일 문구, *_REVIEW_SORTS = ['LATEST','LIKES'] 동일.
리뷰 정렬·집계 정책이 바뀔 때 두 곳을 같이 고쳐야 하고, 한쪽만 고치는 불일치 위험이 상존한다(픽업 판정 #206과 같은 유형).
목표
공통 파이프라인(좋아요 집계·liked set·커서 파싱·페이지 조립)을 파라미터화해 단일 소스로 추출하고, product/store는 각자의 필터·조인 조건만 주입한다. raw SQL은 무리해서 통합하지 말고 공용화 가능한 범위를 설계 단계에서 판단한다.
수행 조건
참고
- 2026-08-30 위생 점검에서 식별. 난이도 대 — 별도 설계 필요.
배경
상품 리뷰(product-review)와 매장 리뷰(store-review)가 repository·service·상수·DTO까지 병렬 구현되어 있다. jscpd 클론 42건 중 최대 클러스터(7건)가 이 쌍이다.
aggregateLikeCounts/findLikedReviewIds는 바이트 단위 동일(둘 다 reviewLike 대상). 좋아요순 keyset raw SQL은 JOIN 대상(product 경유 vs store 직결)만 다르고 주석까지 동일.publicReviewWhere도 쌍.fetchReviewIdPage/parseLikesCursor/hydrateReviews구조·주석 동일 (product-review.service:136-210 ↔ store-review.service:62-140).INVALID_LIKES_CURSOR동일 문구,*_REVIEW_SORTS = ['LATEST','LIKES']동일.리뷰 정렬·집계 정책이 바뀔 때 두 곳을 같이 고쳐야 하고, 한쪽만 고치는 불일치 위험이 상존한다(픽업 판정 #206과 같은 유형).
목표
공통 파이프라인(좋아요 집계·liked set·커서 파싱·페이지 조립)을 파라미터화해 단일 소스로 추출하고, product/store는 각자의 필터·조인 조건만 주입한다. raw SQL은 무리해서 통합하지 말고 공용화 가능한 범위를 설계 단계에서 판단한다.
수행 조건
참고