[TIL] 내일배움캠프 React 과정 2024.06.21

김형빈·2024년 6월 21일
0

내일배움캠프

목록 보기
45/81
post-custom-banner

오늘의 한 일

필터링 기능 구현하기

  • 이번 팀 프로젝트에서 맡은 주요 기능 중에 하나로 오른쪽 체크 박스를 선택하면 해당하는 업종과 가격대의 업소가 지도 및 하단의 목록에 뜨도록 하는 기능이다.

첫 번째로 사용한 방법

  • 업소 데이터를 zustand에 저장하여 체크박스를 선택할 때마다 해당하는 데이터를 필터링하고 체크 박스를 해제하면 전체 데이터에서 체크한 종류의 업소를 필터링하고 이를 다시 합치는 방식으로 구현하였다.
  • 업종 필터링까지는 크게 문제가 없었으나 가격 필터링까지 넣게 되면서 문제가 발생하였다.
  • 예를 들어, 음식점을 선택 해제하고 1~2만원의 가격대를 선택한 후 다시 음식점을 선택하는 상황에서 1~2만원 대의 음식점 정보를 다시 합쳐야 하는데 이 정보를 가져올 방법이 없었다.
  • 결국, 전체 데이터를 2번 필터링해서도 가져와 보고, 필터링 할 때마다 필터링 한 데이터과 필터링 된 데이터도 저장해 보았지만 해결하지 못하였다..

두 번째로 사용한 방법

  • 필터링이 어려운 로직이기는 해도 너무 어렵게 생각한 것 같았다.
  • 체크 박스를 선택할 때마다 이를 필터 리스트에 추가하고 컴포넌트에서 데이터를 필터링하는 방법은 어떨까?

예시 코드

//filter.store.js
const useFilterStore = create((set, get) => ({
  typeFilters: [],
  priceFilter: {},
  addPriceFilter: (filter) => {
    const prevFilters = get().typeFilters;
    set({
      typeFilters: [...prevFilters, filter]
    });
  },
  delPriceFilter: (filter) => {
    const deletedFilter = get().typeFilters.filter((prevFilter) => {
      return prevFilter.name !== filter.name;
    });
    set({
      typeFilters: deletedFilter
    });
  },
  setPriceFilter: (filter) => {
    set({
      priceFilter: filter
    });
  }
}));

export default useFilterStore;
//Filter.jsx
function Filter() {
  const { addPriceFilter, delPriceFilter, setPriceFilter } = useFilterStore(
    useShallow((state) => ({
      addPriceFilter: state.addPriceFilter,
      delPriceFilter: state.delPriceFilter,
      setPriceFilter: state.setPriceFilter
    }))
  );

  const handleType = ({ target }) => {
    const newFilter = { property: 'indutyNm', name: target.value };
    if (target.checked) {
      delPriceFilter(newFilter);
    } else {
      addPriceFilter(newFilter);
    }
  };
  const handlePrice = ({ target }) => {
    const newFilter = { property: 'priceRange', name: target.value };
    if (target.checked) {
      setPriceFilter(newFilter);
    } else {
      setPriceFilter({});
    }
  };
  
  return(
  	...
  )
}
//StoresMap.jsx
function StoresMap() {
  const { jejuStores } = useFilteredJejuStore(
    useShallow((state) => ({
      jejuStores: state.jejuStores
    }))
  );
  const [filteredStores, setFilteredStores] = useState(jejuStores);

  const { typeFilters, priceFilter } = useFilterStore(
    useShallow((state) => ({
      typeFilters: state.typeFilters,
      priceFilter: state.priceFilter
    }))
  );

  useEffect(() => {
    setFilteredStores(jejuStores);
    if (typeFilters.length > 0) {
      typeFilters.forEach((typeFilter) => {
        setFilteredStores((prevStore) => {
          return prevStore.filter((prevStore) => prevStore[typeFilter.property] !== typeFilter.name);
        });
      });
    }
    if (Object.keys(priceFilter).length > 0) {
      setFilteredStores((prevStore) => prevStore.filter((store) => store[priceFilter.property] === priceFilter.name));
    }
  }, [jejuStores, typeFilters, priceFilter]);
  
  return(
   ... 
  )
}
  • Filter 컴포넌트에서 filter.store에 업종과 가격대별 필터 정보를 저장하면 StoresMap 컴포넌트에서 jejuStores 데이터를 필터링 해준다.

결과

  • 잘 동작한다

아쉬운 점

  • 필터링 정보를 저장하고 데이터를 필터링하는데 까지는 기능 구현에 성공하였으나 데이터를 필터링 하는 로직을 컴포넌트에서 작성해야한다는 점이 아쉽다. 이를 함수로 분리하거나 다른 곳에서 로직을 처리할 수 있게 리팩토링 하고 싶다.
  • 또한 필터링된 데이터를 쓰고 싶을 때 많은 양의 코드가 필요하다는 점이 불필요하게 느껴져서 리팩토링이 필요하다.

오늘의 회고

이번주의 팀프로젝트도 끝이 났다. 캠프에서 리더라는 자리를 처음 맡은 만큼 기획에 대한 준비도, 마음가짐도 준비를 했지만 부족한 부분을 많이 느낀 한 주였다. 특히, 진행하는 속도가 느리다고 느껴져도 계속해서 어느 정도 진행했는지 확인 하는거 말고는 최대한 상대가 다치지 않게 속도를 끌어올릴 수 있는지 고민이 많이 되었다. 심지어 나 자신도 필터링 만들때는 삽질을 몇 번 했기에 더더욱 어느 지점에서 어떻게 얘기를 하는지가 고민되었다... 그 외에도 투표로 정하기는 했지만 내가 가져왔던 공공데이터 API에서 여러가지 문제가 발생한거, 회의를 할 때 진행을 제대로 하고 있는 건지 등등 기능 구현 외에도 고민을 너무 많이 하느라 더 빠르게 지쳐버렸다. 물론 좋은 경험들도 있었고, 열심히 하는 팀원들도 느낄수 있었지만, 유독 힘든 주였다. 그래도 만약에 다음 기회가 생긴다면 이 경험들에서 배운 걸 잘 사용해보자
profile
The secret of getting ahead is getting started.
post-custom-banner

0개의 댓글