Skip to content

feat: 관리자 검색 키워드 통계 화면 추가#104

Merged
buddle031 merged 3 commits into
mainfrom
feat/admin-search-keyword-stats
Jun 29, 2026
Merged

feat: 관리자 검색 키워드 통계 화면 추가#104
buddle031 merged 3 commits into
mainfrom
feat/admin-search-keyword-stats

Conversation

@buddle031

@buddle031 buddle031 commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

✨ 작업 내용 한 줄 요약

  • 관리자 검색 키워드 통계 페이지를 추가하고 일별 검색 키워드 집계를 지원하도록 구현했습니다.

🛠️ 작업 내용

  • 관리자 메뉴에 집계 > 검색 키워드 페이지를 추가했습니다.
  • 검색 키워드 통계를 조회하는 관리자 전용 Controller, Service, DTO를 추가했습니다.
  • Thymeleaf 기반 검색 키워드 통계 화면을 구현했습니다.
  • 검색 시 누적 집계와 함께 일별 집계(keyword_daily_counts)가 저장되도록 확장했습니다.
  • 검색 키워드 통계 조회용 Reader/Adapter 및 Repository를 추가했습니다.
  • 운영 환경에서 사용할 DDL(03-keyword-counts.sql)에 keyword_daily_counts 테이블 및 인덱스를 추가했습니다.
  • LayerDependencyTest 규칙을 만족하도록 의존성 구조를 정리했습니다.

🧠 기술적 의사결정

  • 관리자 기능과 사용자 기능의 책임을 분리하기 위해 관리자 조회는 별도의 Controller/Service를 사용했습니다.
  • 조회 기능은 SearchKeywordStatisticsReader 포트를 통해 접근하도록 구성하여 Application 계층이 Infrastructure에 직접 의존하지 않도록 했습니다.
  • 기존 누적 검색 집계는 유지하면서 일별 집계를 별도 테이블로 관리하여 오늘 집계 수를 효율적으로 조회할 수 있도록 설계했습니다.
  • 운영 환경(ddl-auto=validate)을 고려하여 신규 테이블은 엔티티 자동 생성이 아닌 SQL 스크립트로 관리하도록 했습니다.

📚 참고 자료 (선택)

📷 스크린샷 (선택)

Summary by CodeRabbit

  • New Features

    • 관리자 화면에 검색 키워드 집계 페이지가 추가되었습니다.
    • 키워드별 전체 검색 횟수와 오늘 검색 횟수를 함께 확인할 수 있습니다.
    • 관리자 메뉴에 “집계 > 검색 키워드” 항목이 새로 표시됩니다.
  • Bug Fixes

    • 검색어 집계가 누적 값뿐 아니라 일별 값도 함께 반영되도록 개선되었습니다.
    • 검색 키워드 통계가 오늘 날짜 기준으로 정확히 표시되도록 정리되었습니다.
  • Chores

    • 초기 데이터베이스 설정에 검색 키워드 집계 관련 항목이 추가되었습니다.

@buddle031 buddle031 requested a review from mike7643 as a code owner June 29, 2026 05:24
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@buddle031, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 39 minutes

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable usage-based reviews in Billing to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information, and refer to the rate limits docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a278266a-8c35-46a0-8127-e7aaaaaf5ecd

📥 Commits

Reviewing files that changed from the base of the PR and between e9e2675 and f95617c.

📒 Files selected for processing (2)
  • scripts/db/03-keyword-counts.sql
  • src/main/java/com/zimdugo/locker/infrastructure/persistence/SearchKeywordCountRepository.java
📝 Walkthrough

Walkthrough

검색 키워드 일별 카운트 upsert 기능과 어드민 통계 조회 화면을 추가한다. DB에 keyword_daily_counts 테이블을 생성하고, 키워드 카운트 증가 시 일별 카운트도 함께 기록하며, 어드민 페이지에서 전체·오늘 집계를 테이블 형태로 조회할 수 있다.

Changes

검색 키워드 일별 집계 및 어드민 통계 기능

