새로운 주문 페이지 디자인을 적용하면서 아래와 같은 디자인을 구현해야했다.
스크롤 위치에 따라서 위에 배지의 선택이 바뀌는 디자인이다.
라이브러리로도 많이 있는 기능이라서 라이브러리를 적용하고 보니 아래와 같은 문제가 생겼다.
Screen Recording 2025-03-01 at 1.21.56 AM.mov
스크롤이 빠르게 움직일 때 delay로 인해서 제대로된 배지를 선택하지 못하는 문제인데.. 라이브러리 사용법만 봐서는 쉽게 판단이 어려워서 라이브러리 구현을 뜯어봤다.
import throttle from "lodash.throttle";
import { addPassiveEventListener, removePassiveEventListener } from './passive-event-listeners';
// The eventHandler will execute at a rate of 15fps by default
const eventThrottler = (eventHandler, throttleAmount = 66) => throttle(eventHandler, throttleAmount);
const scrollSpy = {
spyCallbacks: [],
spySetState: [],
scrollSpyContainers: [],
mount(scrollSpyContainer, throttle) {
if (scrollSpyContainer) {
const eventHandler = eventThrottler((event) => {
scrollSpy.scrollHandler(scrollSpyContainer);
}, throttle);
scrollSpy.scrollSpyContainers.push(scrollSpyContainer);
addPassiveEventListener(scrollSpyContainer, 'scroll', eventHandler);
return () => {
removePassiveEventListener(scrollSpyContainer, 'scroll', eventHandler);
scrollSpy.scrollSpyContainers.splice(scrollSpy.scrollSpyContainers.indexOf(scrollSpyContainer), 1);
};
}
return () => {};
},
...
여기서 throttleAmount를 기본값으로 66을 주고 lodash의 throttle에 넘겨서 eventListner에 등록하는 것을 확인 할 수 있었다.
왜 throttle을 추가하여 스크롤 이벤트를 제한하였을까?
그 이유는 스크롤 이벤트가 상당히 민감하기에 조금만 움직여도 무수히 많은 이벤트 리스너가 호출되어 성능에 영향을 미칠 수 있기 때문이다.
throttle 내부 구현은 확인하지 않았지만 무언가 setTimeout이나 debounce를 활용했을 것으로 짐작된다.
js 특징상 setTimeout에 delay값으로 0초를 넣어도 늦게 실행될 수 있다는 점을 미루어보면 해당 부분이 문제가 될 것으로 확신했다.
이제 라이브러리 구현상 우리가 원하는 방식과 다르게 동작한다는 것을 확인한 지금 우리가 취할 수 있는 방식은 3가지 정도가 있었다.