Skip to content

feat: 검색 메인 페이지#44

Merged
ho0010 merged 13 commits into
developfrom
feat/search-main
Jul 18, 2025
Merged

feat: 검색 메인 페이지#44
ho0010 merged 13 commits into
developfrom
feat/search-main

Conversation

@ho0010
Copy link
Copy Markdown
Collaborator

@ho0010 ho0010 commented Jul 13, 2025

#️⃣연관된 이슈

[UI] 검색 메인 페이지 #38

📝작업 내용

이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지 첨부 가능)

스크린샷 (선택)

  • 검색 메인 페이지는 검색 창 값에 따라 뷰가 변화합니다.

  • 검색창에 값이 없을때

image
  • 검색 중일때
image
  • 검색 했을때
image
  • 검색 결과가 없을때
image
  • applybook 화면
image

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요

search 페이지는 특히 분기처리가 많아서 좀 복잡해보이는데 가독성 개선을 위한 좋은 방법 있으시면 공유해주세요!

Summary by CodeRabbit

  • 신규 기능

    • 책 검색 페이지가 추가되어 최근 검색어, 인기 검색 도서, 검색 결과, 도서 신청 기능을 제공합니다.
    • "가장 많이 검색된 책" 목록과 최근 검색어 탭이 도입되었습니다.
    • 검색 결과가 없을 경우, 사용자가 직접 도서를 신청할 수 있는 안내 및 이메일 정보가 제공됩니다.
    • 그룹 검색 결과 컴포넌트가 명확하게 구분되어 적용되었습니다.
  • 버그 수정

    • 네비게이션 바에서 경로가 없는 경우 버튼이 표시되지 않도록 개선되었습니다.
    • 그룹 검색 경로가 일관되게 소문자로 통일되었습니다.
  • 개선 사항

    • 검색바에서 검색 완료 시 삭제 버튼이 숨겨지도록 동작이 개선되었습니다.
    • 모달 열기/닫기 동작이 더욱 직관적으로 변경되었습니다.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jul 13, 2025

Walkthrough

여러 검색 관련 기능이 새롭게 추가되었습니다. 책 검색 페이지, 책 신청 페이지, 최근 검색어, 가장 많이 검색된 책 목록, 그리고 검색 결과 컴포넌트가 도입되었습니다. 일부 기존 컴포넌트의 이름과 동작도 변경되었으며, 라우팅 경로 및 조건부 렌더링 로직이 보완되었습니다.

Changes

파일(들) 변경 요약
src/components/search/BookSearchResult.tsx, src/components/search/MostSearchedBooks.tsx 책 검색 결과 및 가장 많이 검색된 책을 보여주는 새로운 컴포넌트 추가
src/components/search/SearchBar.tsx isSearched라는 새로운 boolean prop 추가 및 삭제 버튼 조건부 렌더링 로직 수정
src/components/search/GroupSearchResult.tsx 컴포넌트명 및 기본 export를 GroupSearchResult로 변경
src/components/common/Filter.tsx 모달 토글 함수의 조건문을 단순화하여 항상 상태를 반전하도록 변경
src/components/common/NavBar.tsx Fab 컴포넌트가 path가 있을 때만 렌더링되도록 조건 추가
src/pages/search/Search.tsx, src/pages/search/ApplyBook.tsx 책 검색 및 책 신청 페이지 신규 추가, 상태 및 UI 로직 구현
src/pages/index.tsx /search, /search/applybook 라우트 추가 및 import 순서 정리
src/pages/group/Group.tsx 그룹 검색 경로를 /groupsearch로 소문자로 통일
src/pages/groupSearch/GroupSearch.tsx 검색 결과 컴포넌트 import 및 사용 부분을 새 이름으로 변경

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SearchPage
    participant BookSearchResult
    participant MostSearchedBooks
    participant ApplyBookPage

    User->>SearchPage: 방문/검색어 입력
    SearchPage->>MostSearchedBooks: (초기) 인기 책 목록 표시
    User->>SearchPage: 검색어 입력 및 검색
    SearchPage->>BookSearchResult: 검색 결과 요청 및 표시
    User->>BookSearchResult: '책 신청하기' 클릭
    BookSearchResult->>ApplyBookPage: 신청 페이지로 이동
