• IceCraft - search검색부분(리팩토링), 디바운싱 적용하기

    2024. 6. 23.

    by. 서카츄

    검색하는 페이지에서 서버 부담을 줄이기 위해 디바운싱을 적용시켜 검색기능 리팩토링을 진행하였다.



    훅으로 만들어 빼두기

    import { useState, useEffect } from "react";
    
    const useDebounce = (value: string, delay: number = 500) => {
      const [debounced, setDebounced] = useState(value);
    
      useEffect(() => {
        const handler = setTimeout(() => setDebounced(value), delay);
        return () => clearTimeout(handler);
      }, [value, delay]);
    
      return debounced;
    };
    
    export default useDebounce;

     
     
     
     
     

    훅 불러와서 useDebounce 적용하기

    import React, { useState } from "react";
    import { getRoomsWithKeyword } from "@/utils/supabase/roomAPI";
    import SearchIcon from "@/assets/images/icon_search.svg";
    import S from "@/style/mainpage/main.module.css";
    import Image from "next/image";
    import { toast } from "react-toastify";
    import useGetRoomsSocket from "@/hooks/useGetRoomsSocket";
    import useDebounce from "@/hooks/useSearchDebounce";
    
    const RoomSearch = () => {
      const { setRooms } = useGetRoomsSocket();
      const [search, setSearch] = useState<string>("");
      const debouncedValue = useDebounce(search);
    
      //NOTE - 방 목록 검색
      const searchHandler = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        if (!search.trim()) return;
    
        try {
          const rooms = await getRoomsWithKeyword(debouncedValue);
          setRooms(rooms);
        } catch (error) {
          toast.error("검색 중 오류가 발생했습니다.");
        }
      };
    
      return (
        <form onSubmit={searchHandler}>
          <div className={S.roomSearch}>
            <label htmlFor="search">검색하기</label>
            <input
              type="text"
              id="search"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              placeholder="방 이름을 입력해 주세요."
            />
            <button>
              <Image src={SearchIcon} alt="search Icon" />
            </button>
          </div>
        </form>
      );
    };
    
    export default RoomSearch;

     
    사용방법은 매우 간단하게 적용했다
    커스텀 훅으로 빼둔 useDebounce를 input value내용을 handler에 넘겨서 
    마지막 요청에 값을 업데이트해서 수파베이스에 있는 데이터 내용을 불러온다.
    그리고 debouncedValue값이 업데이트 될 때 실행되도록 개선해 두었다.
     
     
     
     

    리팩토링

    "use client";
    
    import React, { useEffect, useState } from "react";
    import { getRoomsWithKeyword, getRooms } from "@/utils/supabase/roomAPI";
    import SearchIcon from "@/assets/images/icon_search.svg";
    import S from "@/style/mainpage/main.module.css";
    import Image from "next/image";
    import { toast } from "react-toastify";
    import useGetRoomsSocket from "@/hooks/useGetRoomsSocket";
    import useDebounce from "@/hooks/useSearchDebounce";
    import { FormSearchProps } from "@/types";
    
    const FormSearch = ({ placeholder }: FormSearchProps) => {
      const { setRooms } = useGetRoomsSocket();
      const [search, setSearch] = useState<string>("");
      const debouncedValue = useDebounce(search, 500);
    
      //NOTE - 메인페이지 방 목록 검색
      const searchHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
        setSearch(e.target.value);
      };
    
      useEffect(() => {
        const fetchRooms = async () => {
          try {
            if (!debouncedValue.trim()) {
              const allRooms = await getRooms(0, 20);
              setRooms(allRooms);
              return;
            }
    
            const roomKeyword = await getRoomsWithKeyword(debouncedValue);
            setRooms(roomKeyword);
          } catch (error) {
            toast.error("검색 중 오류가 발생했습니다.");
          }
        };
    
        fetchRooms();
      }, [debouncedValue]);
    
      return (
        <>
          <div className={S.roomSearch}>
            <label htmlFor="search">검색하기</label>
            <input type="text" id="search" value={search} onChange={searchHandler} placeholder={placeholder} />
            <button type="button">
              <Image src={SearchIcon} alt="search Icon" />
            </button>
          </div>
        </>
      );
    };
    
    export default FormSearch;

     
    0.5초마다 검색하게 만들었고, 사용자가 검색 내용을 비웠을때 다시 전체데이터를 불러오는 방식으로 리팩토링을 진행하였다.

     
     
     
     

    개념정리는 다음 포스팅에!

    Debounce와 Throttleing 개념(디바운싱&쓰로틀링)

    IceCraft - search검색부분(리팩토링), 디바운싱 적용하기검색하는 페이지에서 서버 부담을 줄이기 위해 디바운싱을 적용시켜 검색기능 리팩토링을 진행하였다.훅으로 만들어 빼두기import { useState, u

    seokachu.tistory.com

     

    댓글