React

 

자바스크립트

 

검색어를 입력할 때마다 바로 검색을 실행하면 서버 자원이 낭비될 수 있습니다. 이를 방지하기 위해 다음과 같은 방법을 사용할 수 있습니다:

  1. 디바운싱(Debouncing): 사용자가 입력을 멈춘 후 일정 시간 동안 대기한 다음 검색 요청을 보내는 방법입니다.
  2. 스로틀링(Throttling): 일정 시간 간격으로만 검색 요청을 보내는 방법입니다.

일반적으로 디바운싱이 검색에 더 자주 사용됩니다. 이는 사용자가 입력을 멈춘 후에만 검색 요청을 보내기 때문입니다.

디바운싱을 사용한 예제

아래는 JavaScript와 디바운싱을 사용하여 검색 요청을 효율적으로 처리하는 예제입니다

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Search with Debouncing</title>
</head>
<body>
    <input type="text" id="searchInput" placeholder="Search...">
    <div id="results"></div>

    <script>
        // 디바운스 함수
        function debounce(func, delay) {
            let debounceTimer;
            return function(...args) {
                clearTimeout(debounceTimer);
                debounceTimer = setTimeout(() => func.apply(this, args), delay);
            };
        }

        // 검색 함수
        async function search(query) {
            if (!query) return;

            try {
                const response = await fetch(`/search?q=${encodeURIComponent(query)}`);
                const data = await response.json();
                displayResults(data);
            } catch (error) {
                console.error('Error fetching search results:', error);
            }
        }

        // 결과 표시 함수
        function displayResults(data) {
            const resultsDiv = document.getElementById('results');
            resultsDiv.innerHTML = '';
            data.results.forEach(result => {
                const resultItem = document.createElement('div');
                resultItem.textContent = result;
                resultsDiv.appendChild(resultItem);
            });
        }

        // 디바운스를 적용한 검색 함수
        const debouncedSearch = debounce(search, 300);

        // 입력 이벤트 리스너
        document.getElementById('searchInput').addEventListener('input', (event) => {
            debouncedSearch(event.target.value);
        });
    </script>
</body>
</html>

 

 

설명

 

  • 디바운스 함수: debounce 함수는 입력이 멈춘 후 일정 시간(delay) 동안 대기한 다음에 지정된 함수를 실행합니다. 입력이 계속되면 타이머를 재설정합니다.
  • 검색 함수: search 함수는 실제로 검색 요청을 서버에 보냅니다.
  • 결과 표시 함수: displayResults 함수는 서버에서 받은 검색 결과를 화면에 표시합니다.
  • 디바운스를 적용한 검색 함수: debouncedSearch는 debounce 함수를 사용하여 search 함수에 디바운싱을 적용한 것입니다.
  • 입력 이벤트 리스너: input 이벤트가 발생할 때마다 debouncedSearch 함수를 호출합니다.

 

이 방법을 사용하면 사용자가 입력을 멈춘 후에만 검색 요청이 발생하므로, 불필요한 서버 요청을 줄일 수 있습니다.

 

 

 


리액트-

하드처리

리액트에서 검색어 입력 시 디바운싱을 적용하여 서버 자원 낭비를 줄이는 방법을 설명하겠습니다. 이 예제에서는 useState와 useEffect 훅을 사용하여 상태를 관리하고, useCallback 훅을 사용하여 디바운스 함수를 생성합니다.

React 컴포넌트 예제

아래는 디바운싱을 적용한 React 컴포넌트의 예제입니다:

 

import React, { useState, useEffect, useCallback } from 'react';

function debounce(func, wait) {
    let timeout;
    return function(...args) {
        const context = this;
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(context, args), wait);
    };
}

const SearchComponent = () => {
    const [query, setQuery] = useState('');
    const [results, setResults] = useState([]);

    // 디바운스된 검색 함수
    const debouncedSearch = useCallback(
        debounce(async (searchQuery) => {
            if (!searchQuery) return;

            try {
                const response = await fetch(`/search?q=${encodeURIComponent(searchQuery)}`);
                const data = await response.json();
                setResults(data.results);
            } catch (error) {
                console.error('Error fetching search results:', error);
            }
        }, 300), // 300ms 디바운스 시간
        []
    );

    // query 상태가 변경될 때마다 debouncedSearch 호출
    useEffect(() => {
        debouncedSearch(query);
    }, [query, debouncedSearch]);

    // 입력 핸들러
    const handleInputChange = (event) => {
        setQuery(event.target.value);
    };

    return (
        <div>
            <input
                type="text"
                value={query}
                onChange={handleInputChange}
                placeholder="Search..."
            />
            <div>
                {results.map((result, index) => (
                    <div key={index}>{result}</div>
                ))}
            </div>
        </div>
    );
};

export default SearchComponent;

 

설명

  1. 디바운스 함수: debounce 함수는 입력이 멈춘 후 일정 시간(wait)이 지난 다음에 주어진 함수를 호출합니다. useCallback을 사용하여 메모이제이션된 디바운스 함수를 생성합니다.
  2. 상태 관리: query와 results 상태를 관리합니다. query는 입력된 검색어를, results는 검색 결과를 저장합니다.
  3. 검색 함수: debouncedSearch 함수는 디바운싱을 적용하여 서버에 검색 요청을 보냅니다.
  4. useEffect 훅: query 상태가 변경될 때마다 debouncedSearch 함수를 호출합니다. debouncedSearch 함수는 디바운싱을 적용하여 서버 요청을 최적화합니다.
  5. 입력 핸들러: handleInputChange 함수는 입력값이 변경될 때마다 query 상태를 업데이트합니다.
  6. 렌더링: input 태그와 검색 결과를 표시하는 div 태그를 렌더링합니다. results 배열을 맵핑하여 각 결과를 화면에 출력합니다.

 