Loading

Possibly related PRs

Suggested labels

✨ Feature, 🎨 Html&css

Poem

🐰
검색의 숲에 길을 내었네,
책 찾는 토끼는 신이 났지!
인기 책도, 최근 검색도 척척—
신청 페이지로 폴짝 뛰어가네.
새 길, 새 이름, 새 희망 싹트는
오늘도 코드밭에 꽃이 피었네.
📚✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10f6347 and 8b70c02.

📒 Files selected for processing (2)
  • src/components/search/GroupSearchResult.tsx (2 hunks)
  • src/pages/index.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/components/search/GroupSearchResult.tsx
  • src/pages/index.tsx
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (4)
src/pages/search/ApplyBook.tsx (1)

31-37: 높이 설정 개선 권장

height: 60vh 사용 시 다양한 화면 크기에서 일관성 있는 사용자 경험을 제공하기 어려울 수 있습니다. min-height를 사용하거나 flex 속성을 활용하는 것을 고려해보세요.

- height: 60vh;
+ flex: 1;
+ min-height: 300px;
src/components/search/BookSearchResult.tsx (1)

13-16: 함수를 더 간결하게 리팩토링하세요.

isEmptySearchedBookList 함수가 불필요하게 복잡합니다. 직접 boolean 값을 반환하는 것이 더 간결합니다.

-  const isEmptySearchedBookList = () => {
-    if (searchedBookList.length === 0) return true;
-    else return false;
-  };
+  const isEmptySearchedBookList = () => searchedBookList.length === 0;

또는 함수를 완전히 제거하고 인라인으로 사용할 수도 있습니다:

