Skip to content

feat: 일반 탐색 최근 검색어 구현#893

Merged
m6z1 merged 2 commits into
developfrom
feat/892
Jun 9, 2026
Merged

feat: 일반 탐색 최근 검색어 구현#893
m6z1 merged 2 commits into
developfrom
feat/892

Conversation

@m6z1

@m6z1 m6z1 commented Jun 6, 2026

Copy link
Copy Markdown
Member

📌𝘐𝘴𝘴𝘶𝘦𝘴

📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯

  • 일반 탐색 화면에 최근 검색어 섹션 UI를 추가했습니다.
  • 최근 검색어 조회/개별 삭제/전체 삭제 API 연동을 추가했습니다.
  • 검색창 X 클릭 시 검색 결과 및 empty view 상태가 초기화되도록 수정했습니다.

📷𝘚𝘤𝘳𝘦𝘦𝘯𝘴𝘩𝘰𝘵

default.mp4

💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴

  • 삭제/전체 삭제 API 문서의 endpoint가 비어 있어 DELETE /novels/recent-searches/{recentSearchId}, DELETE /novels/recent-searches 기준으로 구현했습니다.

Summary by CodeRabbit

새로운 기능

  • New Features
    • 최근 검색 목록을 조회하고 탐색 화면에 표시할 수 있습니다.
    • 최근 검색 항목을 개별적으로 또는 일괄로 삭제할 수 있습니다.
    • 검색창 아래에 최근 검색 섹션이 추가되었습니다.

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Looking for one thing? Review this PR in Change Stack to search files, summaries, diffs, and code without losing your place.

Review Change Stack

Warning

Review limit reached

@m6z1, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 27 minutes and 43 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 628d298c-9152-4d88-81df-7954bf47b053

📥 Commits

Reviewing files that changed from the base of the PR and between f69765e and 9085c22.

📒 Files selected for processing (1)
  • app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt

Walkthrough

이 PR은 일반 탐색 화면에 서버 기반 최근 검색어 조회, 단건 삭제, 전체 삭제 기능을 구현합니다. 데이터 계층(DTO, Entity, API, Repository, 매퍼)부터 UI 계층(Model, Adapter, ViewModel, Activity)까지 일관되게 최근 검색 기능을 적층하고, 검색 기록 API 응답을 UI에 표시합니다.

Changes

최근 검색어 기능

Layer / File(s) Summary
데이터 응답 DTO 및 엔티티 모델
app/src/main/java/com/into/websoso/data/remote/response/RecentSearchesResponseDto.kt, app/src/main/java/com/into/websoso/data/model/RecentSearchesEntity.kt
RecentSearchesResponseDto는 JSON 응답의 id/keyword 필드를 직렬화하고, RecentSearchesEntity는 도메인 엔티티로 응답 구조를 미러링.
API 엔드포인트
app/src/main/java/com/into/websoso/data/remote/api/NovelApi.kt
최근 검색 조회, 단건 삭제, 전체 삭제를 위한 suspend 메서드 3개 추가.
Repository 메서드
app/src/main/java/com/into/websoso/data/repository/NovelRepository.kt
API 메서드를 래핑하는 Repository suspend 함수 3개 추가.
데이터 매퍼
app/src/main/java/com/into/websoso/data/mapper/NovelMapper.kt
RecentSearchesResponseDto.toData()로 응답 DTO를 엔티티로 변환.
UI 모델
app/src/main/java/com/into/websoso/ui/normalExplore/model/NormalExploreModel.kt
RecentSearchModel(id, keyword) 데이터 클래스 추가.
UI 매퍼
app/src/main/java/com/into/websoso/ui/mapper/NovelMapper.kt
RecentSearchEntity.toUi()로 엔티티를 UI 모델로 변환.
최근 검색 Adapter
app/src/main/java/com/into/websoso/ui/normalExplore/adapter/RecentSearchAdapter.kt
RecentSearchModel 목록을 RecyclerView에 표시. 아이템/삭제 버튼 클릭 콜백 및 DiffUtil 구현 포함.
ViewModel 상태 관리
app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt
recentSearches, isRecentSearchesVisible LiveData 추가. 초기화 및 검색 흐름 중에 최근 검색 조회 및 표시 여부 판정. deleteRecentSearch, deleteAllRecentSearches 메서드 추가.
Activity 통합
app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreActivity.kt
Adapter 초기화 및 ViewModel 상태 관찰. 검색 입력/버튼 처리를 searchKeyword() 공통 메서드로 통합. 최근 검색 아이템 클릭 시 searchRecentSearch() 호출.
UI 리소스
app/src/main/res/layout/activity_normal_explore.xml, app/src/main/res/layout/item_normal_explore_recent_search.xml, app/src/main/res/drawable/bg_normal_explore_recent_search_chip.xml, app/src/main/res/drawable/ic_normal_explore_recent_search_delete.xml, core/resource/src/main/res/values/strings.xml
최근 검색 섹션 레이아웃, 아이템 레이아웃(데이터 바인딩), 칩 배경 및 삭제 아이콘 드로어블, 제목/전체삭제 문자열 리소스.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Team-WSS/WSS-Android#826: NormalExploreActivity/ViewModel 검색 흐름 수정으로 최근 검색 표시 로직과 겹칠 수 있음.
  • Team-WSS/WSS-Android#874: updateSearchResult/updateSearchWordEmpty 메서드 수정 영역이 본 PR과 중복되어 병합 충돌 가능성 있음.

