별도의 라이브러리 없이 순수 JavaScript(vanilla JS)만으로 사용자가 페이지 하단 근처까지 스크롤했는지 감지하는 방법을 알아봅니다.
무한 스크롤, 지연 로딩(lazy loading), '맨 위로' 버튼 표시 등을 구현하다 보면 사용자가 페이지 전체 또는 특정 섹션의 맨 아래까지 스크롤했을 때 특정 이벤트를 실행해야 하는 경우가 종종 있습니다.
맨 아래 스크롤 감지 방법 (모든 최신 브라우저 및 IE9 이상 지원)
가장 기본적인 방식은 window.onscroll 이벤트 안에서 뷰포트 높이 + 스크롤된 거리가 문서 전체 높이와 같거나 커졌는지 비교하는 것입니다.
window.onscroll = function() {
if (window.innerHeight + window.pageYOffset >= document.body.offsetHeight) {
alert("At the bottom!")
}
}
예외 상황(Edge Case) 해결 방법
위 코드가 의도대로 동작하지 않는다면, window.pageYOffset 값에 Math.ceil() 메서드를 적용해 보세요.
window.onscroll = function() {
if ((window.innerHeight + Math.ceil(window.pageYOffset)) >= document.body.offsetHeight) {
alert('At the bottom!')
}
}
Math.ceil을 사용하는 이유는 일부 브라우저가 요소 크기를 계산할 때 서브픽셀(subpixel) 단위의 정밀도를 사용하기 때문입니다. 예를 들어 어떤 요소의 너비나 높이가 500.25px처럼 소수점 값을 가질 수 있습니다.
Math.ceil은 값을 항상 올림 처리하므로, 예를 들어 1.45px는 2px로 계산됩니다. 이렇게 하면 소수점 오차로 인해 조건이 마지막 몇 픽셀에서 실패하는 문제를 방지할 수 있습니다.
또한 일부 Mac 컴퓨터에서는 창(window) 높이가 1px씩 어긋나는 현상이 보고되기도 합니다. 이런 경우에는 문서 전체 높이에서 몇 픽셀을 빼주는 방식으로 우회할 수 있습니다.
(window.innerHeight + window.pageYOffset) >= document.body.offsetHeight - 2
참고: 최근에는 pageYOffset 대신 scrollY가 자주 사용됩니다. 하지만 scrollY는 Internet Explorer에서 동작하지 않습니다. 구형 브라우저까지 폭넓게 지원하려면 pageYOffset을 사용하는 것이 안전합니다.
실제로 동작하는 예제는 아래 CodePen 데모에서 확인할 수 있습니다.
스크롤 값 디버깅용 헬퍼 함수
window.innerHeight, window.pageYOffset, document.body.offsetHeight 세 값 사이의 관계가 헷갈린다면, 스크롤할 때마다 각각의 픽셀 값을 콘솔에 출력해 주는 간단한 헬퍼 함수를 활용해 보세요.
window.onscroll = function() {
console.log('Window height (px):', window.innerHeight)
console.log('Currently scrolled from top (px):', window.pageYOffset)
console.log('Document height(px):', document.body.offsetHeight)
}
값의 변화를 눈으로 직접 확인하면 스크롤 감지 로직이 훨씬 쉽게 이해될 것입니다. 처음 접했을 때 저도 pageYOffset이 다소 혼란스러웠는데, 결국 이 값은 문서 맨 위에서부터 현재 세로로 스크롤된 픽셀 수를 의미합니다.