[Codecamp-Week4] Throttling & Debouncing

·2022년 8월 1일
0
post-custom-banner

5주차에 쓰는 5주차에 배운 4주차 주제(?)
게시물 목록에서 검색버튼을 클릭하면 해당 제목이 검색되도록 하는 방법, 검색버튼 없이 input 창에 제목을 검색하면 자동으로 검색되도록 하는 방법에 대해 배웠다.
검색 버튼 없이 자동으로 검색되도록 하는 방법을 배우면서 Throttling(쓰로틀링)과 Debouncing(디바운싱)에 대해 알아보았다.
Throttling과 Debouncing에 대해 살펴보자!

1. Throttling, Debouncing 이란?

1) Throttling과 Debouncing

Throttling과 Debouncing 둘 다 Javascript 이벤트를 제어하는 방법이다.
두 가지 방법 모두 이벤트 핸들러가 많은 연산을 수행하는 경우에 대해 제약을 걸어 제어할 수 있는 수준으로 이벤트를 발생시키는 것을 목표로 하는 기술이다.

2) Throttling 이란?

Throttling(쓰로틀링)이란 연이어 발생한 이벤트에 대해 일정한 delay를 포함시켜 연속적으로 발생하는 이벤트는 무시하는 방식이다.
즉, 지정한 delay 동안 함수가 호출되더라도 무시하게 된다.
Throttling의 대표적인 예는 스크롤이 있다.

3) Debouncing 이란?

Debouncing(디바운싱)이란 연이어 발생한 이벤트를 하나의 그룹으로 묶어 처리하는 방식이다.
마지막 호출이 발생한 후, 일정 시간이 지날 때까지 추가적 입력이 없을 때 실행된다.
Debouncing의 대표적인 예는 검색기능이 있다.

스크롤에 대한 Throttling은 따로 실습을 하지 않은 바, 검색기능에서의 Debouncing에 대해서만 살펴보자! 검색 Debouncing은 Lodash 라이브러리를 사용하였다.

2. Debouncing 살펴보기 (with Lodash)

Lodash를 import하여 Boards title 검색 시 1초간 변화가 없을 경우 title 검색이 진행되도록 구현하였다. 또한, input에서 검색한 keyword가 title keyword와 일치할 경우 해당 keyword 글씨가 빨간색으로 나타나도록 설정하였다.

import { useQuery, gql } from "@apollo/client";
import styled from "@emotion/styled";
import { ChangeEvent, MouseEvent, useState } from "react";
import {
  IQuery,
  IQueryFetchBoardsArgs,
} from "../../src/commons/types/generated/types";
import _ from "lodash";
import { v4 as uuidv4 } from "uuid";

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

const Row = styled.div`
  display: flex;
  flex-direction: row;
`;

const Column = styled.div`
  width: 25%;
`;

export default function StaticRoutedPage() {
  const [keyword, setKeyword] = useState("");

  const { data, refetch } = useQuery<
    Pick<IQuery, "fetchBoards">,
    IQueryFetchBoardsArgs
  >(FETCH_BOARDS);

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

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

  const onClickPage = (event: MouseEvent<HTMLSpanElement>) => {
    if (!(event.target instanceof HTMLSpanElement)) return;
    refetch({ page: Number(event.target.id) }); // 해당 결과를 refetch하므로, 입력되지 않은 인자는 굳이 입력하지 않아도 그대로 재사용됨
  };

  return (
    <>
      검색어 입력 : <input type="text" onChange={onChangeSearch}></input>
      {data?.fetchBoards.map((el) => (
        <Row key={el._id}>
          <Column>{el.writer}</Column>
          <Column>
            {el.title
              .replaceAll(keyword, `#$%${keyword}#$%`)
              .split("#$%")
              .map((el) => (
                <span
                  key={uuidv4()}
                  style={{ color: keyword === el ? "red" : "black" }}
                >
                  {el}
                </span>
              ))}
          </Column>
        </Row>
      ))}
      {new Array(10).fill(1).map((_, index) => (
        <span key={index + 1} id={String(index + 1)} onClick={onClickPage}>
          {" "}
          {index + 1}{" "}
        </span>
      ))}
    </>
  );
}

<참조 : https://webclub.tistory.com/607>

profile
개발을 개발새발 열심히➰🐶
post-custom-banner

0개의 댓글