[실험]Browser Cache와 Scroll Position이 연관이 있는걸까?

alang·2021년 9월 8일
6

TIL

목록 보기
10/10

개요 ( 실험의 발단 )

이번 무한 스크롤 UI를 구현하며 팀내에서 올라왔던 질문이 있었습니다.

'강사님의 브라우저에서는 스크롤을 내리면 새로 렌더링이 될때 스크롤바가 위로 초기화되어 올라가는데, 왜 저는 스크롤바가 초기화되지 않을까요?'

분명 동일한 코드로 작성했음에도 왜 다른 형태로 렌더링될까.. 이해가 되지않는 상황이라 팀원분과 같이 고민을 했고,

다른분께서 개발자 도구에서 Disable cache의 체크 유무에 따라 스크롤 초기화 유무가 달라질수 있다는 점을 공유해주셨습니다.

그럼에도 Browser Cache에 대해 알고있는 바가 없어 이해가 잘 가지 않았습니다. 인터넷 검색을 통해 Chrome에서는 스크롤 위치를 기억하기 때문에 뒤로가기를 눌러도 이전에 기억하고 있던 scroll position으로 지정된다라는 점은 알수 있었으나 아무리 찾아봐도 browser cache에서 scroll position을 기억하고 있다는것은 찾아볼수 없었습니다. 제가 유일하게 찾은 정보는, browser cache는 static assets, 즉 Image,HTML,CSS,JavaScript를 캐싱한다 였습니다.

그렇게 의문을 품은채 강의를 듣던중에 IntersectionObserver를 이용해 무한스크롤을 구현하던중, 브라우저 캐시가 비워져 있는 상태에서 처음으로 이미지를 불러오거나, Disable cache설정이 켜진 상태에서 문제점을 발견하였습니다.

다음과 같이 분명 IntersectionObserver의 observe 대상으로 마지막 li가 잘 지정이되어있는데, 화면속에 렌더링이 되어있지 않음에도 불구하고, 해당 li가 화면속에 나타났다고 감지하여 추가적으로 렌더링을 지속하게 되었습니다. (첫화면에는 5개의 사진만 fetch 되는것이 의도된 바입니다)


그리고 이는 해당 사진들이 캐시속에 저장되어있을경우에는(Disable Cache를 끈 상태) 의도한 대로 5개의 사진만 fetch가 되었습니다.

가설

이와 같은 상황을 보며 한가지 상황을 유추해볼수 있었습니다.

이미지가 캐시에 있는지 여부에 따라, 렌더링 되는 방식이 다르구나..! 그렇다면 이미지가 캐시에 없을경우엔, li DOM 객체의 크기가 처음엔 css의 style대로 height가 정해지고, 이후 이미지가 로드됨으로서 해당 이미지의 height를 갖게 되는게 아닐까? (물론 그 이전에는 더 다양하고 이상한..? 추론들이 있었습니다)

실험 1

이를 확인해보기 위해 li의 min-height를 30vh로 css style을 지정해보고 Disable cache인 상태로 동일하게 실험을 해보았습니다.

실험은 성공이었습니다! 애초에 li는 기본 크기로 30vh의 크기를 갖기 때문에, 처음 렌더링되는 5개의 li중 4개의li만으로도 뷰포트의 범위를 벗어나게되었고 (30vh*4 = 120vh), 옵저빙 되는 5번째 li는 첫 렌더링시에 IntersectionObserver에게 관측되지 않아 추가적인 fetch는 없었습니다.

실험 1에 대한 추론

이 결과를 위의 캐시 속 이미지의 존재여부에 관한 생각과 함께 정리를 해보았습니다.

그리고 스스로 내렸던 결론으론, <img>가 렌더링될때, 캐시에 이미지가 없다면 기본적으로 비동기적으로 렌더링을 진행하고, 캐시가 이미지에 있다면 동기적으로 렌더링을 진행한다는 점이었습니다. 즉, 캐시에 이미지가 없다면 렌더링은 2차적으로 진행된다.. 라는 점이었죠 ( 정확히는 li의 height 속성이 2단계에 걸쳐서 바뀐다 )

이렇게 스스로 결론 짓고나니, 위와같은 문제가 이해가 될수있었습니다.

