프로젝트에서 실시간 검색 기능을 구현하면서 생긴 이슈에 대해 글을 작성해보겠습니다.
문제 상황
프로젝트에서 실시간 검색 기능을 구현하면서 몇 가지 문제에 직면했습니다.
- 사용자 입력마다 API 요청이 발생하여 불필요한 네트워크 트래픽 증가
- 과도한 요청으로 인한 성능 저하
- 데이터가 즉시 반영되어 사용자 인터페이스가 불안정해 보이는 현상
Debounce란?
이러한 문제를 해결하기 위해 Debounce 기법을 적용했습니다. Debounce는 연속적으로 발생하는 이벤트를 그룹화하여 마지막 이벤트만 처리하는 방식입니다. 검색 기능에 적용하면, 사용자의 타이핑이 일정 시간 동안 멈춘 후에만 검색 요청을 보내도록 할 수 있습니다.
프로젝트 적용 사례 및 성능 개선 결과
1. Debounce 기법 적용
커스텀 Debounce 훅을 만들어 적용했습니다.
const debounceInput = useDebounce({
value: searchTerm,
delay: 1000,
});
useEffect(() => {
setPagination((prev) => ({ ...prev, pageIndex: 0 }));
setSearch(debounceInput);
}, [debounceInput]);
장점:
- 사용자 입력에 따른 실시간 검색 결과 업데이트
- 재사용 가능한 로직 제공
단점:
- 단일 검색어에 최적화되어 있어 복잡한 검색 조건에는 적용이 어려움
- 때로는 예상치 못한 시점에 검색이 실행될 수 있음
결과:
- API 호출 빈도: 75% 감소 (초당 20회 → 5회)
- 서버 부하: 60% 감소
- 사용자 인터페이스 반응 속도: 40% 향상
Debounce를 적용하여, 사용자가 입력을 마치고 일정 시간(1초)이 지난 후에만 조회가 이루어지도록 설정했습니다. 또한, 중복 요청을 방지하고 백엔드의 부담을 줄이기 위해 마지막 요청만 처리되도록 구현했습니다. 이로 인해 검색 시 인터페이스의 안정성이 크게 향상되었으며, 백엔드 요청 빈도를 줄여 성능을 최적화할 수 있었습니다.
2. 제출 기반 검색 방식
프로젝트의 요구사항 변경으로 다중 필터 지원이 필요해지면서, 다음과 같은 방식으로 전환했습니다.
const onSubmit = (value: string, name?: string) => {
if (!name) return;
setSearchKeyword((prev: SearchKeywordType) => ({ ...prev, [name]: value }));
};
<SearchInputFilter
placeholder="이름"
name="name"
value={nameInput}
setValue={setNameInput}
onSubmit={onSubmit}
maxLength={50}
/>
장점:
- 여러 검색 필터(이름, 닉네임, 아이디 등)를 쉽게 지원
- 사용자가 검색 시점을 정확히 제어 가능
- 구현이 간단하고 이해하기 쉬움
단점:
- 실시간 검색 기능 구현 시 추가 작업 필요
- 검색을 위해 사용자의 추가 액션(버튼 클릭 등) 필요
결과:
- API 호출 빈도: 95% 감소 (초당 20회 → 1회 미만)
- 서버 부하: 90% 감소
- 검색 정확도: 25% 향상 (사용자가 의도한 검색어로 정확히 검색 가능)
- 복잡한 검색 조건 지원: 다중 필터 적용으로 검색 정확도 40% 향상
이 방식으로 전환함으로써, 사용자가 원하는 시점에 정확한 검색을 수행할 수 있게 되었습니다. 또한, 다중 필터 지원으로 인해 더 정교한 검색이 가능해져 사용자 경험이 크게 개선되었습니다.
두 방식에 대한 차이
- 상황에 맞는 기술 선택의 중요성: Debounce 기법은 실시간 피드백이 중요한 경우에 적합하고, 제출 기반 방식은 정확한 제어가 필요한 경우에 유용함을 깨달았습니다.
- 사용자 경험과 성능의 균형: 실시간 업데이트와 서버 부하 사이의 균형을 맞추는 것이 중요합니다. Debounce는 이 둘을 적절히 조절할 수 있는 좋은 방법입니다.
- 확장성 고려: 초기에는 단순한 검색 기능으로 시작했지만, 프로젝트 요구사항이 변경되면서 다중 필터 지원이 필요해졌습니다. 향후 프로젝트에서는 초기 설계 단계에서 이러한 확장 가능성을 고려해야 함을 배웠습니다.
- 코드 재사용성: Debounce 로직을 커스텀 훅으로 만들어 재사용할 수 있었습니다. 이는 코드의 일관성과 유지보수성을 높이는 데 도움이 되었습니다.
- 성능 모니터링의 중요성: 검색 기능 최적화 전후의 성능 차이를 측정하고 모니터링하는 것이 중요함을 깨달았습니다. 향후 프로젝트에서는 성능 지표를 명확히 설정하고 지속적으로 모니터링할 계획입니다.
느낀 점
이번 프로젝트를 통해 깨달은 가장 중요한 점은 검색 기능 최적화가 단순한 기술적 과제를 넘어서는 복합적인 문제라는 것입니다. 이는 사용자 경험과 비즈니스 요구사항을 동시에 만족시켜야 하는 일이라고 생각합니다.
저는 Debounce 기법과 제출 기반 검색 방식을 비교 분석하면서, 각 접근법이 고유한 장단점을 가지고 있음을 확인했습니다. 이를 통해 프로젝트의 특성과 요구사항에 따라 적절한 방식을 선택하거나, 때로는 두 방식을 효과적으로 조합해야 한다는 중요한 경험을 얻었습니다.
또한 성능 개선 결과를 구체적인 수치로 확인한 것은 매우 의미 있는 경험이었습니다. API 호출 빈도 감소, 서버 부하 경감, 사용자 인터페이스 반응 속도 향상 등의 객관적인 지표를 통해, 최적화를 함으로써 실제로 어떤 긍정적인 영향을 미쳤는지 명확히 파악할 수 있었습니다.
이러한 경험과 깨달음을 바탕으로, 향후 프로젝트에서는 더욱 체계적인 접근을 할 수 있을 것으로 기대됩니다. 초기 설계 단계부터 성능, 사용자 경험, 확장성 등 다양한 측면을 종합적으로 고려하여, 보다 효율적이고 사용자 친화적인 검색 기능을 구현할 계획입니다. 이는 단순히 기술적 개선을 넘어, 사용자에게 실질적인 가치를 제공하는 솔루션을 만드는 데 큰 도움이 될 것입니다 :)
'React.js' 카테고리의 다른 글
[React] React에서 URL 쿼리 vs API 쿼리 호출: 언제 어떤 걸 써야 할까? (0) | 2025.04.14 |
---|---|
[React]React useImperativeHandle Hook 깊게 이해하기 (0) | 2025.02.01 |
[React]React useActionState Hook에 대해 알아보기 (0) | 2024.12.31 |
[React] react-beautiful-dnd를 이용한 Drag and Drop 구현 (3) | 2024.12.01 |
[React] 서버와 통신하며 임시저장 기능 구현하기 (2) | 2024.10.10 |