회고

스크롤 복원(Scroll Restoration)

다올백설 2022. 8. 13. 22:48

바닐라 자바스크립트든, 리액트든 여러 페이지로 구성된 서비스를 개발하기 위해서 History API를 사용할 수 밖에 없다. 

대부분 페이지 이동 메소드를 호출하거나, state를 전달하는 용도에 대해서만 주의 깊게 볼 것이다. 

 

구글 검색 예시를 떠올려보자.

1. 검색창에 history api를 검색한다. 
2. 스크롤을 내려서 원하는 검색결과를 찾는다. 
3. 원하는 검색결과를 발견하면 클릭해서, 해당 사이트로 이동한다. 
4. 뒤로가기 버튼을 클릭해서 이전 화면(검색결과)으로 이동한다.

1~4번을 거친 뒤 이전 화면으로 돌아왔을 때, 스크롤의 위치는 어디에 있을까? 

답은, 이전 화면에서 탐색한 위치이다. 이것이 스크롤 복원의 기본(default) 동작이다. 

 

대부분 상황에서 스크롤 복원을 의식하며 개발하지 않을 것이다. 

그러나 페이지 랜딩 시 무조건 스크롤을 Top으로 이동시켜야 하거나, infinite scroll 페이지를 개발하는 경우 개발자는 스크롤 복원 이슈에 부딪힐 수 밖에 없다. 

scrollRestoration auto 예시

 

이슈 1. 스크롤 Top 이동

어떤 페이지는 사이트에서의 역할, 또는 일시적인 이유(이벤트, 알람 등)로 항상 스크롤을 Top으로 이동시켜야 할 수도 있다.  (즉, 스크롤 복원을 사용하지 않을 수 있다.)

scrollRestoration의 디폴트 값은 auto이므로 manual로 명시하면 스크롤 복원을 사용하지 않으며, 페이지 랜딩 시 스크롤이 Top으로 이동한다. 

 

scrollRestoration manual 예시

if (history.scrollRestoration) {
  window.history.scrollRestoration = 'manual'; // 스크롤 복원 비활성화
}
window.scrollTo(x, y); // 원하는 위치가 있을 경우 설정해줄 수도 있다.

 

이슈 2. 무한 스크롤 

내가 운영하는 서비스는 컨텐츠 검색 기능이 있다. 예를 들어 "아이돌"이란 단어를 검색창에 입력할 경우 116개의 페이지, 2301개의 컨텐츠가 검색된다. 116개의 페이지는 무한 스크롤의 사용하여, 서버에서 응답받은 컨텐츠 목록를 덧붙이는 방식으로 제공한다. 

아이돌 컨텐츠 검색 요청 시 API 반환값

이때 매번 API 요청을 통해 컨텐츠 목록을 제공한다면 어떨까? 예를들어 3페이지 컨텐츠 목록에서 다른 페이지로 이동한 뒤 돌아왔을 때, 1~3페이지의 리스트를 다시 호출하고 머지해야만 이전 스크롤 위치로 돌아갈 수 있다. 만약 50페이지를 보고있었다면? 비용측면에서 좋지 않은 상황임은 분명하다. 

redux, mobx와 같은 상태 라이브러리를 사용하여 이 문제를 해결할 수 있다. 스크롤이 이동하여 새 페이지를 호출할 때마다, state에 목록을 머지한다면 페이지 이동 후에도 API 호출 없이 이전 스크롤 위치로 이동할 수 있다.

 

마치면서

현재 내가 운영하는 서비스도 redux를 이용하여 무한 스크롤을 제공하고 있으나, 점점 늘어나는 컨텐츠 수와 복잡해지는 상태 트리를 생각하면 가상 목록을 제공하는 방식으로 변화가 필요한 시점이다. 

 

(참고자료)

https://developer.mozilla.org/ko/docs/Web/API/History/scrollRestoration

https://v5.reactrouter.com/web/guides/scroll-restoration