Suggested labels

🍯 [FEAT], [👸 공주 은영]

Suggested reviewers

  • s9hn
  • devfeijoa
  • Sadturtleman

Poem

🐰 최근 검색어 추적하며
서버와 UI 손잡고
삭제 버튼 한 번에
기록 싹 지워내는
깨끗한 검색 경험! ✨

🚥 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 PR 제목이 가장 중요한 변경사항을 명확하게 요약하고 있으며, 일반 탐색 화면의 최근 검색어 기능 구현을 직관적으로 설명합니다.
Linked Issues check ✅ Passed PR의 모든 코드 변경사항이 #892의 요구사항을 충족합니다. 최근 검색어 조회(fetchRecentSearches), 개별 삭제(deleteRecentSearch), 전체 삭제(deleteAllRecentSearches) 기능 구현 및 최대 30개 표시, 빈 상태에서 섹션 숨김 로직이 적용되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #892의 최근 검색어 기능 구현 및 검색창 X 클릭 초기화 요구사항과 관련되어 있으며, 범위를 벗어난 변경사항이 없습니다.
Description check ✅ Passed PR 설명이 필수 섹션(Issues, Work Description, Screenshot, To Reviewers)을 모두 포함하고 있으며, 구현 내용과 의도가 명확하게 기술되어 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/892

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 and usage tips.

@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)
app/src/main/res/layout/item_normal_explore_recent_search.xml (1)

39-39: ⚡ Quick win

접근성을 위한 contentDescription 추가를 권장합니다.

삭제 버튼에 contentDescription="@null"이 설정되어 있어 스크린 리더 사용자가 버튼의 기능을 알 수 없습니다. "최근 검색어 삭제"와 같은 설명 텍스트를 추가하는 것이 좋습니다.

♿ 접근성 개선 제안

strings.xml에 새 문자열 추가:

<string name="normal_explore_recent_search_delete_content_description">최근 검색어 삭제</string>

item_normal_explore_recent_search.xml 수정:

 <ImageView
     android:id="@+id/iv_normal_explore_recent_search_delete"
     android:layout_width="16dp"
     android:layout_height="16dp"
     android:layout_marginStart="6dp"
-    android:contentDescription="`@null`"
+    android:contentDescription="`@string/normal_explore_recent_search_delete_content_description`"
     android:padding="4dp"
     android:src="`@drawable/ic_normal_explore_recent_search_delete`" />
🤖 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 `@app/src/main/res/layout/item_normal_explore_recent_search.xml` at line 39,
Add an accessible contentDescription for the delete button by creating a new
string resource named normal_explore_recent_search_delete_content_description in
strings.xml (value: "최근 검색어 삭제") and then replace
android:contentDescription="`@null`" in item_normal_explore_recent_search.xml with
android:contentDescription="`@string/normal_explore_recent_search_delete_content_description`"
so screen readers announce the button purpose.
🤖 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
`@app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt`:
- Around line 156-157: The ktlint violation is due to method chaining formatting
on _recentSearches update; ensure each chained call is on its own line by moving
the .filterNot call to a new line after invoking orEmpty() so the chain in the
assignment to _recentSearches.value follows ktlint's one-call-per-line rule
(reference: _recentSearches, orEmpty(), filterNot, recentSearchId).

---

