프로그래머스 2020 Dev-Matching : 웹 프론트엔드 과제 복기
https://github.com/woohyeonjo/ilovecat
페이징 UI
와 무한 스크롤 UI
는 많은 컨텐츠를 효과적으로 보여주는 대표적인 UI다. 두 UI는 각각 장단점이 존재하는데 정말 단순하게 유저의 접속 기기만 따진다면 PC에는 페이징 UI
가 모바일에는 무한 스크롤 UI
가 좀 더 어울린다. 하지만 최근에는 반응형 페이지를 통해서 대표적인 스크린 사이즈를 모두 커버하는 경우가 많고 모바일 트래픽이 더 큰 경향이 있기 때문인지 무한 스크롤 UI
가 더 흔하게 보이는 것 같다. 가장 중요한 것은 서비스와 보여주려는 컨텐츠의 특성을 잘 파악해서 적합한 UI를 선택하는 것이다.
스크롤 바가 마지막 컨텐츠를 보여주는 시점에 추가적인 데이터를 제공하는 것이다. 여러가지 사이즈를 이용해서 마지막 컨텐츠가 보이는 시점을 구할 수 있다.
전체 문서의 높이
에서 현재 보이는 영역의 높이
를 뺀 결과는 총 스크롤 할 수 있는 높이
다. 따라서 스크롤 된 높이
가 이와 같다면 스크롤을 끝까지 완료한 것이며 마지막 컨텐츠가 보이는 시점이 될 것이다.
// scrollFetch.js
function scrollFetch(fetchData) {
window.addEventListener('scroll', () => {
if (getScrollTop() < getDocumentHeight() - window.innerHeight) return;
fetchData();
});
}
// 현재 스크롤한 높이를 구하는 함수
function getScrollTop() {
return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
}
// 문서의 높이를 구하는 함수
function getDocumentHeight() {
const body = document.body;
const html = document.documentElement;
return Math.max(
body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight
);
}
export { scrollFetch };
scrollY
, scrollX
와 같다.데이터를 추가로 받아오는 시점을 스크롤 이벤트로 멋지게 구현했다. 근데 문제가 있다. 스크롤을 움직일 때 마다 함수가 실행되는 것이다. 스크롤이 마지막이 아니면 데이터가 추가되지 않지만 그래도 계속해서 스크롤이 마지막인지 확인하는 비교를 수행하다보니 성능문제가 있다.
이 문제에 해결법으로 적용가능한 프로그래밍 기법이 두 가지 있다.
일반적으로 Debouncing
은 검색에서 사용하고 Throttling
은 스크롤에 사용된다고 한다. 아무래도 검색은 유저가 검색어 타이핑을 완료하는 시점에 함수가 실행되어야 하니 Debouncing
이 사용되고 스크롤의 경우에는 변화하는 길이 만큼의 횟수로 스크롤 이벤트가 발생하니 일정 시간으로 함수 호출을 막는 Throttling
이 적당해서인 것 같다.
//throttle.js
export const throttling = () => {
let throttleCheck;
return {
throttle(callback, milliseconds){
if(!throttleCheck){
throttleCheck = setTimeout(() => {
callback(...arguments);
throttleCheck = false;
}, milliseconds);
}
}
};
};
throttleCheck
를 외부에서 접근하지 못하도록 하기 위해서 사용한거 같다. 사실 아직 클로저에 대해서 정확히 이해하지 못해서 따로 공부를 해야겠다.throttleCheck
를 통해서 throttle 상태가 아닐 때만 callback
을 실행한다.setTimeout
은 timer id
를 반환하기 때문에 호출 시점에 throttleCheck
에 숫자가 할당되어 true
값으로 여겨진다.callback
의 실행이 완료되고 throttleCheck
를 false
로 바꾸어 다시 함수 호출이 가능한 상태로 바꾼다. // scrollFetch.js
import { throttling } from './throttle.js';
const throttler = throttling();
function scrollFetch(fetchData) {
window.addEventListener('scroll', () => {
throttler.throttle(() => {
console.log("Activate Scroll Event");
if (getScrollTop() < getDocumentHeight() - window.innerHeight) return;
fetchData();
}, 700);
});
}
...
Throttling
을 적용한다.Throttling
을 이용한 스크롤 이벤트 개선을 공부하던 중 이전에 Lazy Loading
을 구현할 때 사용하였던 Intersection Observer를 이용하면 더 간단하게 무한 스크롤을 구현할 수 있다는 사실을 알게되었다. 다음에는 Intersection Observer
를 이용해서 구현해봐야겠다. 그래도 Throttling
, Debouncing
은 무한 스크롤 뿐만 아니라 적용할 수 있는 곳이 많아서 좋은 공부가 되었다.