- 이슈 내용: React로 구현된 웹 애플리케이션에서 페이지를 이동했을 때 스크롤 위치가 초기화되지 않고 이전 페이지의 스크롤 위치가 그대로 반영되는 이슈
: 배포된 페이지를 QA 할 겸 주변 지인들에게 공유했다. 퍼블리셔 시절 옆에서 많이 가르쳐주셨던 사수분께도 전달드리며 "팀장님~ 제가 이제 리액트도 할 줄 알아요~" 하고 보내놓고 뿌듯해 했는데 돌아온 답장
👩💼 : 이거 페이지 이동하면 스크롤 위치 원래 이렇게 어중간해요?
어어,, 얘가 왜이럴까 정말 당황하게되. 퇴사를 해도 사수님의 피드백은 손이 벌벌 떨렸다네요
이슈 상황을 묘사해보자면 홈 화면에서 아래쪽에 위치한 '내 MBTI 알아보러 가기' 버튼을 클릭하면 검사 페이지로 이동하는데, 이 때 1번 문항이 아닌 2~3번 문항부터 보인다는 거다.
즉, 이전 페이지에서 사용자가 보던 스크롤 위치가 그대로 유지되는 문제였다.
: 이 이슈에 대해서 스스로 내린 결론은 '리액트가 SPA이기 때문에' 였다.
index.html 파일이 유지된 채 라우팅만 변경된다. 즉, 스크롤 위치도 변경되지 않고 그대로 유지될 가능성이 높다.이를 해결하기 위해 찾아보던 중 React Router DOM에서 제공하는 ScrollRestoration을 사용해보기로 했다.
ScrollRestoration 사용import { ScrollRestoration } from 'react-router-dom';
const Login = () => {
return (
<>
<ScrollRestoration />
<div className="flex flex-col justify-center flex-1 min-h-full px-6 py-28 lg:px-8 ">
...
</div>
</>
);
};
하지만 처참히 실패 ..~
Uncaught Error: useMatches must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.
위 에러만 한 바가지로 떴다. 일단 왜 안 되는지부터 찾아보자..
ScrollRestoration은 데이터 라우터(Data Router)에서만 동작한다.
React Router v6에서 ScrollRestoration은 데이터 기반 라우터에서만 정상적으로 동작하도록 설계되었다.
그런데 내가 사용한 라우터는 createBrowserRouter가 아닌 BrowserRouter 기반의 일반적인 라우터라서 ScrollRestoration이 제대로 적용되지 않았던 거다.
ScrollRestoration은 기본적으로 브라우저의 history.scrollRestoration 을 조작하는 방식이다.
useEffect를 활용한 방법: 위 방법이 실패해서 다른 방법을 찾아보다가 페이지 이동 시 useEffect를 사용하여 스크롤을 강제로 맨 위로 끌어올리는 방법을 알게 됐다.
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
const ScrollToTop = () => {
const location = useLocation();
useEffect(() => {
window.scrollTo(0, 0); // 페이지 이동 시 스크롤을 맨 위로 초기화
}, [location]);
return null;
};
export default ScrollToTop;
: 그리고 이 ScrollToTop 컴포넌트를 라우터 내부에서 사용한다.
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import ScrollToTop from '../components/ScrollToTop';
import Home from '../pages/Home';
import TestPage from '../pages/TestPage';
const Router = () => {
return (
<BrowserRouter>
<ScrollToTop />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/test" element={<TestPage />} />
</Routes>
</BrowserRouter>
);
};
export default Router;
결과는 ..~?

: 드디어 .. 페이지가 이동할 때마다 스크롤이 맨 위로 초기화된다!
ScrollRestoration은 Data Router에서만 동작하기 때문에 Brower Router로 구현된 이번 프로젝트에서는 사용이 불가하다.useEffect 를 활용하여 window.scrollTo(0, 0)을 실행하면 스크롤을 초기화할 수 있다!