2023. 1. 24. 11:18ㆍ프로젝트/플랜트하이커 - 식물생활 종합앱
debounce 란?
debounce는 반복적으로 실행되는 이벤트를 제어하는 기법으로 일정한 시간이 지난 후에 콜백함수를 실행하는 형태로 최적화하는 기법이다. 이번 리팩토링에서 debounce 가 적용된 곳은 검색 영역이다.
문제점
검색을 실행할때 기존에는 유저의 입력값이 변할 때 마다 서버호출을 통해 값을 업데이트해왔다. 이렇게 되면 단순한 검색을 실행할때 서버가 수십번 호출되는 문제가 있고, 이는 고스란히 서버의 부하로 이어진다.
반응성이 빠른것이 좋겠지만, 유저입장에서 자신이 입력하는 과정에 나오는 화면은 불필요한 정보이다. 몇단어만 입력해도 검색결과가 나오는것은 분명 좋겠지만 현재 상태에서는 단지 '가나다'를 검색하려고 해도 수차례 호출이 되는것을 볼 수 있다.
해결법
useDebounce 커스텀 hook 만들기
import { useEffect, useState } from "react";
export default function useDebounce<T>(value: T, delay: number) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
useDebounce hook 은 입력값과, delay 시간을 인자로 받고 해당 시간이 지난 후, debounce 된 값을 리턴하는 hook으로 만들었다.
const [searchKeyWord, setSearchKeyWord] = useState<string>("");
const debouncedValue = useDebounce<string>(searchKeyWord,debounceTime)
<input
type="text"
onChange={(e) => {
setSearchKeyWord(e.target.value);
}}
/>
위와 같이 커스텀 hook 에서 받은 debouncedValue 값을 선언해주고, Input을 통해 유저가 입력한 값을 컴포넌트 로컬 state로 받고, 해당 값을 이용해 debounce Value 를 받아 해당 값을 api 패칭을 진행하는 함수 (본 프로젝트에서는 react-query) 에 넘겨주는 형태로 사용했다.
export const debounceTime = 200 as const
딜레이 시간의 경우 constant 폴더의 time 디렉토리에서 따로 선언을 해놓고 불러오는 형태로 관리를 해주었는데 이렇게 사용한 이유는 처음에는 500ms 로 정하고 이용을 해봤는데 반응성이 많이 떨어진다는 느낌을 받았다.
이에 200ms 로 변경을 했더니 만족스러운 결과가 나왔다. 하지만 지극히 개인적인 경험이었기 때문에 나중에 A/B 테스트 등을 통해 최적의 값을 찾게 되면 변경될 값이기 때문에, 유지보수의 용이성을 위해 따로 관리하기로 했다.
적용 후 모습
시간에 쫒겨 프로젝트를 하면서 언젠간 고쳐야지.. 하고 생각만 했었는데 고치고나니 속이 후련하다
'프로젝트 > 플랜트하이커 - 식물생활 종합앱' 카테고리의 다른 글
[Refactoring] 끝났다고 끝이 아니다 리팩토링의 시작 - 주석달기 - (0) | 2022.12.20 |
---|---|
[React 이미지 압축전송] 필요 이상으로 큰 이미지를 서버로 넘기지 말자. Browser Image Compression 을 이용한 이미지 압축 후 전송 (1) | 2022.12.08 |
[Axios interceptor] 403응답(토큰만료)시 refresh Token 사용 자동화 (0) | 2022.11.24 |
[로컬스토리지 암호화] React Secure Storage를 이용한 로컬스토리지 데이터 암호 (0) | 2022.11.24 |
[MSW] MSW를 이용한 데이터 모킹 (Mock Service Worker) (0) | 2022.11.11 |