[ 문제 ]
입양동물 목록 페이지를 무한 스크롤(12개씩 데이터 요청)로 구현하고 완성,,!!했는데 문제가 생겼다.
첫번째 스크롤에서는 12개 데이터 불러옴 (정상),
두번째 스크롤에서는 24개 불러옴 (비정상),
세번째 스크롤에서는 12개 (정상),
네번째는 36개 (완전 비정상)
데이터를 일정하게 12개씩 불러오도록 구현했는데 실제로 자기 맘대로 불러오는 문제가 생김.....
다시 해보니까 그냥 무작위로 불러옴....
사용자가 페이지 하단에 도달할 때 중복으로 서버에 데이터를 요청하는 문제 발생
[ 원인 ]
페이지 하단에 도달할 때마다 데이터 요청 상태(isFetching)가 제대로 업데이트되지 않아서 발생한 문제였다.
이미 데이터를 로드 중임에도 불구하고 서버에 추가 데이터 요청이 반복되면서 불규칙한 갯수의 데이터 불러오기 및 성능 저하가 발생함.
[ 해결 과정 ]
1. useEffect에 [ isFetching ] 의존성 추가
• 수정 전 코드: useEffect에서 스크롤 이벤트 리스너를 추가할 때, 의존성 배열이 비어 있어 스크롤 이벤트를 감지할 때마다 isFetching 상태가 업데이트되지 않아 데이터 요청 중인 상태에서도 추가 데이터를 요청하게 되어 중복 요청이 발생할 수 있다.
• 수정 후 코드: useEffect에서 isFetching을 의존성으로 추가하여, 스크롤 이벤트가 발생할 때마다 isFetching 상태를 확인하여 현재 데이터 요청 중인지를 관리하여 이미 데이터를 요청 중일 때 중복 요청이 방지됨!
2. 데이터 요청 중복 방지 로직 추가 + 데이터 요청 true 상태 관리
if (isFetching) return; // 이미 요청 중이라면 함수 종료
setIsFetching(true); // 데이터 요청 시작
서버에 데이터 요청 전 isFetching상태를 확인하고 데이터를 요청하는 중이라면 함수를 종료하여 요청을 종료함.
만약 if문에서 데이터 요청을 안하고 있는 상태라면 실제 서버에 요청하기 전 isFetching 상태를 true(데이터 요청중)로 설정한다.
그런 후에 서버에 데이터 요청!
++
handleScroll 안에서 setIsFetching(true)를 처리하면, 스크롤 이벤트가 발생할 때마다 상태가 즉시 업데이트되어 실제로 데이터 요청이 발생하지 않아도 불필요하게 상태가 변경될 수 있다.
이를 방지하기 위해 setIsFetching(true)를 axiosAdoptionList 안에서 처리하여, 중복 요청을 방지하면서도 스크롤 이벤트 발생 시 불필요한 상태 업데이트를 줄이고, 데이터 요청 흐름에 맞춰 더 정확하게 상태를 관리할 수 있게 되었습니다.
3. 데이터가 없을 경우
데이터가 없는 경우(끝난 경우)에 대한 별도의 처리가 없어서 데이터가 더 이상 없을 때도 추가로 요청이 발생하고, 이로 인해 불필요한 데이터 요청과 서버 부하가 발생할 수 있다.
if (response.data.length === 0) 조건을 추가하여, 서버에서 더 이상 데이터를 반환하지 않을 경우 isFetching(false)로 상태를 변경하고 함수 실행을 종료함으로써 추가 데이터 요청을 방지했다.
[ 성능 최적화 결과 ]
불필요한 서버 요청이 줄어들었고, 성능이 크게 개선되었음
중복된 데이터 요청이 사라져 더욱 효율적인 무한 스크롤 기능이 구현되었으며, 메모리 관리도 안정적으로 이루어짐
사용자 경험(UX)도 한층 더 향상되었다 😆 😆
⬇️⬇️ 추가로 ⬇️⬇️
[ 💡 메모리 누수 방지를 위한 이벤트 리스너 제거 ]
컴포넌트가 언마운트될 때, useEffect 안에서 추가했던 이벤트 리스너를 반드시 제거하기❕❕
이벤트 리스너를 제거하지 않으면, 컴포넌트가 사라진 후에도 브라우저는 계속해서 이벤트를 감지하려고 시도하게 되고, 이로 인해 불필요한 메모리를 차지하게 되며, 장기적으로 메모리 누수가 발생할 수 있다.
만약, 내 코드에서 스크롤 이벤트가 계속해서 실행되면서도 컴포넌트가 더 이상 존재하지 않는 경우, 해당 이벤트에 대한 처리가 불필요하게 남아 브라우저 성능을 저하시키거나 메모리 사용량을 증가시키게 된다.
특히, 이 문제가 반복되면 브라우저에서 메모리 누수 현상이 심각해질 수 있다.
그러니까 꼭 언마운트시에 이벤트 리스너 제거하기!!
- 불필요한 메모리 사용을 방지
- 컴포넌트가 사라질 때 메모리 누수 없이 깔끔하게 메모리 관리
- 애플리케이션의 성능을 최적화
- 장기적으로 안정적인 동작을 유지
// 스크롤 이벤트 리스너 등록
window.addEventListener("scroll", handleScroll);
// 컴포넌트가 언마운트될 때 리스너 제거
return () => window.removeEventListener("scroll", handleScroll);
'[ PROJECT ] > PetHarmony' 카테고리의 다른 글
[🚨 TroubleShooting] N+1이 뭔데.... (1) | 2024.09.13 |
---|---|
React에서 토글 상태 관리하기 (7) | 2024.09.11 |