[developic] 검색 페이지 - 검색 필터링 기능 업데이트

sue·2021년 6월 2일
0

developic project

목록 보기
18/28
post-thumbnail
post-custom-banner

기존 검색 기능 🚲

디벨로픽의 기존 검색 기능은 검색 결과에 대해 인기순, 최신순 두 가지의 정렬 옵션을 선택할 수 있었다.

그런데 인기순 정렬의 경우, 어쩔 수 없이 오래전에 작성한 게시글일 수록 인기도(누적 좋아요+조회수)가 높을 수 밖에 없는 상황이 발생한다면, 최신 글은 인기순 정렬에서 순위가 낮게 노출되어 유저가 원하는 검색 결과를 쉽게 얻지 못하는 문제가 나타날 수 있다고 생각했다.

사실 벨로그의 블로그 서비스를 잘 이용하면서도 검색 기능에서 기간 별로 검색 결과를 보는 것이 불가능한 데에 불편함을 느껴 이같은 옵션 기능이 있으면 좋겠다고 생각했고, 이 기능이 있는 Behance나 다른 블로그 서비스에서 편리함과 유용함을 경험했기 때문에 우리 프로젝트에서 꼭 구현해보고 싶었다.

따라서 인기순 정렬의 옵션으로 특정 기간을 필터링하여 그 기간에 해당하는 검색 결과를 출력하는 기능을 추가하기로 했다.


검색 옵션 기능 업데이트 🚀

SearchPost.tsx

// 정렬 옵션 데이터 설정 
export const sortOptionData = [
  { name: '인기순', value: 'popular' },
  { name: '최신순', value: 'recent' },
];
// 기간 필터링 옵션 데이터 설정 
export const dateOptionData = [
  { name: '모든 기간', value: 'all' },
  { name: '최근 24시간', value: 'day' },
  { name: '최근 1주일', value: 'week' },
  { name: '최근 1개월', value: 'month' },
];

export default function SearchPost(): JSX.Element {
  const { pageData, getSearchListDispatch, hasMore } = useList();
  const [currentSort, setCurrentSort] = useState(sortOptionData[0]); // 정렬 기본값: 인기순 
  const [currentDate, setCurrentDate] = useState(dateOptionData[0]); // 기간 기본값: 모든 기간
  const { query } = useRouter();
  
  // 쿼리 키워드가 입력되면, 검색결과를 얻어오는 기능 디스패치 실행, 이때 전달하는 객체값으로 sort 옵션이 들어간다. 
  useEffect(() => {
    if (query.keyword) {
      getSearchListDispatch({
        query: query.keyword,
        sort: currentSort.value as 'popular' | 'recent',
        type: 'post',
        term: currentDate.value as 'all' | 'day' | 'week' | 'month',
        limit: 12,
        offset: page * 12,
      });
    }
  }, [query, currentSort, currentDate, getSearchListDispatch, page]);

  return (
    <SearchPageWithNavLayout>
      <SearchContentBox>
        <div className="sort-option">
          <SortOption 
            sortOptionData={sortOptionData}
            setCurrentSort={setCurrentSort}
            currentSort={currentSort}
          /> // SortOption 컴포넌트로 정렬 옵션 데이터를 넘겨준다. 인기순, 최신순 정렬 옵션을 출력하는 컴포넌트가 된다. 
          {currentSort.value === sortOptionData[0].value && (
            <SortOption
              sortOptionData={dateOptionData}
              setCurrentSort={setCurrentDate}
              currentSort={currentDate}
            /> // 현재 검색 정렬 옵션 값이 인기순이라면, 추가 SortOption 컴포넌트를 출력하고 기간 필터링 옵션 데이터를 넘겨준다. 기간 필터링 옵션을 출력하는 컴포넌트가 된다.   
          )}
        </div>
        {(pageData as SearchPageDataType).post &&
          (pageData as SearchPageDataType).post.length >= 1 && (
            <>
              <SearchResultCount
                searchTitle={SearchNavData[0].name}
                resultCount={(pageData as SearchPageDataType).post.length}
              />
              <SearchPostCardList />
              <FetchMoreTrigger />
            </>
          )}
      </SearchContentBox>
    </SearchPageWithNavLayout>
  );
}

먼저 정렬 옵션 데이터와 기간 필터링 옵션 데이터를 설정해주었다. 그리고 이 데이터를 바탕으로 현재 선택된 정렬 옵션과 현재 선택된 기간을 변화시킬 수 있는 각각의 상태를 만들어준다. 검색어가 입력되어 query.keyword값이 존재하는 경우, useEffect로 검색 결과를 받아오는 디스패치를 실행하는데 이때 전달해야 하는 값으로 정렬과 기간 옵션을 추가로 넣어주었다.

