[ Virtual Scroll ] 데이터가 있는척, 사용자를 속여서 최적화하기

2026. 1. 19. 23:50Frontend

🎤 "무한 스크롤" 구현해 보셨나요?

네, 아마 프론트엔드 개발자라면 응당 구현해봤을 것이라고 생각합니다.

무한스크롤이란 스크롤형태의 페이징을 의미하며, 스크롤이 끝까지 닿거나, 닿으려하는 경계에 하나의 요소를 특정하고, 해당 요소가 사용자가 볼 수 있는 view 영역에 보이게 됐을 때, 이벤트를 트리깅하여 데이터를 추가로 불러오는 페이징 기법입니다.

 

말 그대로 데이터가 무한하다면 정말로 무한하게 데이터를 볼 수가 있는 구조입니다.

하지만, 한가지 의문이 있습니다.

 

"계속 무한하게 추가가 된다면 어떻게 될까?"

 

음... 아마 무한히 볼 수 있지 않을까?

 

 

...라고만 생각하셨다면, 지금이 바로 프론트엔드 세계로 한걸음 더 나아갈 수 있는 기회!

 

 

🏋🏻 "무한 스크롤"과 함께 "무한 과부화"

이전 질문에 이어서 무한하게 늘어나면,

그 무한한 요소가 브라우저에 무한하게 존재하게 된다는 뜻이기도 합니다.

 

그렇다면 스크롤이 일어날 때 마다 해당 요소들의 값은 재계산되어 스크롤 위치로 재배치 될 것이고, 스크롤 한 틱에 엄청난 부하가 걸리게 되어 버벅이는 화면을 마주할 수가 있게됩니다.

 

즉, 무한 스크롤은 무한 과부화이기도합니다.

 

그렇다면 어떻게 페이스북, X, 인스타그램과 같이 무한 스크롤을 기본으로 하는 플래폼들은

그렇게 많은 피드를 로드하고도 어떻게 부드럽고 안전하게 컨텐츠를 보여주는걸까? 라는 의문이 생깁니다.

 

이에 대한 대책으로 나온 기법이 바로 "가상 스크롤"입니다.

 

🤔 가상 스크롤은 왜 "가상" 스크롤인가?

사실 저도 가상 스크롤의 핵심 아이디어는 인지하고 있었지만, 정식적인 이름과 구체적인 구현 방식에 대해서 알게된 것은 최근에 지나지 않습니다.

 

그래서 궁금했습니다. 왜 많은 단어를 놔두고 어째서 "가상"인가?

 

그 이유는 바로 "요소가 없는데 있는 척" 사용자를 속여서 최적화하는 기법이기 때문에 "가상" 스크롤이었습니다.

 

 

사용자: " 와, 리스트가 정말 길어서 스크롤바가 아주 작네 ^^ ! " ( 인식 )

브라우저: " 실제 데이터는 10개뿐이고, 높이만 5,000px인 빈 상자를 보여주고 있어. " ( 현실 )

 

와 같은 시나리오 입니다.

 

즉, 가상 스크롤이란

스크롤 내부의 영역의 높이를 기준으로 높이는 유지하되,

사용자에게 보이는 영역의 item만을 view에 나타내는 기법입니다.

 

결과적으로 10만, 100만개의 데이터가 있더라도 사용자가 보고 있는 item만이 렌더링되고 나머지 영역은 빈 영역으로 높이만을 가지고 있어, 부하를 일으키지 않아 UX를 저해하지 않고 컨텐츠를 제공할 수 있게 됩니다.

 

🥹 그래서 어떻게 만들 수 있지?

단순하게 구현 아이디어를 떠올린다면 아래와 같은 방식이 있을 것 같습니다.

 

1. 스크롤 영역의 전체 높이를 기준으로 한다.

2. 보이는 영역만을 잘라서 배치하고 나머지 영역은 html에 배치 "자체"를 하지 않고 메모리에만 데이터를 가지고 있는다.

3. 보이지 않게되는 부분은 전체 높이를 기준으로 padding-top / padding-bottom 으로 공간만을 채운다.

