003

😉 헷갈렸던 & 몰랐던 부분들만 정리하는 나만의 TIL
😯 모든 강의 내용은 적지 않아요!

오늘의 소감은?
안드로이드 어플리케이션 개발 시 사용했던 recycler view와 굉장히 유사한 무한 스크롤
직접 코딩해보니 재미있었습니다. :)

하지만 아직 여러 이슈가 많이 발생하네요.
실제로 웹을 개발할 때, 무한 스크롤을 사용하기 위해서는 고려해야 할 사항이 많을 것 같습니다.
오늘 글에 첨부한 오늘의 집 무한 스크롤 개발기 다들 한번씩 읽어보시면 재미있으실 것 같아요!




[1] 무한 스크롤 (Infinite scroll)

무한 스크롤 방식은 스크롤이 화면의 가장 밑 부분에 도달했을 때, 나머지 컨텐츠를 보여주는 방식입니다.


[1-1] 구현 방식

  1. windowscroll 이벤트를 통해 스크롤링이 일어날 때마다 화면 전체의 height와 스크롤 위치를 통해 스크롤이 컨텐츠 끝 즈음에 다다랐는지 체크해서 처리하는 방식
  2. intersection observer 방식 (지정한 돔 객체가 보고 있는 시야에 닿았는지 안 닿았는지 체크)


[1-2] 실습

중요 포인트에 대해서만 첨부할 예정입니다.


[1] window의 scroll event 방식

먼저 window.addEventListener(’scroll’ …) 방식으로 무한 스크롤을 구현하게 되면,

스크롤이 동작할때마다 해당 이벤트가 발생하여 퍼포먼스에 문제가 될 수 있습니다.


window.addEventListener("scroll", () => {
  const { isLoading, totalCount, photos } = this.state;
  const isScrollEnded =
    window.innerHeight + window.scrollY + 100 >= document.body.offsetHeight;

  if (isScrollEnded && !isLoading && photos.length < totalCount) {
    onScrollEnded();
  }
});

Untitled


콘솔을 찍고 5개의 사진만 천천히 내렸음에도 불구하고, 거의 100번의 이벤트가 발생함을 알 수 있습니다.


이는 쓰로틀링 또는 디바운싱을 통해 문제를 어느정도 해결할 수 있지만,

그렇다면 스크롤 이벤트가 멈추지 않고 계속해서 사용자가 스크롤링을 하는 경우에

다음 request가 발생하지 않을 수 있다는 또 다른 이슈가 있습니다.



[2] intersection observer 방식

intersection observer 방식에서는, 화면에 있는 가장 마지막 li (DOM 객체)가 화면 시야에 들어왔는지 체크하고, 그 때 다음 페이지를 불러오는 방식입니다.

이미지 지연 로딩에서도 intersection observer 방식을 많이 사용합니다.


하지만 이전의 브라우저에서 호환되지 않을 수 있습니다.

참고 문서

https://developer.mozilla.org/ko/docs/Web/API/IntersectionObserver


// photoList Component
const observer = new IntersectionObserver(
  entries => {
    entries.forEach(entry => {
      if (entry.isIntersecting && !this.state.isLoading) {
        console.log('화면 끝!');
        onScrollEnded();
      }
    });
  },
  {
    threshold: 1,
  },
);

...

// render func

...
const $nextLi = $photos.querySelector('li:last-child');

  if ($nextLi !== null) {
    if ($lastLi !== null) {
      observer.unobserve($lastLi);
    }
    $lastLi = $nextLi;
    observer.observe($lastLi);
  }

Untitled 1


아까의 scroll보다 조금 더 여러 이슈를 예방할 수 있으며, 조작이 간단합니다.



Intersection Observer를 사용하기 위해서는 observe, unobserve를 잘 해야합니다.

const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting && !this.state.isLoading) {
        console.log("화면 끝!");

        if (this.state.totalCount > this.state.photos.length) {
          onScrollEnded();
          // 지켜보고 있던 entry.target을 unobserve해줍니다.
          observer.unobserve(entry.target);
        }
      }
    });
  },
  {
    threshold: 1,
  }
);

적절한 때에 observe, unobserve를 해줘야 무한 observe가 발생하지 않게 됩니다.

불과 5분전 한번에 6개의 request요청이 발생하는 제 웹을 보고 심히 놀랐습니다.


또한 threshold값으로 observe 대상이 얼마나 노출되어 있는지에 따라 동작하게 할 수 있습니다.

여러 값으로 시도해본 결과, 저는 0.8이 가장 좋았던 것 같습니다.

물론 UI의 기능과 사용성에 따라 조절해야 하는 값이겠죠.


[1-3] 무한 스크롤 사용성

무한 스크롤은 본질적으로 가지고 있는 문제가 많습니다.

[1] 단점

  1. 뒤로 가기가 없는 경우, 사용자는 초기 화면으로 돌아갈 수 없습니다.
  2. Footer가 고정되지 않은 경우, 접근하기 위해서 너무 많은 스크롤을 내려야 합니다.
  3. 무한 스크롤로 불러온 페이지는 해당 스크롤 위치를 기억하지 못해 나갔다 다시 들어오면 유저가 보던 페이지의 위치가 초기화되는 문제가 있습니다.


하지만 잘 사용하면 피드의 큰 성능 향상과 사용자 유입에 좋은 UX 방식입니다.

[2] 장점

  1. 사용자 참여 및 콘텐츠 탐색이 쉽습니다.
  2. 클릭하는 것보다 더 나은 UX를 제공합니다. 다음 콘텐츠를 보기 위한 추가 클릭을 할 필요가 없으며, 페이지 로드 시간이 짧습니다.
  3. 터치스크린일때 더 유용하게 적용합니다. 화면이 작을수록 스크롤은 길어집니다. 따라서 모바일 환경에서 콘텐츠를 보여주기 직관적이고 사용하기 쉬운 방식입니다.

따라서 웹의 특성에 따라 적절하게 사용하는 것이 좋겠습니다.


무한 스크롤을 이용하고 있는 오늘의집 document를 심심풀이로 읽어보았습니다.

제가 궁금했던 이슈들을 어떻게 해결하는지에 대한 과정을 읽을 수 있었습니다.

오늘의집 내 무한스크롤 개발기


무한 스크롤을 처음 접했을 때, Android의 recycler view와 상당히 유사하다고 생각했지만,

위와 아래의 페이지의 내용을 날리고, 리렌더링 하는 것을 직접 구현해보니..

상당히 복잡한 과정을 거쳐 무한 스크롤 UX 방식이 탄생함을 알 수 있었습니다.


무한 스크롤을 조금 더 공부해보고,

나중에 인스타그램 클론 코딩 또는 다른 SNS 클론 코딩을 해볼 기회가 있으면 공부한 내용을 적극적으로 적용해보고 싶습니다.





출처

프로그래머스

오늘의집 내 무한스크롤 개발기

무한 스크롤 구현하기

댓글남기기