다음으로는 SortOption 컴포넌트로 정렬 옵션 데이터를 넘겨준다. 인기순, 최신순 정렬 옵션을 출력하며 클릭으로 선택 가능한 컴포넌트를 만들어준다.

또 현재 검색 정렬 옵션 값이 인기순일 경우, 추가 SortOption 컴포넌트를 출력하도록 하고 기간 필터링 옵션 데이터를 넘겨준다. 기간 필터링 옵션을 보여주고 선택할 수 있는 컴포넌트가 된다.

SortOption.tsx

type SortOptionPropsType = {
  sortOptionData: { name: string; value: string }[];
  setCurrentSort: React.Dispatch<React.SetStateAction<{ name: string; value: string }>>;
  currentSort: { name: string; value: string };
};

export default function SortOption({
  sortOptionData,
  setCurrentSort,
  currentSort,
}: SortOptionPropsType): JSX.Element {
  const sortDropdownRef = useRef<HTMLDivElement>(null);

  const [isSortActive, setIsSortActive] = useOutsideClick(sortDropdownRef, false);
  const onClickSortBtn = useCallback(() => {
    setIsSortActive(prev => !prev);
  }, [setIsSortActive]);

  return (
    <SearhSortOptionContainer>
      <div className="option__btn" onClick={onClickSortBtn}>
        <span>{currentSort.name}</span>
        <MdKeyboardArrowDown />
      </div>
      <div
        className={`sort__dropdown dropdown ${isSortActive ? 'sort-active' : ''}`}
        ref={sortDropdownRef}
      >
        <ul>
          {sortOptionData.map(sortOption => (
            <li
              key={sortOption.value}
              onClick={() => setCurrentSort(sortOption)}
              className={`${
                currentSort.value === sortOption.value ? 'item-active' : ' '
              }`}
            >
              <span>{sortOption.name}</span>
            </li>
          ))}
        </ul>
      </div>
    </SearhSortOptionContainer>
  );
}

SortOption 컴포넌트는 넘어온 정렬 옵션이나 기간 필터링 옵션을 출력하고, 클릭으로 상태를 변경시킬 수 있는 공통 컴포넌트다. 먼저 넘겨 받은 currentSort.name 값으로 옵션명을 보여준다. 마찬가지로 넘겨받은 sortOptionDatamap()을 실행해 옵션 리스트를 만든 뒤, onClick 이벤트 발생 시 현재 클릭된 옵션 상태로 업데이트 해주는 함수를 실행한다.


구현 결과


업데이트한 검색 옵션 기능은 인기순 정렬 선택 시, 원하는 기간 별로 필터링을 설정해 검색 결과를 탐색할 수 있다.


사실 이전까지는 검색 기능에 대해 깊게 생각해본 적이 없었다. 내게 검색이란 데이터와 사용자가 있는 사이트라면 으레 갖춰야 할 필수 기능 정도였다. 하지만 이번에 검색 기능을 구현하면서 내가 겪었던 검색 경험을 떠올리고, 여러 사이트를 분석해보면서 엄청난 잠재 능력을 가진 녀석이구나! 라는 생각이 들었다.

검색 결과의 질은 사이트의 가치를 판단하는 기준이 될 수 있다. 또한 사용자에게 더 나은 검색 경험을 제공하는 일은 결국 서비스의 비지니스 임팩트에도 영향을 미칠 수밖에 없을 것이다. 이에 관한 개인적인 경험 하나를 꺼내보자면, 패션 쇼핑몰 앱으로 유명한 브랜디와 지그재그를 함께 사용했던 적이 있었다. 두 앱 모두 많은 패션 아이템과 쇼핑몰을 노출하며, 혹할 만한 이벤트 푸시 알림을 자주 보내고, 여성 사용자들이 선호하는 광고 모델을 잘 선정했다. 마켓팅 측면에서 느낀 경험은 비슷했다는 얘기다. 그런데 나는 결국 지그재그의 단골 사용자가 되었다. 나의 발걸음을 잡은 건 바로 지그재그의 '비슷한 상품 이미지 검색 기능'이었다. 이 기능은 내가 보고 있는 상품의 이미지를 분석해 같거나 유사한 상품 목록을 보여줌으로써 해당 상품에 대한 좀 더 많은 사용자의 후기를 볼 수 있고, 합리적인 가격 비교를 가능하게 해주었기 때문이다.

물론 검색 기능이 사용자의 발걸음을 붙잡는 요인의 전부가 될 순 없지만 우리 서비스에서 데이터를 수집하는 게 첫 번째 단계라면, 수집한 데이터를 잘 제공하는 것은 그 다음으로 중요하게 생각해야 할 단계가 아닐까 생각했다. 아직은 작은 업데이트에 불과하더라도 검색으로 더 의미있는 가치를 얻을 수 있는 방향을 계속 고민해보고 싶다.

post-custom-banner

0개의 댓글