티스토리 뷰
히스토리 복원 관련한 기능을 구현하던 중 스크롤 이슈에 부딪혔다. 페이지로 다시 복귀했을 때, 스크롤 위치값을 가지고 있는데에도 불구하고 스크롤이 최상단으로 가는 문제였다. 분명 흔하게 사용되는 기능이기 때문에 해결하는 방법이 있을 것 같아 이리저리 찾아 해결한 방법을 소개하고자 한다.
참고로 해결방법은 너무 쉬웠으며, 심지어 이전에 포스팅 했던 내용중에 잠깐 언급된 적도 있었다. (반성해 ㅜㅜ...)
✔️ 정확하게 어떤 상황이었을까?
내가 마주한 상황은 이러했다.
사용자가 페이지에서 스크롤을 내리고, 창을 켜는 등의 어떠한 액션을 한다 -> 해당 페이지를 떠날 때, sessionstorage에 해당 페이지를 특정할 수 있는 고유의 key값과 데이터, 창 오픈 값(T/F), 스크롤 위치 등의 정보를 저장한다 -> 이후 동일한 페이지에 복귀했을 때, 데이터와 스크롤 및 창 상태 등을 그대로 유지시켜준다.
의 시나리오에서 가장 중요한 '그대로 유지'시켜준다가 수행되지 않았다. 수행되지 않은 부분은 상단에 언급한 것 처럼 '스크롤'에 관한 이슈였는데, scroll Y 값을 가지고 있는데에도 불구하고 잠깐 내려갔다가 다시 최상단 0값으로 올라오는 현상이 있었다.
✔️ 의심했던 부분
일단 첫번째로 의심했던 부분은 랜더링 관련 부분이다. 데이터가 저장되어있지만 화면 자체는 다시 그려야 할 수 밖에 없는 상황에서 혹시 화면이 채 그려지기 전에 스크롤을 복귀시키려고 했던건 아닌지 의심하였다. 이렇게 되면 저장하고 있는 Y값만큼 화면이 충분히 그려지지 않아서 최대한 밑으로 갔다가 실패하여 최상단으로 올라오는 것이라 생각했다.
이 문제 때문에 그런 것은 아니었지만 결과적으로 이 부분도 해결했어야 하는 부분이라 생각하여 코드를 수정하였다.
const restoreHistory = () => {
// 세션 스토리지에서 데이터를 불러 화면을 복귀하는 작업
setTimeout(() => {
// 스크롤을 복구하는 로직
}, 0);
}
setTimeout을 0초로 설정하여 사용하는 것을 별로 좋아하지는 않지만 상단과 같은 방식으로 해결하였다. 혹시 왜 그렇게 사용했는지 궁금한 분은 하단 URL에 setTimeout과 task Queue, call stack에 관하여 읽어보면 좋을 것 같다. (정리해둔 과거의 나 칭찬해)
https://hyermione.tistory.com/74
✔️ 그럼 뭐가 문제였을까?
문제가 되었던 부분은 바로 history api의 설정에 있다.
우선 의도하지 않게 최상단으로 스크롤링 되는 이유는 크롬의 특성이라고 한다. 그런데 한가지 이해가 되지 않는 점은 bfcache로 인하여 스크롤이 복원되지 않기 때문에 최상단으로 이동한다면 이해 하겠지만 이와 반대로 크롬에서 스크롤을 복원하려는 특징때문에 해당 현상이 일어난다고 한다. 페이지를 떠날 때, 스크롤이 0으로 이동하고 이를 복원하려는 걸까? 이러면 복원하려는 특징이 의미가 있는것일까? 이 부분은 추후에 다시 포스팅을 작성해보도록 해야겠다.
아무튼 스크롤을 임의로 지정해주기 위해서는 크롬의 스크롤 복원 특징을 없애주어야 하는데, 다행히 해결방법이 history API의 속성에 있다. 바로 scrollRestoration 속성을 manual로 설정해주는 것이다. 속성 이름도 아주 직관적이다.
// 사용자 스크롤 위치 복원 활성화(기본값)
window.history.scrollRestoration = 'auto';
// 사용자 스크롤 위치 복원 비활성화
window.history.scrollRestoration = 'manual';
생각보다 간단하게 해결할 수 있는 부분이라 다행이었다.
✔️ History API
이 포스팅은 이전에 history API에 관하여 담은 이야기이다. 분명 이 곳에도 scrollRestoration을 언급했는데에도 상단 이슈를 해결할 때에 전혀 생각이 안났을 뿐더러 완전 생소한 기능처럼 느껴졌다. 이 포스팅에 들어올 때마다 그 날의 반성과 history web api와 더 친해지고자 url을 첨부해둔다.
https://hyermione.tistory.com/109
'JavaScript > JS' 카테고리의 다른 글
Intersection Observer API의 개념 및 사용법 / 고속 스크롤에 대한 이슈 (0) | 2022.09.15 |
---|---|
페이지 탭 이동 혹은 최소화 등을 감지하는 visibilitychange event (0) | 2022.09.13 |
모바일 사파리에서는 pagehide/show를 사용할 것 (0) | 2022.08.30 |
lodash란 무엇인가 (es6 기본 제공 문법보다 빠른가요?) (0) | 2022.08.08 |
js scroll을 부드럽게 만드는 방법 (+ 사파리 적용) (0) | 2022.08.02 |
- Total
- Today
- Yesterday
- 리코일
- js
- 자바스크립트
- 리액트
- 리액트상태관리
- 리액트훅
- javascript
- 깃명령어
- sentry
- reacthook
- gitRebase
- 깃
- react
- frontend
- 프론트앤드
- BFCache
- vue
- 프론트엔드
- 김민태
- npm
- js테스트
- 센트리모니터링
- CSS
- 센트리
- storybookUI
- Git
- 모바일사파리
- 사파리
- TIL
- 크롬
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |