성능개선 이어서 들어가 봅시다!
Debounce 적용하기
상황
- 프로젝트 검색 기능을 구현할 때, 한 글자씩 입력할 때마다 API 요청하도록 구현했었다.
분석
- 위와 같은 방법으로 기능을 구현하면 필요 이상의 요청이 발생할 것이라고 판단했다.
- 검색 input 값을 콘솔창에 출력해봤더니 키워드 완성 전 필요 없는 값들이 입력이 발생할 때 마다 출력되고 있었다. 이렇게 순간적으로 많은 양의 데이터를 서버에 요청하면 서버에 부하가 발생하여 응답 속도가 느려질 것이다.
- 이 문제에 대한 해결책을 찾기 위해 구글링해본 결과, Debounce라는 기술을 활용할 수 있다고 한다. Debounce는 검색 기능 등에 자주 활용되는 기술로, 서버 요청 횟수를 효율적으로 개선할 수 있다고 한다. 이를 적용하여 개선해 보자.
💡 Debounce
- 사용자의 입력과 같은 이벤트 발생 시 일정 시간 동안 추가적인 이벤트 발생을 제어하는 기술이다.
- 검색 기능으로 예를 들면, 사용자가 검색어를 입력하는 동안에 매 입력마다 검색을 실행하지 않고, 입력이 끝난 후 일정 시간 동안 추가 입력이 없다면 검색을 실행한다.
🔎 사용방법
- useEffect를 사용하여 입력값 query가 변경될 때마다 디바운스를 적용하여 API 요청을 지연시킨다.
1️⃣ 컴포넌트 내에서 사용하기
- 코드 예시
// DebouncedSearch.jsx
import React, { useState, useEffect } from 'react';
function DebouncedSearch() {
const [query, setQuery] = useState('');
const [searchResults, setSearchResults] = useState([]);
// 입력 값이 변경될 때마다 타이머 설정
useEffect(() => {
const delayDebounceTimer = setTimeout(() => {
// 여기에 API 요청 코드 넣으면 됨
// 받아온 값을 setSearchResults에 저장
}, 1000); // 1s 디바운스 지연 시간
// 이전에 설정한 타이머를 클리어하여 디바운스 취소
return () => clearTimeout(delayDebounceTimer);
}, [query]);
function handleInputChange(event) {
setQuery(event.target.value);
}
return (
<div>
<input
type="text"
value={query}
onChange={handleInputChange}
placeholder="Search"
/>
<ul>
{searchResults.map((result, index) => (
<li key={index}>{result}</li>
))}
</ul>
</div>
);
}
export default DebouncedSearch;
2️⃣ 커스텀 훅으로 사용하기
- 코드예시
// useDebounce.jsx
import { useEffect, useState } from 'react';
export default function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value)
useEffect(()=>{
const timer = setTimeout(()=>{
setDebouncedValue(value)
}, delay)
return () => clearTimeout(timer)
}, [value])
return debouncedValue
}
// DebouncedSearch.jsx
import React, { useState } from 'react';
import useDebounce from './useDebounce'; // useDebounce 커스텀 훅 임포트
function DebouncedSearch() {
const [query, setQuery] = useState('');
const [searchResults, setSearchResults] = useState([]);
const debouncedQuery = useDebounce(query, 1000); // 1s 디바운스 지연 시간
useEffect(() => {
// 여기에 API 요청 코드 넣으면 됨
// 받아온 값을 setSearchResults에 저장
}, [debouncedQuery]);
function handleInputChange(event) {
setQuery(event.target.value);
}
return (
<div>
<input
type="text"
value={query}
onChange={handleInputChange}
placeholder="Search"
/>
<ul>
{searchResults.map((result, index) => (
<li key={index}>{result}</li>
))}
</ul>
</div>
);
}
export default DebouncedSearch;
📝 프로젝트에 Debounce 적용
요청 횟수 비교하기 (Debounce 적용 전)
'햄마요덮밥' 으로 검색한 결과, 요청 횟수 24건
요청 횟수 비교하기 (Debounce 적용 후)
'햄마요덮밥' 으로 검색한 결과, 요청 횟수 2건
반응형
'🤸♀️ 개발 회고 > Minicook' 카테고리의 다른 글
사이드 프로젝트 19편 | AWS EC2 인스턴스로 웹 서버 배포하기 -1 (react, putty) (0) | 2024.04.09 |
---|---|
사이드 프로젝트 18편 | 반응형 웹 캐러셀 제작하기 (swiper, react-slick) (0) | 2024.03.25 |
사이드 프로젝트 14편 | LCP 성능 최적화 -2 (bundle size 줄이기, react-icons, cra-bundle-analyzer ) (0) | 2024.03.20 |
사이드 프로젝트 13편 | LCP 성능 최적화 -1 (충격적인 성능 점수, LightHouse, 이미지 리사이징) (0) | 2024.03.14 |
사이드 프로젝트 11편 | 헤더 (라우터, 웹 브라우저 캐싱, redux, localStorage) (0) | 2024.03.08 |