Nitpick comments:
In `@app/src/main/res/layout/item_normal_explore_recent_search.xml`:
- Line 39: Add an accessible contentDescription for the delete button by
creating a new string resource named
normal_explore_recent_search_delete_content_description in strings.xml (value:
"최근 검색어 삭제") and then replace android:contentDescription="`@null`" in
item_normal_explore_recent_search.xml with
android:contentDescription="`@string/normal_explore_recent_search_delete_content_description`"
so screen readers announce the button purpose.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 35a8b386-967a-4c99-9d7e-4b325999b2ef

📥 Commits

Reviewing files that changed from the base of the PR and between b2635e6 and f69765e.

📒 Files selected for processing (15)
  • app/src/main/java/com/into/websoso/data/mapper/NovelMapper.kt
  • app/src/main/java/com/into/websoso/data/model/RecentSearchesEntity.kt
  • app/src/main/java/com/into/websoso/data/remote/api/NovelApi.kt
  • app/src/main/java/com/into/websoso/data/remote/response/RecentSearchesResponseDto.kt
  • app/src/main/java/com/into/websoso/data/repository/NovelRepository.kt
  • app/src/main/java/com/into/websoso/ui/mapper/NovelMapper.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreActivity.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/adapter/RecentSearchAdapter.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/model/NormalExploreModel.kt
  • app/src/main/res/drawable/bg_normal_explore_recent_search_chip.xml
  • app/src/main/res/drawable/ic_normal_explore_recent_search_delete.xml
  • app/src/main/res/layout/activity_normal_explore.xml
  • app/src/main/res/layout/item_normal_explore_recent_search.xml
  • core/resource/src/main/res/values/strings.xml

Comment thread app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt Outdated
@m6z1 m6z1 added 🍯 [FEAT] 새로운 기능을 개발합니다. 🏹 궁사 명지 웹소소 공주의 은밀한 사냥생활 labels Jun 6, 2026

@Sadturtleman Sadturtleman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다!

다만 repo가 class로 되있는데 interface로 바꾸는건 어떨까 한번 여쭤봅니다!

@m6z1 m6z1 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sadturtleman 오 repo 를 추상화 했을 때의 장점이 무엇일까요 ?? !! ㅎㅎ
이제 하루가 아키텍처를 바꾸셔도 됩니다

@devfeijoa devfeijoa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다 뭉치! 👍🏻

repository를 추상화 하는 의견 좋네요 ! 저도 그에 대한 생각을 남기자면,,
interface 분리의 장점은 이해하지만 현재 NovelRepository는 구현체가 하나뿐이고 별도 대체 구현이나 명확한 분리가 필요한 상황은 아닌 것 같아 보입니다...! 지금 분리하면 테스트성,확장성 이점보다는 Repository/Impl 구조와 Hilt binding이 추가되는 비용이 더 커 보여서요...!
추후 local/remote 분리나 fake 구현이 필요해지는 시점에 분리해도 괜찮지 않을까요?
이에 대한 @m6z1 @Sadturtleman 뭉치와 하루의 의견이 궁금하네요 ㅎ ㅎ

@Sadturtleman

Sadturtleman commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

수고하셨습니다 뭉치! 👍🏻

repository를 추상화 하는 의견 좋네요 ! 저도 그에 대한 생각을 남기자면,, interface 분리의 장점은 이해하지만 현재 NovelRepository는 구현체가 하나뿐이고 별도 대체 구현이나 명확한 분리가 필요한 상황은 아닌 것 같아 보입니다...! 지금 분리하면 테스트성,확장성 이점보다는 Repository/Impl 구조와 Hilt binding이 추가되는 비용이 더 커 보여서요...! 추후 local/remote 분리나 fake 구현이 필요해지는 시점에 분리해도 괜찮지 않을까요? 이에 대한 @m6z1 @Sadturtleman 뭉치와 하루의 의견이 궁금하네요 ㅎ ㅎ

물론 그래도 되지만 이미 feed와 같이 리팩토링을 하면서 hilt binding을 추가하기도 했고, 아키텍쳐의 일관성이 깨지는 것 같아 바꾸는게 좋지 않을까? 라는 의견이었습니다!

@m6z1 m6z1 merged commit c79bc2d into develop Jun 9, 2026
2 checks passed
@m6z1 m6z1 deleted the feat/892 branch June 9, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🍯 [FEAT] 새로운 기능을 개발합니다. 🏹 궁사 명지 웹소소 공주의 은밀한 사냥생활

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 일반 탐색 최근 검색어 구현

3 participants