라이브러리 없이 Lazyloading을 구현

이건우·2022년 3월 2일
0
post-custom-banner

Lazyloading 이란 ?

  • 페이지에 액세스 할 때 모든 콘텐츠를 대량으로 로드하는 대신 사용자가 필요한 페이지의 일부에 엑세스 할 때에 콘텐츠를 로드 할 수 있게 하는 것 입니다 .
  • 페이지를 읽어 들이는 시점에 중요하지 않은 리소스 로딩을 추 후에 하는 기술입니다 . 대신에 중요하지 않은 리소스들은 필요할 때 로드가 되어야 합니다 .

lazy loading의 장점 ?

  • lazy loading은 콘텐츠 전달 최적화와 최종 사용자 간의 경험을 간소화 하는 균형을 맞춥니다.
  • 사용자가 처음 열 때 웹 사이트의 일부만 다운로드 해야하므로 사용자에게 콘텐츠를 더 빨리 제공합니다.
  • 콘텐츠가 지속적으로 사용자에게 공급되므로 사용자가 웹사이트를 이탈할 확률을 낮출 수 있습니다.
  • 사용자가 한 번에 필요로 하는 경우에만 콘텐츠를 불러오므로 리소스 비용(사용자의 배터리, 시간, 시스템 리소스)이 낮아집니다

lazy loading의 단점 ?

  • lazy loading은 검색 엔진 순위에 영향을 미칠 수 있습니다 . 웹사이트를 크롤링하는 검색엔진은 리소스의 내용을 잘못 해석하거나 무시 할 수 있습니다 .

  • 블로그 게시물과 같은 웹페이지의 전체 구성 요소를 느리게 로드하면 검색 엔진이 해당 구성 요소를 우회하여 콘텐츠가 인덱싱 되지 않아 검색 엔진 결과가 줄어들 수 있습니다.

  • 이러한 문제를 극복하는 한 가지 요령은 lazy load하는 콘텐츠에 대한 링크를 제공하는 것입니다.

lazy loading 구현 방법 ?

lazyloading을 구현하는 방법에는 IntersectionObserver 를 이용한 infinity scrole을 구현 할 수 있고 다른 방법들도 있지만 저는 다른 방법으로 구현해 보았습니다 .

lazyloadinig을 구현 하기 위한 방법으로는 어떠한 경우에 사용자에게 필요한 정보의 타입에 따라 필요한 정보를 보여줄 지를 생각해보아야 합니다 . 저는 쌓여있는 글들을 사용자가 스크롤을 내려서 가장 마지막 글을 볼 때 쯔음에 데이터를 추가해주는 방법으로 구현해 보았습니다 .

Code

  1. 우선 유저의 스크롤을 감지해서 Footer의 길이를 제거 하고 가장 아래로 왔을 때에 isLoading을 false에서 true로 바꾸어서 로딩을 보여준다 .

  2. 로딩중일 때에 데이터를 10개씩 넘겨주고 다시 로딩을 true 에서 false로 바꾸어준다 .

  3. 만일 데이터를 전부 불러와서 없는 경우에는 데이터를 더 불러오지 않는다 .

code

 useEffect(()=> {
    function scrolling() {
      let scrollHeight = Math.max(
        document.documentElement.scrollHeight,
        document.body.scrollHeight
      );
      let scrollTop = Math.max(
        document.documentElement.scrollTop,
        document.body.scrollTop
      );
  
      let clientTop = document.documentElement.clientHeight;
      // 여기까지가 가장 아래의 스크롤을 구하기 위한 변수
      // scrollHeight : 화면에 보이지 않는 총 높이까지 포함된 페이지의 높이
      // scrollTop : 이미 스크롤되어서 보이지 않는 구간의 높이
      // clientHeight : 사용자에게 보여지는 페이지의 높이
      if(footerref && footerref.current?.clientHeight){
        const footerRealHeight = footerref.current.clientHeight
         //footerRealHeight는 footer의 높이
        if (scrollTop + clientTop >= scrollHeight - footerRealHeight) {
        //footer의 높이를 제외한 전체 스크롤 높이보다 scrollTop과 clientTop의 합의 높이가 같거나 더 크면 
            setPage(storageData.slice(0, pageNum + 10));
        //데이터를 추가해주고
            setTimeout(() => {
             if (pageNum < storageData.length + 9) {
               //만약 데이터 전체의 길이가 storageData에 9를 더한값 (뒷자리가 1인경우 예를 들어 11인경우도 대비해 9를 더해준다.)
                setPageNum(pageNum + 10);
               //데이터 추가
              } else {
                return;
                //만약 pageNum이 큰경우에는 아무것도 하지 않는다 . 
              }
            }, 10);
        } else {
          return
        }
      }
    }
    window.addEventListener("scroll", scrolling);
    return () => {
      //스크롤을 감지하고
      window.removeEventListener("scroll", scrolling);
      //스크롤 이벤트가 계속 반복되는걸 방지하기 위함
    };
  }, [storageData, pageNum]);

CommentList.tsx 에서는

  useEffect((): void => {
    if (props.page.length === props.storageData.length) {
      props.setIsLoading(false);
    // localstorage에 저장된 데이터와 실질적으로 쓰이는 데이터의 길이가 같다면 로딩을 false로 만들어주고
    }
    if (props.storageData.length <= 10) {
      props.setPage(props.storageData);
      props.setPageNum(10);
      props.setIsLoading(false);  
      //localstorage의 데이터가 10개 이하인 경우에도 실질적으로 쓰이는 데이터인 page를 setPage를 통해 갱신시키고 pageNum을 10으로 맞춰준 뒤에 로딩또한 false로 해둔다 
    } else {
      props.setPage(props.storageData.slice(0, props.pageNum));
      //위의 조건을 통과하지 않을 경우에는 storageData를 pageNum 만큼 slice 한 값으로 채워준다 
    }
  }, [props.storageData, props.page.length]);
 {props.page.map((el: storageType, index: number) => {
          if (index > props.page.length * 10 - 1) {
            return <react.Fragment key={`index-${index}`} />;
// 그 뒤에 page를 map 해서 보여준다 .
          }

스크롤바를 집중적으로 봐주세요 !

profile
주니어 개발자 이건우 입니다 .
post-custom-banner

0개의 댓글