캐시에 이미지가 없을때는 비동기적으로 처리되기때문에, 1차적으로 렌더링이 진행되면서 li는 css style로 지정된 min-height의 크기를 가진채 렌더링되고, 이후 img가 불러와지며 해당 img의 크기에 맞게 li의 사이즈가 다시 정해진다라고 볼수있는 거였죠.

그렇기 때문에 만약 첫 렌더링시에 (불러와지는li 갯수 * li의 min-height 설정값) 이 100vh를 넘지 않는다면, 마지막 li가 화면속에 있다고 측정되며 추가적인 api 호출이 있었던겁니다.

다시 처음의 스크롤 초기화 문제

그렇게 어느정도 머리속에서 정리를 해다가, 다시 처음의 문제가 떠올랐습니다. 왜 스크롤바가 처음으로 돌아갈까.. 이것도 위에서 발견한 사실과 연관있지 않을까???

새로운 가설

그러다 문득, 어떤 한가지 생각이 떠올랐습니다.

만약 이미지 처리가 비동기적으로 이루어지는, 즉 li의 height가 2단계에 걸쳐서 바뀌는 상황에서, 1단계때(li의 height가 min-height로 정해질때), Render된 DOM들이 화면속 뷰포트를 넘어가지 않게된다. scrollBar의 필요성이 사라지므로 scrollBar가 사라지고 저장되어 있던 scroll position이 사라진다.

이후, 2단계로 li의 height가 커지며, 다시 화면을 넘치게 되면서 scrollBar가 생겨나게 되고, 이때 기억하고 있는 scroll position이 없기때문에, 해당 과정이 물흐르듯 빠르게 지나간 우리의 눈에는, 마치 scrollBar가 제일 위로 올라간듯한 착각을 준게 아닐까? 사실은 스크롤바가 사라졌다가, 다시 생겨난 것이다.

실험 2

그렇다면, scrollBar가 사라지지 않는 상황을 준다면 어떻게 될까? 이때는 scroll position을 기억하기 때문에 위치를 그대로 갖지 않을까?

아까전의 실험과 마찬가지로, li의 min-height를 30vh로 설정후 다시 실험을 진행해보았습니다.

생각했던 대로 결과가 나올수 있었습니다. 이를 통해서, scrollBar가 유지되는 동안은 해당 객체들이 다시 render되더라도 scroll position을 기억해내고, scrollBar가 사라지는 상황이 생겼을때, 기억하던 scroll position을 잃게된다라는 결론을 내리게 되었습니다.

내린 결론

궁극적으로 위와 같은 실험들을 하며 내린 결론은,

  • Browser cache는 scroll position을 기억하는 것과는 직접적인 연관을 갖지 않는다.
  • 마찬가지로, Browser cache 자체가 DOM Tree Rendering을 하는 로직에 있어, 직접적인 연관을 갖지는 않는다. ( cache의 유무 따라 reflow와 repaint 가 수행되기도, 수행 안되기도 하지만, 이는 직접적인 연관을 갖는 다고 하기엔, sideEffect 정도로 생각이 된다. )
  • <img>태그 통해 image를 불러올때는 기본적으로 비동기적인 과정으로 렌더링이 진행되고, 만약 해당 image 데이터가 캐시 속에 보관되어있다면, 동기적으로 렌더링된다.
  • 동일한 화면속에서 기억하고 있는 scroll Position을 잃어버리는 경우는, 해당 scrollBar가 사라질때이다.

와 같습니다.

과연 이 결론 도출이 맞을까요?

여러 검토를 하며 나온 결론이다 보니 스스로에겐 맞을것이다,라는 작은 확신이 있으나, 아무래도 공식 정보를 통해서나, 지식적으로 얻은 결론이 아닌, 실험을 통한 결과 도출로 내린 결론이다 보니 확신을 가질수만은 없다는 생각이 들어 이와 같이 글을 작성하였습니다.


참고 문헌

Browser Cache의 역할 :
https://www.bigcommerce.com/ecommerce-answers/what-browser-cache-and-why-it-important/

Chrome은 어디에서 scroll position을 기억할까? :
https://stackoverflow.com/questions/16239520/chrome-remembers-scroll-position
https://developer.mozilla.org/ko/docs/Web/API/Window/scrollY

profile
안녕하세요. 개발자 지망생입니다.

0개의 댓글