Layer / File(s) Summary
DB 스키마 및 로컬 초기화 설정
scripts/db/03-keyword-counts.sql, src/main/resources/application-local.yaml
keyword_counts·keyword_daily_counts 테이블과 인덱스 DDL을 추가하고, 로컬 프로파일 SQL 초기화 목록에 해당 스크립트를 등록한다.
도메인 계약 및 모델 정의
src/main/java/com/zimdugo/locker/domain/search/SearchKeywordDailyCountStore.java, ...SearchKeywordStatistic.java, ...SearchKeywordStatisticsReader.java
SearchKeywordDailyCountStore 인터페이스, SearchKeywordStatistic record, SearchKeywordStatisticsReader 인터페이스를 도메인 레이어에 추가한다.
일별 카운트 엔티티·레포지토리 및 통계 조회 쿼리
src/main/java/com/zimdugo/locker/infrastructure/persistence/SearchKeywordDailyCountEntity.java, ...SearchKeywordDailyCountRepository.java, ...AdminSearchKeywordStatisticsProjection.java, ...SearchKeywordCountRepository.java
SearchKeywordDailyCountEntity JPA 엔티티, upsert 네이티브 쿼리 레포지토리, 통계 projection 인터페이스, keyword_counts LEFT JOIN keyword_daily_counts 조회 메서드를 추가한다.
인프라 어댑터 구현 및 커맨드 서비스 확장
src/main/java/com/zimdugo/locker/infrastructure/adapter/SearchKeywordDailyCountStoreAdapter.java, ...AdminSearchKeywordStatisticsReaderAdapter.java, src/main/java/com/zimdugo/locker/application/search/SearchKeywordCountCommandService.java
SearchKeywordDailyCountStoreAdapter·AdminSearchKeywordStatisticsReaderAdapter를 구현하고, SearchKeywordCountCommandService.increase에 일별 카운트 증가 호출을 추가한다.
어드민 통계 서비스·컨트롤러·뷰
src/main/java/com/zimdugo/admin/application/dto/AdminSearchKeywordStatisticsResult.java, ...AdminSearchKeywordStatisticsService.java, ...AdminSearchKeywordStatisticsController.java, src/main/resources/templates/admin/layout.html, src/main/resources/templates/admin/search-keyword-statistics.html
AdminSearchKeywordStatisticsResult DTO, getStatistics() 서비스, /admin/statistics/search-keywords GET 컨트롤러, 사이드바 메뉴 항목, Thymeleaf 통계 템플릿을 추가한다.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant AdminSearchKeywordStatisticsController
  participant AdminSearchKeywordStatisticsService
  participant AdminSearchKeywordStatisticsReaderAdapter
  participant SearchKeywordCountRepository
  Browser->>AdminSearchKeywordStatisticsController: GET /admin/statistics/search-keywords
  AdminSearchKeywordStatisticsController->>AdminSearchKeywordStatisticsService: getStatistics()
  AdminSearchKeywordStatisticsService->>AdminSearchKeywordStatisticsReaderAdapter: readStatistics(today)
  AdminSearchKeywordStatisticsReaderAdapter->>SearchKeywordCountRepository: findStatistics(today) [native LEFT JOIN]
  SearchKeywordCountRepository-->>AdminSearchKeywordStatisticsReaderAdapter: List<AdminSearchKeywordStatisticsProjection>
  AdminSearchKeywordStatisticsReaderAdapter-->>AdminSearchKeywordStatisticsService: List<SearchKeywordStatistic>
  AdminSearchKeywordStatisticsService-->>AdminSearchKeywordStatisticsController: AdminSearchKeywordStatisticsResult
  AdminSearchKeywordStatisticsController-->>Browser: search-keyword-statistics 뷰 렌더링
Loading
sequenceDiagram
  participant SearchKeywordCountCommandService
  participant SearchKeywordCountStore
  participant SearchKeywordDailyCountStoreAdapter
  participant SearchKeywordDailyCountRepository
  Note over SearchKeywordCountCommandService: increase(keyword) 호출 시
  SearchKeywordCountCommandService->>SearchKeywordCountStore: increase(normalizedKeyword)
  SearchKeywordCountCommandService->>SearchKeywordDailyCountStoreAdapter: increase(normalizedKeyword, LocalDate.now(SEOUL_ZONE))
  SearchKeywordDailyCountStoreAdapter->>SearchKeywordDailyCountRepository: INSERT ... ON CONFLICT DO UPDATE upsert
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • JECT-Study/Zimdugo-4th-Server#102: 동일한 keyword_counts/03-keyword-counts.sql 및 키워드 카운트 증가 흐름을 도입한 PR로, 이번 변경이 해당 기반 위에 일별 집계와 통계 조회를 확장한 것이다.

Suggested reviewers

  • mike7643

Poem

