JSON 검색 기능 구현하기 (갠프 리팩토링)

sohyuniyaa·2024년 1월 20일
0

회고록

목록 보기
6/6
post-thumbnail

개인 프로젝트로 진행했던 마켓제로 쇼핑몰을 리팩토링 하면서 검색 페이지에서 아주 조금? 은 아닌것 같고 꽤 헤맸던것 같다.
이유는 기존에 키워드를 다루는 상태가 너무 중구난방으로 중복되고 필요 이상으로 복잡하게 쓰이면서 계속 꼬였던게 문제였다.

기존에 문제였던 구현 방식

  • 상품명 혹은 키워드를 검색했을 때 해당 상품에 대한 데이터만 가져와야하는데 전체 데이터가 결과로 나옴.
  • 검색했을 때 키워드로 입력한 링크 키워드 값은 변경이 되지만 원하는 데이터 값으로 출력이 안됨.
    navigate(/search?keyword=${encodeURIComponent(keyword)});
  • 예를들어, 고구마를 입력했을 때 ‘고구마’에 대한 결과 의 타이틀이 나와야하지만
    ’’에 대한 결과 로만 계속 반복중 ..

🖍️ After

  • 문제점!

    • searchKeyword 상태가 애플리케이션의 여러 부분에서 다루어지고 있었다는 점
    • Header 컴포넌트로 갔다가 searchBar 컴포넌트로 갔다가 검색을 다루는 컴포넌트 부분에서 setSearchKeyword 를 통해 상태를 설정하고, 이 상태를 SearchList 컴포넌트에 prop으로 전달하여 사용하고 있었다.
      이런 방식은 상태 관리가 너무 복잡하며, 여러 부분에서 상태를 업데이트할 가능성이 있어 버그를 유발할 수 있다.
  • 해결방안!

    • 검색어는 URL의 쿼리 파라미터로 추가
    • react-router-dom의 useLocation 훅을 사용하여 SearchList 컴포넌트에서 직접 검색어를 가져오는 방식으로 코드를 수정
    • 가져온 검색어를 사용하여 상품명 기준으로 목록을 필터링

const SearchBar = () => {
	const navigate = useNavigate();

  const handleSubmit = (e) => {
    e.preventDefault();
    if (keyword.trim() !== '') {
      navigate(`/search?keyword=${encodeURIComponent(keyword)}`);
      setShowModal(false);
    }
  };

  const handleKeyPress = (e) => {
    if (e.key === 'Enter' && keyword.trim() !== '') {
      navigate(`/search?keyword=${encodeURIComponent(keyword)}`);
      setShowModal(false);
    }
  };
 export default SearchBar;

먼저, 검색바에서 검색어를 입력하거나 Enter를 눌러 검색할 때,
navigate 함수를 이용하여 검색 페이지로 이동하고, 이때 URL의 쿼리 파라미터로 keyword를 포함시킨다.


import { Link, useLocation } from 'react-router-dom';

const SearchList = () => {
  const location = useLocation();
  const searchKeyword =
    new URLSearchParams(location.search).get('keyword') || '';

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('/data/products.json');
        const data = await response.json();
        setAllProducts(data.allProducts);
      } catch (error) {
        console.error(error);
      }
    };
    fetchData();
  }, []);

  // 검색 키워드에 따른 상품 필터링
  useEffect(() => {
    let filteredProducts;

    if (searchKeyword !== '') {
      filteredProducts = allProducts.filter((product) =>
        product.productName.toLowerCase().includes(searchKeyword.toLowerCase()),
      );
    } else {
      filteredProducts = allProducts;
    }

    setSearchResult(filteredProducts);
    setCurrentPage(1); // 검색 키워드가 변경되면 첫 번째 페이지로 리셋
  }, [searchKeyword, allProducts]);

searchList 검색결과 페이지에서는 useLocation을 사용하여 URL의 위치를 가져온다.
위 코드에서 new URLSearchParams(location.search).get('keyword') || ''; 코드는 URL의 쿼리 파라미터에서 'keyword' 값을 가져오는 역할을 한다.
즉, searchKeywordURL의 검색 쿼리에서 'keyword'를 가져온다.

이렇게 가져온 'keyword' 값은 searchKeyword 상태에 저장되며,
이후 useEffect에서 allProducts를 필터링하는 데 사용된다.

그리고 현재 페이지를 1로 설정하여, 검색 결과가 변경되면 항상 첫 페이지부터 보여주게 한다.


리팩토링 계획이었던 상태관리나 메인, 로그인 시 유저 이름 업데이트, 장바구니와 위시리스트 등등 거의 모든 부분들을 수정했다.
완벽하진 않지만, 마무리가 잘 된것 같고 아직 필터링 하는 부분에서 살짝 고쳐야할 부분이 있긴 하지만 그래도 트러블슈팅 과정이 잘 해결되었다는거로 만족합니다.

profile
우당탕탕 프론트엔드 코린이 공간 🙆🏻‍♀️

0개의 댓글