4. 연산이 지연되거나 갑자기 나타나는 어색함을 개선하기 위해 미리 2~4개 요소를 추가로 렌더링해둔다.

 

이렇게 핵심적인 포인트를 나열해봤지만, 실제 구현하기 위해서는 더 복잡한 과정을 거쳐야

가상 스크롤을 구현할 수 있을 것입니다.

 

때문에 더 쉬운 방법을 소개드리려 합니다.

 

👍🏻 고맙다, 최고 Tanstack!

첫번째로 수 많은 개발자들이 사랑하는 Tanstack 시리즈 중 하나인

Tanstack Virtual 입니다.

 

생태계가 활발해서 유지보수가 지속적으로 이루어지고 있고, Docs가 잘 되어있으며 번들사이즈까지 작습니다.

Frontend 개발자로서 Tanstack을 사랑하지 않을 수가 없군요...

 

그렇게 확장성도 용이하고 사용하기 쉬운 장점만해도 활용가치가 충분하다고 생각합니다.

 

👍🏻 고맙다, 최고 CSS!

두번째로는 훨씬 간편하고 빠르게 적용시킬 수 있는 방법으로 2024년에 표준이 된

CSS의 content-visibility 입니다.

 

등장한 것은 Chrome에서 2020년에 가장 먼저 도입되었고, 이어서 2024년에서는 Edge, Firefox, Safari 모두 표준화되어 활용 가치가 높아졌습니다.

 

기존의 방식은 JS 활용한 수동식 눈속임이었다면, content-visibility는

"브라우저 엔진 차원에서 지원하는 공식적인 렌더링 최적화 기술"이라고 표현할 수 있습니다.

 

추가적으로 함께 쓰이는 contain-intrinsic-size가 존재하는데, 이 속성은 렌더링 전 요소의 높이를 미리 추정하여 스크롤바가 튀는 현상 방지할 수 있는 속성으로 UX에 저해되지 않도록 같이 활용되는 경우가 많습니다.

 

✨ 정리하자면

구분 가상 스크롤 (JS 방식) content-visibility: auto (CSS 방식)
구현 난이도높음
(라이브러리 필요, 스크롤 계산 복잡)
매우 낮음 (CSS 두 줄 추가)
DOM 상태 화면 밖 요소는 DOM에서 제거됨 DOM에 존재하지만 렌더링만 생략
접근성 페이지 내 검색(Ctrl+F) 시 검색 안 됨 페이지 내 검색 시 자동으로
렌더링되어 감지됨
정확도 스크롤바 위치 계산 오류가 있는 편 브라우저가 직접 관리하여 매우 정확함

 

두가지 방법 모두 장단점이 있는 편이지만, 압도적으로 많은 데이터로 DOM에 존재하는 것 자체가 부담이라면 Tanstack Virtual과 함께 내부 검색이 가능한 커스텀 검색 UI를 구현하여 활용하고, 절충이 가능한 수준이라면 content-visibility를 활용하는 것이 합리적으로 느껴졌습니다.

 

✍🏻 마치며...

사내에서 많은 리팩터링과 다양한 상황에 대한 대응책으로 아이디어를 떠올리고 해결 해본 경험도 중요하지만, 대규모 시스템 즉, 예측 가능하면서도 경험 이전에 설계, 대응이 어렵고 이미 문제가 발생하고 나서는 늦어버리는 재해같은 위험을 미리 대비할 수 있는 방향으로 사고하고, 최소한의 대응책은 마련해둘 수 있는 지식 또한 중요하다는 생각이 들었습니다.

 

기업 서비스 특성상 대규모 시스템을 대비하고 실무에서 설계해본 경험이 없다보니 자연스럽게 관심이 사라지고, 희미해져가는 것 같았습니다. 이러한 사고방식은 위험하고, 경계해야겠다고 다짐하며 다시 한번 치명적인 문제에 대비할 수 있는 설계의 중요성을 깨닫고 실천하고자 다짐하는 계기가 되었습니다.