🐰 키워드 세어 날마다 쌓고,
어드민 화면에 순위가 빛나네.
Seoul 시간 기준, 오늘도 집계!
테이블엔 전체·오늘 카운트 가득~
토끼가 코드 읽으며 깡충깡충 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 관리자 검색 키워드 통계 화면 추가라는 핵심 변경을 간결하게 잘 요약합니다.
Description check ✅ Passed 필수 섹션(요약, 작업 내용, 기술적 의사결정)을 모두 채웠고, 선택 항목은 비어 있어도 문제 없습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/admin-search-keyword-stats

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.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
scripts/db/03-keyword-counts.sql (1)

8-9: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

uk_keyword_counts_keyword와 중복되는 인덱스는 제거하세요.

Line 5의 UNIQUE 제약이 이미 keyword 인덱스를 만듭니다. 이 인덱스를 하나 더 두면 검색 집계 쓰기마다 같은 키를 두 번 갱신해서 저장공간과 쓰기 비용만 늘어납니다.

♻️ 제안 변경
-CREATE INDEX IF NOT EXISTS idx_keyword_counts_keyword
-    ON keyword_counts (keyword);;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/db/03-keyword-counts.sql` around lines 8 - 9, Remove the redundant
keyword index from the keyword_counts migration: the UNIQUE constraint on
keyword already creates an index, so the extra CREATE INDEX in the script should
be deleted to avoid duplicate write overhead. Update the SQL in
03-keyword-counts.sql so only the unique index created by the table definition
remains, and make sure no separate idx_keyword_counts_keyword definition is left
behind.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/zimdugo/locker/infrastructure/persistence/SearchKeywordCountRepository.java`:
- Around line 21-30: The native query in SearchKeywordCountRepository uses
projection aliases without quotes, which can break mapping to
AdminSearchKeywordStatisticsProjection getters. Update the SELECT aliases in the
repository query to use fixed quoted names for totalCount and todayCount so
PostgreSQL preserves the exact case and the projection properties resolve
correctly.

---

Nitpick comments:
In `@scripts/db/03-keyword-counts.sql`:
- Around line 8-9: Remove the redundant keyword index from the keyword_counts
migration: the UNIQUE constraint on keyword already creates an index, so the
extra CREATE INDEX in the script should be deleted to avoid duplicate write
overhead. Update the SQL in 03-keyword-counts.sql so only the unique index
created by the table definition remains, and make sure no separate
idx_keyword_counts_keyword definition is left behind.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0ea2d579-f82d-4c0d-a006-509edf9cc747

📥 Commits

Reviewing files that changed from the base of the PR and between c73c835 and e9e2675.

📒 Files selected for processing (17)
  • scripts/db/03-keyword-counts.sql
  • src/main/java/com/zimdugo/admin/application/AdminSearchKeywordStatisticsService.java
  • src/main/java/com/zimdugo/admin/application/dto/AdminSearchKeywordStatisticsResult.java
  • src/main/java/com/zimdugo/admin/entrypoint/AdminSearchKeywordStatisticsController.java
  • src/main/java/com/zimdugo/locker/application/search/SearchKeywordCountCommandService.java
  • src/main/java/com/zimdugo/locker/domain/search/SearchKeywordDailyCountStore.java
  • src/main/java/com/zimdugo/locker/domain/search/SearchKeywordStatistic.java
  • src/main/java/com/zimdugo/locker/domain/search/SearchKeywordStatisticsReader.java
  • src/main/java/com/zimdugo/locker/infrastructure/adapter/AdminSearchKeywordStatisticsReaderAdapter.java
  • src/main/java/com/zimdugo/locker/infrastructure/adapter/SearchKeywordDailyCountStoreAdapter.java
  • src/main/java/com/zimdugo/locker/infrastructure/persistence/AdminSearchKeywordStatisticsProjection.java
  • src/main/java/com/zimdugo/locker/infrastructure/persistence/SearchKeywordCountRepository.java
  • src/main/java/com/zimdugo/locker/infrastructure/persistence/SearchKeywordDailyCountEntity.java
  • src/main/java/com/zimdugo/locker/infrastructure/persistence/SearchKeywordDailyCountRepository.java
  • src/main/resources/application-local.yaml
  • src/main/resources/templates/admin/layout.html
  • src/main/resources/templates/admin/search-keyword-statistics.html

@buddle031 buddle031 merged commit cd4d704 into main Jun 29, 2026
3 checks passed
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