박주니 개발 정리

observe 적용 방법 본문

nextjs

observe 적용 방법

박주니 2023. 3. 6. 17:17
728x90
반응형

우선 observe 적용에 대해서 설명하기 전에 observe를 사용했던 이유는 무한 스크롤 최적화를 하기 위함입니다. 특정 요소를 지나갈 때마다 새로운 컨텐츠를 로드할 수 있습니다. 그 외 이미지나 동영상 등의 미디어 로딩, 광고 배너 등의 노출, 애니메이션 실행, 로딩바등 최적화할 때 사용합니다. 

 

조건) 기본적인 리스트 데이터 api 연결해주시길 바랍니다. 

 

1. new IntersectionObserver을 이용해서 기본 구성을 만들어주시길 바랍니다. 

import {useRef} from "react";

const obsRef = useRef(null); //observer Element
 
useEffect(() => {
    //옵저버 생성
    const observer = new IntersectionObserver(obsHandler, { threshold: 0.5 });
    // IntersectionObserver 상호작용
    if (obsRef.current) observer.observe(obsRef.current);
    return () => {
      // 인스턴스 해제
      observer.disconnect();
    };
  }, []);
  
  return (
  	<>
    	<ul>
    	// list 나오는 부분
        </ul>
        <div ref={obsRef}></div>
    </>
  )
  1. <div ref={obsRef}></div>:  react의 가상 돔과 별개로 dom 엘리먼트에 직접 접근할 수 있어서 불필요한 렌더링을 방지할 수 있습니다. 
  2. if(obsRef.current)  observer.observe(obsRef.current): obsRef.current를 console로 확인해보면 div가 나오는 것을 확인하실 수 있습니다. 스크롤 진행시 div영역 전까지 observer.observe()는 IntersectionObserver 상호작용한다는 의미입니다. (해당 영역에서는 스크롤할 때 데이터를 불러옵니다)
  3. observer.disconnect(): observer 영역에 벗어나는 경우 observer.disconnect()로 observer 인스턴스 해제합니다. 

2. 무한 스크롤 페이지 갯수 변수를 설정하고 new IntersectionObserver에 들어갈 obsHandler을 설정합니다. 그리고 가져올 데이터 함수에 page 매개변수를 전달합니다. 

  let p2 = 1; // 무한스크롤 page 갯수
  const [page, setPage] = useState(1);
  
  useEffect(() => {
  	getList(page)
  }, [])
    
  //무한스크롤때문에 추가
  const obsHandler = (entries) => {
    //옵저버 콜백함수
    const target = entries[0];
    console.log("target", target);
    if (target.isIntersecting) {
      //옵저버 중복 실행 방지
        p2 = p2 + 1;
        setPage(p2);
    }
  };

설명) 스크롤 진행시 데이터가 존재할 경우 페이지가 계속 +1씩 진행될 수 있게 만듭니다. obsHandler 함수가 observe에 core 부분이 될 수 있습니다. 

3. getList 함수에 페이지갯수를 받았을 때 전체 데이터갯수와 비교해서 preventRef를 설정합니다.

추가 설명) 2번에서 getList(page) 전달받은 매개변수가 _page 입니다.

  const cnt = 3; // 한 페이지당 갯수
  const preventRef = useRef(true); //옵저버 중복 실행 방지
  const [isLast, setIsLast] = useState(false); // Load More 표시
  
  const getNftList = async (_page) => {
    setLoad(true); //로딩 시작 //무한스크롤때문에 추가
    const p = _page ? _page : page;

    axios(`${process.env.NEXT_PUBLIC_API_URL}/api/main`, {
		....
    })
      .then((res) => {
        const data_ast = data.assets; // 데이터 리스트
        let list;
        list = data_ast.slice(0, cnt * p); // 한페이지에 나올 데이터

        setTList([...list]);// 한페이지에 나올 데이터 셋팅
        
        /*데이터 전체 갯수와 현재 페이지 갯수 비교*/
        if (list.length == data.assets.length) {
          setIsLast(true);
          preventRef.current = false; 
        } else {
          preventRef.current = true; 
          setIsLast(false);
        }
        setLoad(false); //로딩 종료 //무한스크롤때문에 추가
      })
      .catch((error) => {
		console.log(error)
      });
  };

cnt 적용 설명 이미지

  • cnt 설명) cnt를 3으로 설정했을 때 스크롤 진행시 3개 나오고 밑에 obsRef를 인식을 하고 다른 데이터 3개를 부르게 됩니다. 즉 1페이지에 3개씩 나온다고 이해하시면 됩니다.

4. obsHandler 함수에서 preventRef를 추가해서 true일경우에만 조건이 성립하게 만듭니다.

  //무한스크롤때문에 추가
  const obsHandler = (entries) => {
    //옵저버 콜백함수
    const target = entries[0];
    if (target.isIntersecting && preventRef.current) {
      preventRef.current = false; 
      if (!isLast) {
        p2 = p2 + 1;
        setPage(p2);
        getNftList(p2);
      }
    }
  };

 

tip) 먼저 만들때 observe를 이용한 리스트를 만들기보다는 전체 리스트를 만들고나서 observe를 셋팅하시는 것을 추천합니다. 그리고나서 적용 순서를 

1. setPage와 setIsLast를 설정

2. cnt 한페이지 갯수 설정 

3. return 안에 데이터리스트 하단에 <div ref={obsRef}></div> 설정 

4. new IntersectionObserver 및 obsHandler 셋팅 

5. 정상작동 되는 지 확인 

6. 현재 페이지와 전체 데이터 페이지 비교해서 preventRef 조건 셋팅 

7. obsHandler 조건 추가 

이 방식으로 진행하시면 이해하시기 편하실거라 생각합니다. 

728x90
반응형
Comments