feat(search): 검색어 기록(recordSearch)과 인기 검색어 시간별 스냅샷 - #251
Conversation
검색 진입 화면(figma search 05) '인기 검색어 TOP10 + 순위 변동 + HH:00 기준' 대응. spec 문서가 없어 시안 + 문답으로 정책을 확정했다. - recordSearch(keyword) mutation(OptionalJwt): 정규화(trim·공백 축약, 빈값/200자 초과 400) 후 SearchEvent 기록. 로그인 시 SearchHistory upsert(soft-delete 복원·last_used_at 갱신)와 한 트랜잭션. 검색 실행 시 1회 호출 계약(탭 전환·페이지네이션 제외). - popularSearchKeywords(limit=10, 최대 20): 최신 스냅샷 + 직전 스냅샷 비교 UP/DOWN/SAME/NEW. 스냅샷 없으면 빈 배열 + rankedAt null. - SearchKeywordRankSnapshot 모델(마이그레이션): 매시 정각 직전 24h SearchEvent 집계 TOP20 (count desc → keyword asc), uk(ranked_at, rank)로 멱등. 불변 로그라 deleted_at 없음. - @nestjs/schedule 도입(6.x — 12.x는 ESM 전용이라 jest CJS 변환 불가): 정각 크론 + 부팅 시 현재 정각 스냅샷 1회 생성. 실패는 로그만 남긴다. - common/utils/search-keyword: 정규화·단어 분리 순수 함수(후속 상품/매장 검색이 공유). - 시드: 시드 유저 소유 SearchEvent + 직전/현재 정각 스냅샷 2개(변동 4종 노출). resetSeedScope에 SearchEvent 정리 추가. 자체 판단(시안 외): 직전 스냅샷은 '가장 최근의 이전 스냅샷'(다운타임 허용), 동률은 keyword asc, 스냅샷 저장 20건/노출 10건. 테스트 21건: 정규화 유닛, recordSearch 로그인/비로그인/복원/400, 스냅샷 윈도우·TOP20· 멱등·빈 이벤트·soft-delete 제외, trend 4종·직전 스냅샷 탐색·limit, uk 충돌 흡수, 스케줄러 실패 삼킴, resolver 통합.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
🩺 NestJS Doctor — 90/100 (Excellent)진단 279건 (error 0).
architecture / security 상위 항목
|
🧹 knip — dead-code 리포트전체 리포트
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 713f7f27aa
ℹ️ 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".
| }): Promise<KeywordCountRow[]> { | ||
| const rows = await this.prisma.searchEvent.groupBy({ | ||
| by: ['keyword'], | ||
| where: { created_at: { gte: args.since, lt: args.until } }, |
There was a problem hiding this comment.
Exclude soft-deleted events from ranking counts
When a SearchEvent in the 24-hour window has deleted_at set, this predicate still includes it in the grouped count, so deleted searches can inflate searchCount, displace active keywords, and persist incorrect rankings in the hourly snapshot. This also contradicts the newly added soft-delete된 이벤트는 집계에서 제외한다 service test; add deleted_at: null to the aggregation filter.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
false positive: groupBy는 soft-delete Prisma extension의 루트 READ 대상(READ_ACTIONS에 groupBy 포함)이라 deleted_at: null이 자동 주입됨. 레포 규칙상 루트 READ에는 중복 명시하지 않음(CLAUDE.md). 같은 PR의 soft-delete된 이벤트는 집계에서 제외한다 실DB 테스트가 이를 검증하며 통과함. 기존 aggregateProductRecentOrderCounts(orderItem.groupBy)도 동일 전제.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Coverage report
Test suite run success1717 tests passing in 199 suites. Report generated by 🧪jest coverage report action from 713f7f2 |
배경
검색 진입 화면(figma
search/05) '인기 검색어 TOP10 + 순위 변동(▲/–/▼) + HH:00 기준' 대응. spec 문서가 없어 시안 + 문답으로 정책 확정(검색 화면 API 4 PR 중 1/4).변경
recordSearch(keyword)mutation (OptionalJwt): 정규화(trim·공백 축약, 빈값/200자 초과 400) 후SearchEvent기록. 로그인 시SearchHistoryupsert(soft-delete 복원·last_used_at 갱신)와 한 트랜잭션. 검색 실행 시 1회 호출 계약.popularSearchKeywords(limit=10, 최대 20): 최신 스냅샷 + 직전 스냅샷 비교UP/DOWN/SAME/NEW. 스냅샷 없으면 빈 배열 +rankedAt: null.SearchKeywordRankSnapshot모델(마이그레이션): 매시 정각 직전 24hSearchEvent집계 TOP20,uk(ranked_at, rank)멱등. 불변 로그라deleted_at없음.@nestjs/schedule6.x 도입(12.x는 ESM 전용 → jest CJS 변환 불가). 정각 크론 + 부팅 시 1회. 실패는 로그만.common/utils/search-keyword정규화·단어 분리 순수 함수(후속 PR의 상품/매장 검색이 공유).자체 판단(시안 외)
직전 스냅샷 = '가장 최근의 이전 스냅샷'(다운타임 허용), 동률 keyword asc, 저장 20/노출 10.
테스트
21건 추가 — 정규화 유닛, recordSearch 4경로, 스냅샷 윈도우·TOP20·멱등·soft-delete 제외, trend 4종, uk 충돌 흡수, 스케줄러, resolver 통합.
yarn validate통과, 로컬 부팅 스모크(쿼리·뮤테이션) 확인.