practical debugging note
React 검색창 디바운스를 넣고도 요청이 두 번 나가던 이유
검색창에 디바운스를 넣었는데도 네트워크 요청이 중복되던 원인을 useEffect 의존성과 초기 실행 기준에서 정리했습니다.
문제를 발견한 장면 검색창에 300ms 디바운스를 넣었는데 개발자 도구 Network 탭에는 같은 검색어 요청이 두 번씩 찍혔다.
- 문제를 발견한 장면
- 중복을 만든 코드 모양
- 고친 방향
- 확인 방법
- 짧은 회고
문제를 발견한 장면
검색창에 300ms 디바운스를 넣었는데 개발자 도구 Network 탭에는 같은 검색어 요청이 두 번씩 찍혔다. 처음에는 React Strict Mode 때문이라고 넘기려 했지만, 운영 빌드에서도 일부 상황에서 중복 요청이 보였다.
직접 헷갈렸던 부분은 debouncedKeyword가 바뀔 때 요청하는 effect와, 페이지 번호가 바뀔 때 요청하는 effect를 따로 둔 점이었다. 검색어를 바꾸면 페이지를 1로 돌리고, 그 변화가 다시 요청을 만들었다.
중복을 만든 코드 모양
대략 이런 흐름이었다.
useEffect(() => {
setPage(1);
}, [debouncedKeyword]);
useEffect(() => {
fetchItems({ keyword: debouncedKeyword, page });
}, [debouncedKeyword, page]);
검색어가 바뀌면 첫 번째 effect가 page를 바꾸고, 두 번째 effect가 검색어 변화와 page 변화에 각각 반응했다.
고친 방향
검색 조건을 하나의 객체로 보고, 실제 요청을 만드는 기준을 한 군데로 모았다. 검색어 변경 이벤트에서 page를 같이 정리하고, effect는 최종 조건만 바라보게 했다.
const [query, setQuery] = useState({ keyword: "", page: 1 });
function handleKeywordChange(value: string) {
setQuery({ keyword: value, page: 1 });
}
useEffect(() => {
const controller = new AbortController();
fetchItems(query, { signal: controller.signal });
return () => controller.abort();
}, [query.keyword, query.page]);
여기에 디바운스된 값은 handleKeywordChange로 들어가기 전에만 적용했다. 상태를 여러 군데에서 고치지 않는 게 더 중요했다.
확인 방법
수정 뒤에는 단순히 화면이 맞는지만 보지 않았다.
- 검색어 한 글자 입력
- 빠르게 지우기
- 다른 검색어 입력
- 페이지 2로 이동
- 다시 검색어 변경
이 순서로 Network 탭에서 같은 URL이 연속으로 찍히는지 확인했다.
짧은 회고
디바운스는 요청 횟수를 줄여주지만, 상태 변경 경로가 두 갈래면 중복을 완전히 막아주지 못했다. 검색 조건처럼 서로 묶여 움직이는 값은 처음부터 한 덩어리로 다루는 편이 초보자가 읽기에도 덜 복잡하다.