이 방법을 사용하면 검색어 입력 시 디바운싱을 적용하여 서버 요청 빈도를 줄이고, 효율적인 검색 기능을 구현할 수 있습니다.

 

 

 

 

 

 

리액트 - lodash 이용

 

React와 TypeScript에서 lodash의 debounce 함수를 사용하여 디바운싱을 구현하는 코드를 다시 정리하겠습니다.

1. lodash 설치

먼저, lodash와 해당 타입 정의 파일을 설치합니다. 프로젝트 루트 디렉토리에서 다음 명령어를 실행합니다:

 

npm install lodash
npm install @types/lodash

npm install --save-dev @types/lodash

 

2. React 컴포넌트 코드

updateItem 함수에 디바운스를 적용한 전체 코드는 다음과 같습니다:

import React, { useCallback, useEffect, useState } from "react";
import "./App.css";
import Todo, { ItemType } from "./components/Todo";
import { Container, List, Paper } from "@mui/material";
import AddTodo from "./components/AddTodo";
import Call from "./service/ApiService";
import { debounce } from "lodash";

const DUMMY_DATA = [
  {
    todoId: "0",
    title: "Todo 컴포넌트 만들기",
    done: false,
  },
  {
    todoId: "1",
    title: "Todo 컴포넌트 만들기2",
    done: false,
  },
  {
    todoId: "2",
    title: "Todo 컴포넌트 만들기3",
    done: false,
  },
];

const App: React.FC = () => {
  const [items, setItems] = useState<ItemType[]>([]);
  const [errorMessage, setErrorMessage] = useState<string>("");

  const requestOptions = {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  };

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          "http://localhost:5000/api/todo",
          requestOptions
        );

        if (response.ok) {
          const res = await response.json();
          setItems(res.data);
        } else {
          console.error("Failed to fetch data");
        }
      } catch (error) {
        console.error(" 에러 :", error);
        setErrorMessage("데이터를 가져오지 못했습니다.");
      }
    };

    fetchData();
  }, []);

  // 추가 처리
  const addItem = (item: ItemType) => {
    Call("/todo", "POST", item).then((response) => {
      setItems(response.data);
    });
  };

  // 삭제 처리
  const deleteItem = (item: ItemType) => {
    Call("/todo", "DELETE", item).then((response) => {
      setItems(response.data);
    });
  };

  // 디바운스 적용된 수정 처리 함수
  const debouncedUpdateItem = useCallback(
    debounce((item: ItemType) => {
      Call("/todo", "PUT", item).then((response) => {
        setItems(response.data);
      });
    }, 300),
    []
  );

  const updateItem = (item: ItemType) => {
    debouncedUpdateItem(item);
  };

  let todoItems;

  if (items && items.length > 0) {
    todoItems = (
      <Paper className="mt50">
        <List>
          {items.map((item) => (
            <Todo
              item={item}
              key={item.todoId}
              deleteItem={deleteItem}
              updateItem={updateItem}
            />
          ))}
        </List>
      </Paper>
    );
  } else if (errorMessage) {
    todoItems = <h3 className="mt50">{errorMessage}</h3>;
  }

  return (
    <div className="App">
      <Container maxWidth="md" className="mt5">
        <AddTodo addItem={addItem} />
        <div className="TodoList">{todoItems}</div>
      </Container>
    </div>
  );
};

export default App;

 

 

설명

  1. lodash 설치: lodash와 해당 타입 정의 파일을 설치합니다.
  2. debounce 가져오기: import { debounce } from "lodash"; 구문을 사용하여 lodash에서 debounce 함수를 가져옵니다.
  3. 디바운스 적용된 수정 처리 함수: debouncedUpdateItem 함수는 debounce를 사용하여 생성됩니다. 이 함수는 300ms의 지연 시간을 가지며, 호출이 연속적으로 발생해도 마지막 호출 후 300ms가 지나야 실행됩니다.
  4. updateItem 함수: updateItem 함수는 debouncedUpdateItem을 호출하여 디바운스된 함수를 실행합니다.
  5. useCallback 사용: debouncedUpdateItem 함수는 useCallback을 사용하여 메모이제이션됩니다. 이렇게 하면 함수가 재생성되지 않고, 컴포넌트가 리렌더링되더라도 동일한 함수 인스턴스를 유지합니다.
  6. 렌더링: items 배열을 맵핑하여 각 Todo 컴포넌트를 렌더링합니다. Todo 컴포넌트는 item, deleteItem, updateItem props를 받습니다.

이 코드를 통해 updateItem 함수 호출 시 디바운싱이 적용되어 불필요한 서버 요청을 줄일 수 있습니다.

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

인간이란 것은 자기 자유의지로 스스로 자신에게 자초한 상처나 그 밖의 병은 타인의 손으로 가해진 것만큼 고통을 느끼지 않는다. -마키아벨리

댓글 ( 0)

댓글 남기기

작성

React 목록    more