-        {isEmptySearchedBookList() ? (
+        {searchedBookList.length === 0 ? (
src/pages/search/Search.tsx (2)

20-54: 더미 데이터를 별도 파일로 분리하거나 모킹 라이브러리 사용을 고려하세요.

하드코딩된 더미 데이터가 컴포넌트 내부에 있어서 코드의 가독성을 떨어뜨리고 있습니다. 또한 외부 이미지 URL 사용은 서비스 안정성에 영향을 줄 수 있습니다.

다음과 같은 개선 방안을 고려해보세요:

  1. 더미 데이터를 별도 파일로 분리:
// src/mocks/searchData.ts
export const mockSearchedBooks: SearchedBook[] = [...]
export const mockRecentSearches: string[] = [...]
  1. 이미지 assets을 로컬에서 관리하거나 플레이스홀더 이미지 사용
  2. MSW 같은 모킹 라이브러리 도입 고려

117-127: 중복된 컴포넌트 렌더링을 단순화하세요.

동일한 컴포넌트가 type prop만 다르게 두 번 렌더링되고 있어 코드 중복이 발생하고 있습니다.

다음과 같이 단순화할 수 있습니다:

-            {isSearched ? (
-              <BookSearchResult
-                type={'searched'}
-                searchedBookList={dummySearchedBook}
-              ></BookSearchResult>
-            ) : (
-              <BookSearchResult
-                type={'searching'}
-                searchedBookList={dummySearchedBook}
-              ></BookSearchResult>
-            )}
+            <BookSearchResult
+              type={isSearched ? 'searched' : 'searching'}
+              searchedBookList={dummySearchedBook}
+            />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb3cd9e and 10f6347.

📒 Files selected for processing (12)
  • src/components/common/Filter.tsx (1 hunks)
  • src/components/common/NavBar.tsx (1 hunks)
  • src/components/search/BookSearchResult.tsx (1 hunks)
  • src/components/search/GroupSearchResult.tsx (2 hunks)
  • src/components/search/MostSearchedBooks.tsx (1 hunks)
  • src/components/search/SearchBar.tsx (2 hunks)
  • src/pages/group/CreateGroup.tsx (1 hunks)
  • src/pages/group/Group.tsx (1 hunks)
  • src/pages/groupSearch/GroupSearch.tsx (2 hunks)
  • src/pages/index.tsx (2 hunks)
  • src/pages/search/ApplyBook.tsx (1 hunks)
  • src/pages/search/Search.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/pages/search/ApplyBook.tsx (2)
src/components/common/Wrapper.tsx (1)
  • Wrapper (3-14)
src/styles/global/global.ts (2)
  • colors (4-53)
  • typography (56-76)
src/components/search/MostSearchedBooks.tsx (2)
src/components/common/BookSearchBottomSheet/BookSearchBottomSheet.styled.ts (3)
  • BookList (166-170)
  • BookItem (172-179)
  • BookTitle (202-207)
src/styles/global/global.ts (2)
  • typography (56-76)
  • colors (4-53)
src/components/search/BookSearchResult.tsx (2)
src/pages/search/Search.tsx (1)
  • SearchedBook (12-18)
src/styles/global/global.ts (2)
  • colors (4-53)
  • typography (56-76)
🔇 Additional comments (16)
src/pages/group/CreateGroup.tsx (1)

11-11: LGTM!

에셋 파일의 구조 개선을 위한 경로 변경으로 다른 새로운 컴포넌트들과 일관성을 유지하고 있습니다.

src/pages/search/ApplyBook.tsx (1)

8-27: 컴포넌트 구조 및 로직 양호

컴포넌트의 전체적인 구조와 네비게이션 로직이 적절하게 구현되어 있습니다.

src/pages/group/Group.tsx (1)

132-132: LGTM!

라우팅 경로를 소문자로 통일하여 웹 표준에 맞게 개선되었습니다.

src/pages/groupSearch/GroupSearch.tsx (2)

8-8: LGTM!

컴포넌트명을 더 명확하고 구체적으로 변경하여 코드의 가독성이 향상되었습니다.


60-60: LGTM!

import 변경과 일치하는 컴포넌트 사용으로 일관성이 유지되고 있습니다.

src/components/search/GroupSearchResult.tsx (1)

87-87: LGTM!

컴포넌트명과 export를 일관성 있게 변경하여 다른 파일들의 import와 완벽히 일치합니다.

Also applies to: 142-142

src/components/common/Filter.tsx (1)

23-23: 모달 토글 동작 개선이 적절합니다.

기존의 조건부 열기에서 직접 토글로 변경하여 사용자가 필터를 다시 클릭해서 모달을 닫을 수 있게 되었습니다. 이는 일반적인 드롭다운/모달 컴포넌트의 예상 동작입니다.

src/components/common/NavBar.tsx (1)

93-93: 방어적 프로그래밍으로 안전성이 향상되었습니다.

path prop이 falsy일 때 Fab 컴포넌트를 렌더링하지 않도록 하여 잠재적인 오류를 방지합니다.

src/pages/index.tsx (2)

15-17: import 경로 수정 및 새로운 컴포넌트 추가가 적절합니다.

GroupSearch import 경로의 대소문자가 수정되었고, 검색 기능을 위한 새로운 컴포넌트들이 올바르게 import되었습니다.


33-34: 검색 기능을 위한 라우팅 확장이 올바릅니다.

새로운 검색 페이지와 도서 신청 페이지에 대한 라우트가 적절히 추가되었습니다.

src/components/search/SearchBar.tsx (2)

12-12: 검색 상태 관리를 위한 prop 추가가 적절합니다.

isSearched prop 추가로 검색 후 UI 동작을 제어할 수 있게 되었습니다.

Also applies to: 15-22


36-38: 검색 후 삭제 버튼 숨김 로직이 UX를 개선합니다.

검색이 완료된 후에는 삭제 버튼을 숨겨서 사용자 혼란을 방지하는 좋은 UX 개선입니다.

src/components/search/MostSearchedBooks.tsx (1)

98-109: 접근성 개선을 위한 시맨틱 HTML 사용이 좋습니다.

BookList를 ul로, BookItem을 li로 사용하여 스크린 리더 접근성이 개선되었습니다. 순위 목록의 의미가 명확하게 전달됩니다.

src/components/search/BookSearchResult.tsx (2)

21-48: 렌더링 로직이 잘 구현되었습니다.

조건부 렌더링, 빈 상태 처리, 그리고 접근성을 위한 alt 텍스트 제공이 모두 적절하게 구현되어 있습니다.


50-132: 스타일링이 디자인 시스템과 일관되게 구현되었습니다.

colors와 typography 상수를 적절히 활용하여 일관된 스타일링을 구현했습니다.

src/pages/search/Search.tsx (1)

148-188: 레이아웃과 스타일링이 적절하게 구현되었습니다.

fixed positioning과 z-index를 활용한 레이어링, 반응형 디자인 고려가 모두 적절합니다.

onLeftClick={handleBackButton}
/>
<TextWrapper>
<MainText>texthip2025@gmail.com</MainText>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

하드코딩된 이메일 주소 개선 필요

이메일 주소가 하드코딩되어 있어 향후 변경 시 코드 수정이 필요합니다. 환경 변수나 설정 파일로 관리하는 것을 고려해보세요.

- <MainText>texthip2025@gmail.com</MainText>
+ <MainText>{process.env.REACT_APP_SUPPORT_EMAIL || 'texthip2025@gmail.com'}</MainText>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<MainText>texthip2025@gmail.com</MainText>
<MainText>{process.env.REACT_APP_SUPPORT_EMAIL || 'texthip2025@gmail.com'}</MainText>
🤖 Prompt for AI Agents
In src/pages/search/ApplyBook.tsx at line 21, the email address is hardcoded
directly in the JSX. To improve maintainability, replace the hardcoded email
with a value sourced from an environment variable or a configuration file.
Update the code to read the email from process.env or a config object and use
that variable in the JSX instead of the fixed string.

Comment on lines +118 to +122
const Cover = styled.img`
width: 45px;
height: 60px;
object-fit: cover;
`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

이미지 로딩 실패 처리를 추가해야 합니다.

외부 이미지 URL 사용 시 로딩 실패에 대한 fallback 처리가 필요합니다.

다음과 같이 개선하는 것을 권장합니다:

const Cover = styled.img`
  width: 45px;
  height: 60px;
  object-fit: cover;
+ background-color: ${colors.grey[400]};
`;

그리고 컴포넌트에서 onError 핸들러를 추가:

<Cover 
  src={book.coverUrl} 
  alt={`${book.title} 커버`}
  onError={(e) => {
    e.currentTarget.src = '/images/book-placeholder.jpg';
  }}
/>
🤖 Prompt for AI Agents
In src/components/search/MostSearchedBooks.tsx around lines 118 to 122, the
Cover styled image component lacks error handling for failed image loads. To fix
this, add an onError event handler to the Cover component usage that sets the
image source to a local fallback image (e.g., '/images/book-placeholder.jpg')
when the original image fails to load. This ensures a graceful fallback for
broken external image URLs.

Comment on lines +48 to +49
{/* 서버 응답 포맷을 모르기에 우선 하드 코딩 */}
<DateText>01.12. 기준</DateText>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

하드코딩된 날짜를 동적으로 처리하도록 개선이 필요합니다.

현재 하드코딩된 날짜는 임시 구현으로 보입니다. 프로덕션에서는 서버에서 받은 데이터를 기반으로 동적으로 표시되어야 합니다.

다음과 같이 개선하는 것을 권장합니다:

- {/* 서버 응답 포맷을 모르기에 우선 하드 코딩 */}
- <DateText>01.12. 기준</DateText>
+ <DateText>{formatDate(lastUpdated)} 기준</DateText>

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/components/search/MostSearchedBooks.tsx around lines 48 to 49, the date
"01.12." is hardcoded in the DateText component. Replace this hardcoded date
with a dynamic value sourced from the server response or component props. Ensure
the date is formatted correctly before rendering, so it updates based on actual
data rather than a fixed string.

Comment on lines +10 to +41
const dummyBooks: Book[] = [
{
id: 1,
title: '토마토 컵라면',
coverUrl: 'https://cdn.imweb.me/upload/S20230204e049098f5e744/e6fd3d849546d.jpg',
},
{
id: 2,
title: '사슴',
coverUrl: 'https://cdn.imweb.me/upload/S20230204e049098f5e744/e6fd3d849546d.jpg',
},
{
id: 3,
title: '호르몬 체인지지',
coverUrl: 'https://cdn.imweb.me/upload/S20230204e049098f5e744/e6fd3d849546d.jpg',
},
{
id: 4,
title: '호르몬 체인지지',
coverUrl: 'https://cdn.imweb.me/upload/S20230204e049098f5e744/e6fd3d849546d.jpg',
},
{
id: 5,
title: '호르몬 체인지지',
coverUrl: 'https://cdn.imweb.me/upload/S20230204e049098f5e744/e6fd3d849546d.jpg',
},
{
id: 6,
title: '호르몬 체인지지',
coverUrl: 'https://cdn.imweb.me/upload/S20230204e049098f5e744/e6fd3d849546d.jpg',
},
];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

더미 데이터에서 보안 및 데이터 품질 문제가 있습니다.

  1. 외부 URL 사용으로 인한 보안 및 가용성 위험
  2. 3번부터 6번까지 동일한 책 제목으로 복사-붙여넣기 오류 의심
  3. 모든 책이 동일한 외부 이미지 URL 사용

다음과 같이 개선하는 것을 권장합니다:

const dummyBooks: Book[] = [
  {
    id: 1,
    title: '토마토 컵라면',
-    coverUrl: 'https://cdn.imweb.me/upload/S20230204e049098f5e744/e6fd3d849546d.jpg',
+    coverUrl: '/images/book-placeholder.jpg',
  },
  {
    id: 2,
-    title: '사슴',
-    coverUrl: 'https://cdn.imweb.me/upload/S20230204e049098f5e744/e6fd3d849546d.jpg',
+    title: '어린 왕자',
+    coverUrl: '/images/book-placeholder-2.jpg',
  },
  {
    id: 3,
-    title: '호르몬 체인지지',
-    coverUrl: 'https://cdn.imweb.me/upload/S20230204e049098f5e744/e6fd3d849546d.jpg',
+    title: '1984',
+    coverUrl: '/images/book-placeholder-3.jpg',
  },
  // 각각 다른 책 정보로 수정
];

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/components/search/MostSearchedBooks.tsx between lines 10 and 41, the
dummyBooks array has security and data quality issues: it uses external image
URLs which pose security and availability risks, and books from id 3 to 6 have
duplicated titles and identical cover URLs likely due to copy-paste errors. To
fix this, replace the external image URLs with local or trusted internal assets,
ensure each book has a unique and meaningful title, and assign distinct cover
images for each book to improve data quality and security.

<Content>
{isSearching ? (
<>
(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

문법 오류: 불필요한 괄호를 제거하세요.

JSX 내에 의미 없는 괄호가 있어 문법 오류를 발생시킬 수 있습니다.

다음과 같이 수정하세요:

-            (
             {isSearched ? (
               <BookSearchResult
                 type={'searched'}
                 searchedBookList={dummySearchedBook}
               ></BookSearchResult>
             ) : (
               <BookSearchResult
                 type={'searching'}
                 searchedBookList={dummySearchedBook}
               ></BookSearchResult>
             )}
-            )

Also applies to: 128-128

🤖 Prompt for AI Agents
In src/pages/search/Search.tsx at lines 116 and 128, there are unnecessary
parentheses in the JSX code that cause syntax errors. Remove these redundant
parentheses to correct the JSX syntax and ensure the component renders properly.

Comment on lines +44 to +91
const [searchTerm, setSearchTerm] = useState('');
const [isSearching, setIsSearching] = useState(false);
const [isSearched, setIsSearched] = useState(false);

const [recentSearches, setRecentSearches] = useState<string[]>([
'딸기12',
'당근',
'수박245',
'참',
'메론1',
]);

const handleChange = (value: string) => {
setSearchTerm(value);
setIsSearched(false);
setIsSearching(value.trim() !== '');
};

const handleSearch = (term: string) => {
if (!term.trim()) return;
setIsSearching(true);
setIsSearched(true);
setRecentSearches(prev => {
const filtered = prev.filter(t => t !== term);
return [term, ...filtered].slice(0, 5);
});
};

const handleDelete = (recentSearch: string) => {
setRecentSearches(prev => prev.filter(t => t !== recentSearch));
};

const handleRecentSearchClick = (recentSearch: string) => {
setSearchTerm(recentSearch);
setIsSearched(true);
setIsSearching(true);
};

const handleBackButton = () => {
setSearchTerm('');
};

useEffect(() => {
if (searchTerm.trim() === '') {
setIsSearching(false);
setIsSearched(false);
}
}, [searchTerm]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

복잡한 상태 관리 로직을 useReducer로 리팩토링하는 것을 고려하세요.

현재 여러 개의 연관된 상태가 분산되어 관리되고 있어 복잡도가 높습니다. 상태 간의 의존성으로 인한 버그 발생 가능성이 있습니다.

useReducer를 사용한 상태 관리 패턴을 고려해보세요:

type SearchState = {
  searchTerm: string;
  isSearching: boolean;
  isSearched: boolean;
  recentSearches: string[];
};

type SearchAction = 
  | { type: 'SET_SEARCH_TERM'; payload: string }
  | { type: 'SUBMIT_SEARCH'; payload: string }
  | { type: 'CLEAR_SEARCH' }
  | { type: 'SELECT_RECENT_SEARCH'; payload: string };

function searchReducer(state: SearchState, action: SearchAction): SearchState {
  // 상태 업데이트 로직을 중앙화
}

이렇게 하면 상태 변화를 더 예측 가능하고 관리하기 쉽게 만들 수 있습니다.

🤖 Prompt for AI Agents
In src/pages/search/Search.tsx between lines 44 and 91, the current state
management uses multiple useState hooks for related states, causing complexity
and potential bugs. Refactor this by replacing all these useState calls with a
single useReducer hook that manages an object containing searchTerm,
isSearching, isSearched, and recentSearches. Define a reducer function that
handles actions like SET_SEARCH_TERM, SUBMIT_SEARCH, CLEAR_SEARCH, and
SELECT_RECENT_SEARCH to update the state accordingly. Update all handlers to
dispatch these actions instead of setting state directly, centralizing and
simplifying state logic.

@heeeeyong
Copy link
Copy Markdown
Collaborator

heeeeyong commented Jul 13, 2025

큰차이 없을거같기는한데... 조건부 렌더링부분을 함수로 빼내서 return() 부분에 넣으면 렌더링 영역의 구조에 대한 가독성은 좀 높아질거같은데 별로일까여?

@ho0010
Copy link
Copy Markdown
Collaborator Author

ho0010 commented Jul 18, 2025

큰차이 없을거같기는한데... 조건부 렌더링부분을 함수로 빼내서 return() 부분에 넣으면 렌더링 영역의 구조에 대한 가독성은 좀 높아질거같은데 별로일까여?

정확히 어디부분 말씀하시는지 모르겠네요.. 그 리뷰 남길때 코드에 마우스 올리면 버튼나오는데 누르고 드래그하면 리뷰 남기고 싶은 부분 지정 가능합니다!

@vercel
Copy link
Copy Markdown

vercel Bot commented Jul 18, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
thip ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 18, 2025 10:05am

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.

2 participants