Infinity scroll과 Lazy loading은 요소를 동적으로 로딩하여 DOM 랜더링 및 network 통신을 최적화할 수 있어 웹 사이트를 최적화하는데에 중요한 기능입니다.
아직은 실험요소지만 많은 브라우저에서 지원하는 Intersection observer를 사용한 기능 구현을 설명합니다.
리스트 UI에서 아래로 스크롤하여 요소가 동적으로 추가됨과, 랜더링 된 요소들이 보일 때 이미지를 로딩하는 UI를 구성했습니다.
IntersectionObserver의 인스턴스는 아래와 같이 생성합니다.
const observer = new IntersectionObserver(callBack, options)
해당 생성자에는 call back 함수와 어떻게 동작할 것인지 지정할 options 객체를 넘길 수 있습니다.
const observer_callback = (entries, observer) => {
console.log('entries: ', entries) // [IntersectionObserverEntry], 현재 Intersection된 요소들의 배열입니다.
console.log('observer: ', observer) // IntersectionObserver instance
}
Call back은 해당 요소가 '지정된 수치'에 도달했을 때 해당 요소를 call back 함수에 넘겨주어 의도한 동작을 해당 함수에 구현할 수 있습니다.
const options = {
root: stack, // Root element
rootMargin: '0px', // Margin of root element
threshold: 0.5, // Percentage value for call call back function
}
옵션 객체는 root element, margin of root element, threshold 를 설정할 수 있습니다.
root element는 scroll 되어지는 요소들의 부모 element 즉, intersecting의 기준이 되는 element를 설정합니다.
rootMargin은 IntersectionObserver가 정확하게 계산하기 위해 root element에 margin style이 설정되어 있을 경우 설정합니다.
threshold는 0 ~ 1.0 사이의 값으로 설정 가능하며 observing 되는 요소의 0% ~ 100% 비율이 intersecting 되었을 때 call back 함수를 실행하기 위한 기준 값입니다.
만든 IntersectionObserver를 아래와 같이 적용시킬 수 있습니다.
observer.observe(item) // item: <element>
observing 대상을 리스트의 로딩된 items, 그리고 추가될 items들에 설정하여 Infinite scroll을 call back function 부분에서 구현할 수 있습니다.
제 예제에서는 추가로 items가 로딩이 될 때 한 번에 15개를 추가하도록 구성하였습니다.
그리고 Lazy loading 구현도 마찬가지로 observing 되는 요소의 intersection call back를 통해 구현할 수 있습니다.
해당 observing item에 data attribute에 이미지의 주소나 필요에 따른 다양한 값을 바인딩하고, intersecting 될 때에 해당 값을 꺼내와서 활용할 수 있습니다.
위 구현 사항을 Github에서 코드로 확인해보실 수 있습니다.
결과물 미리보기
이슈
데이터를 서버로부터 가져와 loading 하는 경우 약간의 갭이 있을 수밖에 없어 이 이슈가 무시될 수 있다. 이럴 때에는 placeholder 격의 UI를 배치하거나 item block 자체는 추가하되, data binding은 data fetch가 이루어지고 나서 binding 하도록 할 수 있을 것이다.
이 이슈는 유저가 리스트를 스크롤하는 와중에 스크롤이 끊기는 현상을 해결한 사례를 설명한다.
개선 전의 코드는 '마지막 요소'가 threshold 값에 기반하여 intersected 되었을 때 '15개'의 items를 새로 추가한다.
하지만 모바일 환경에서는 빠른 속도로 스크롤이 가능했었고, 일부 환경에서 브라우저 프로세싱 환경이 좋지 않을 경우 새로운 items들이 list에 추가되기 전에 list의 끝에 도달하여 유저 입장에서는 스크롤이 지속적으로 끊기는 현상을 경험하게 되었다.
그러하여 '마지막 요소'를 판단하는 함수의 기준을 '마지막 요소로부터 -5 index'일 경우로 수정하였다.
이 방법을 사용한 이유는 브라우저 처리 속도에 과부하를 주지 않고 스크롤이 끊기는 현상을 심플하게 개선할 수 있다고 생각하였기 때문이다.
Source
'Front-End' 카테고리의 다른 글
[JS] event.stopPropagation을 웬만해서 사용하지 않아야 하는 이유 (0) | 2021.10.08 |
---|---|
React 의미론적 컴포넌트화, 최적화에 대해서 (0) | 2021.10.08 |
[JS] Optional chaining, Nullish coalescing operator 🛒 (0) | 2021.08.04 |
[JS] Live collection, Static collection 📑 (0) | 2021.08.03 |
[JS] 브라우저에서 말 하기 👄 | SpeechSynthesis (0) | 2021.07.30 |