[React] 검색프로세스, debouncing, throttling

yeni·2022년 11월 28일
0

검색 프로세스 이해

게시판에 들어오는 값들을 단어로 쪼개서 검색전용Board를 따로 만들고 그 단어가 몇 번 게시물에 있는지 게시물 번호를 저장해 놓은 뒤, 해당 단어로 검색이 들어오면 검색전용Board에 저장되어있는 Board의 값을 보여주는 형태로 보통 검색이 이루어진다.

토크나이징 : 토큰단위로 단어를 쪼개는 것
역인덱스 방식 : Data를 특정 키워드들로 구분지어, 해당하는 글들을 모아 저장하는 방식
이 방식을 쉽게 만들어 주는 도구가 Elastic Search
이 방식은 Disk에 저장되는 방식으로 컴퓨터가 꺼져도 저장이 유지되고 안전하지만 속도가 조금 떨어짐.
반면, Memory에 저장되는 방식은 Disk저장보다는 안정성이 떨어지지만 속도가 빠름
(많이 검색되는 것 위주로 메모리DB에 올려놓음)
Redis : 메모리저장기반 방식

CPU / RAM ⇢ 변수, 빠름 / DISK ⇢ 파일, 느림


debouncing

연이어 발생한 이벤트를 하나의 그룹으로 묶어 처리하는 방식으로 주로 그룹에서 마지막, 혹은 처음에 처리된 함수를 처리하는 방식으로 사용된다.

특정 시간 이내에 추가 입력이 없을 시, 마지막에 1회 실행

throttling:

연이어 발생한 이벤트에 대해 일정한 delay를 포함 시켜, 연속적으로 발생하는 이벤트는 무시하는 방식으로 사용된다.
ex) 스크롤 기능
특정 시간 이내에 추가 입력이 있어도 처음 1회만 실행

Lodash 디바운싱

lodash : JS 유틸리티 라이브러리, 내장되어있는 유용한 함수가 많으므로 참고해서 사용하면 좋다!

npm에서 설치 가능
yarn add lodash
yarn add --dev @types/lodash

import { gql, useQuery } from "@apollo/client";
import { ChangeEvent, MouseEvent, useState } from "react";
import _ from "lodash";
import { v4 as uuidv4 } from "uuid";

const FETCH_BOARDS = gql`
  query ($page: Int, $search: String) {
    fetchBoards(page: $page, search: $search) {
      _id
      writer
      title
      contents
    }
  }
`;

export default function StaticRoutedPage() {
  // const [search, setSearch] = useState("");

  const [keyword, setKeyword] = useState("");

  const { data, refetch } = useQuery(FETCH_BOARDS);

  const onClickPage = (event: MouseEvent<HTMLSpanElement>) => {
    // 검색에서 refetch할 때 사용한 search 검색어가 저장되어있는 상태이므로 추가로 search 포함하지 않아도 됨
    void refetch({ page: Number(event.currentTarget.id) });
  };

  // const onClickSearch = () => {
  //   // search에 들어간 단어로 다시 리패치하는데, 검색을 요청할 때는 무조건 1페이지로 로드 되므로 1페이지로 명시해주어야함
  //   void refetch({ search, page: 1 });
  // };

  const getDebounce = _.debounce((value) => {
    void refetch({ search: value, page: 1 });
    setKeyword(value);
  }, 500);

  const onChangeSearch = (event: ChangeEvent<HTMLInputElement>) => {
    getDebounce(event.currentTarget.value);

    // debounce 직접 만들기
    // setTimeout(() => {}, 1000);
  };

  // 더 안전한 시크릿 코드
  const mySecretCode = uuidv4();

  return (
    <div>
      검색어입력 : <input type="text" onChange={onChangeSearch} />{" "}
      {/* <button onClick={onClickSearch}>검색하기</button> */}
      {data?.fetchBoards.map((el) => (
        <div key={el._id}>
          <span style={{ margin: "10px" }}>
            {el.title
              .replaceAll(keyword, `${mySecretCode}${keyword}${mySecretCode}`)
              .split(mySecretCode)
              // .replaceAll(keyword, `@#$%${keyword}@#$%`)
              // .split("@#$%")
              .map((el) => (
                <span
                  key={uuidv4()}
                  style={{ color: el === keyword ? "red" : "black" }}
                >
                  {el}
                </span>
              ))}
          </span>
          <span style={{ margin: "10px" }}>{el.contents}</span>
        </div>
      ))}
      {new Array(10).fill(1).map((_, index) => (
        <span key={index + 1} id={String(index + 1)} onClick={onClickPage}>
          {index + 1}
        </span>
      ))}
    </div>
  );
}
profile
차곡차곡 쌓는 몌으니 개발노트

1개의 댓글

comment-user-thumbnail
2022년 11월 28일

쵝오

답글 달기