[트러블슈팅] Scroll to Top 버튼 및 페이지 이동 시 스크롤 맨 위 미작동 이슈 해결
![[트러블슈팅] Scroll to Top 버튼 및 페이지 이동 시 스크롤 맨 위 미작동 이슈 해결](https://cdn.hashnode.com/res/hashnode/image/upload/v1748360121861/895836cf-c51f-4c82-9c20-6ef7585193bb.jpeg)
이런 식으로 버튼들을 오른쪽 하단에 빼주었다 ✨
아무래도 글이 많아지면 스크롤을 아래로 계속 내렸다가 다시 위로 올리는 게 꽤 귀찮고 요즘 대부분의 웹사이트에서도 이 기능을 제공하고 있다..! (다들 아시다시피 😘)


근데 작동을 안 해요🙂↔️ ㅋㅋㅋㅋㅋㅋ
👻 기존코드
(App.jsx)
import { BrowserRouter } from 'react-router-dom'
import AppRoutes from './routes/AppRoutes'
import PageScrollToTop from './components/common/PageScrollToTop'
import { useEffect } from 'react'
import { ToastContainer } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'
function App() {
return (
<BrowserRouter>
<ToastContainer position='top-center' autoClose={2000} />
<PageScrollToTop />
<AppRoutes />
</BrowserRouter>
)
}
export default App
(PageScrollToTop.jsx)
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
const PageScrollToTop = () => {
const { pathname } = useLocation()
useEffect(() => {
window.scrollTo({
top: 0,
behavior: 'smooth',
})
}, [pathname])
return null
}
export default PageScrollToTop
(ScrollAndWriteButton.jsx)
const ScrollBtn = () => {
const navigate = useNavigate()
const [showModal, setShowModal] = useState(false)
const handleCreatePostClick = () => {
setShowModal(true)
}
const handleTop = () => {
const scrollContainer = document.querySelector('#root')
if (scrollContainer) {
scrollContainer.scrollTo({
top: 0,
behavior: 'smooth',
})
}
}
(AppRoutes.jsx)
import { useEffect } from 'react'
import { Route, Routes } from 'react-router-dom'
import routes from './routes'
import Layout from './Layout'
import useAuthStore from '../store/login/useAuthStore'
const AppRoutes = () => {
const mainPaths = ['/', '/community', '/user-post', '/job']
const initialize = useAuthStore((state) => state.initialize)
useEffect(() => {
initialize()
}, [])
return (
<Routes>
{routes.map((route, index) => {
const isMain = mainPaths.includes(route.path)
return (
<Route
key={index}
path={route.path}
element={
<Layout
headerType={isMain ? 'main' : 'sub'}
label={route.label}
noMargin={route.noMargin}
>
{route.element}
</Layout>
}
/>
)
})}
</Routes>
)
}
export default AppRoutes
어떤게 문제지? 라고 했을 때
PageScrollToTop.jsx에서window.scrollTo는 브라우저 윈도우 자체 스크롤을 조작하는데실제 스크롤은
#root나 그 안쪽 div에서 발생하고 있으면window.scrollTo는 동작하지 않는 문제…👿
해결해보자 ‼️
- 스크롤이 브라우저
window에서 발생하도록 구조와 CSS를 조정했다
html,
body {
@apply w-full h-full min-h-screen p-0 m-0 overflow-auto;
}
이 부분에서
h-full: 부모 요소의 높이를 따라가야만 제대로 작동함
html→body→#root→ 그 하위 컴포넌트여기서
h-full은 부모가 정확한 높이를 가지고 있어야 의미 있음- 그런데
html이나body에h-full을 주면, 그 안의 콘텐츠가 넘쳐도 확장되지 않고 스크롤이 생기지 않음
→ 브라우저는window전체를 높이로 딱 맞춰버림!!!!
- 그런데
overflow-auto는 높이가 초과될 때만 스크롤 생성그런데 위에서
h-full로 높이를 딱 맞췄기 때문에, overflow가 안 생김페이지 내용이 1000000000px이어도
body가 100vh로 고정돼 있어서 window에 스크롤이 안 생기고
실질적으로는 자식 요소에서 스크롤이 생기거나, 아무 데서도 안 생김!!!!!!!
🤦🏻♀️ 어떤 관련성이 있냐고 ?
window.scrollTo는 브라우저 window 객체에 스크롤이 존재할 때만 작동하는데
→ 내가 작성한 코드에서는 실제 스크롤이 window가 아니라 내부 요소에 생겨서 window.scrollTo({ top: 0 })가 아무 반응을 하지 않게 되는 것…
🌱 수정 코드
h-full,overflow-auto제거
html,
body {
@apply w-full p-0 m-0;
overflow: visible;
}
ScrollAndWriteButton.jsx수정#root를 삭제해주었다(#root는 스크롤 요소가 아니기 때문) + 실제 스크롤이 window에서 일어나고 있음
const handleTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth',
})
}

위로 올라가는 버튼 완성!
그리고 화면 이동시에 맨 위로 스크롤 되는 부분도 확인 👍🏻
🌱 느낀점 & 배운점
스크롤 컨테이너가 어디인지 정확히 파악하는 게 중요하다.
- 특정 레이아웃이나 CSS 구조에 따라 내부 특정 요소가 스크롤 컨테이너가 되는 경우가 많다.!!
- 당연히
window.scrollTo가 잘 작동할 거라 생각하고 작성했는데.. 실제 스크롤 이벤트와 스크롤 위치는 언제나 최상위window가 아닐 수 있다는 점
CSS 높이(
height) 설정에 따른 스크롤 발생 원리를 이해하게 되었다html,body,#root등 부모 요소의height: 100%설정이 콘텐츠 확장과 스크롤 생성에 어떻게 영향을 주는지 그리고overflow-auto와 함께 어떻게 동작하는지 실제로 경험하며 배웠다.잘못된
height설정은 의도와 다르게 스크롤이 사라지고 이로 인해window.scrollTo가 작동하지 않는 상황이 발생할 수 있다는 것을 깨달았다
React Router에서 페이지 이동 후 스크롤 위치 초기화도 같은 맥락에서 문제를 재점검
페이지가 전환될 때window.scrollTo가 동작하지 않았는데! 이 문제는 스크롤 컨테이너 문제 때문임을 알게 되었고 이를 해결하기 위해 구조와 스타일을 점검하는 습관을 들여야겠다고 느꼈다.UI/UX 개선에 있어 디테일한 부분까지 놓치지 않고 점검하는 과정이 중요하다
단순히 버튼을 띄우고 이벤트를 연결하는 것뿐 아니라 사용자가 실제 경험하는 인터랙션에 문제가 없는지 꼼꼼히 확인해야 한다는 점을 다시 한번 느꼈다.
![[React] 클라이언트에서 이미지를 압축해보자](https://cdn.hashnode.com/res/hashnode/image/upload/v1759903597964/227ea5dc-8ff1-4999-9869-1bceb71b210a.png)
![[책 추천] 프론트엔드 개발자라면 반드시 알아야 할 '웹 접근성' 이야기](https://cdn.hashnode.com/res/hashnode/image/upload/v1753777028409/0438e77e-a609-48d8-989a-68191214a5b1.png)
![[Next.js] 나만의 학습 블로그 만들기#3-다국어 지원 (Feat.next-i18next)](https://cdn.hashnode.com/res/hashnode/image/upload/v1752472189546/a25d48d1-715a-4c90-a530-7dded2981fe7.png)
![[Next.js] 나만의 학습 블로그 만들기#4 - 댓글 기능(Feat. Giscus)](https://cdn.hashnode.com/res/hashnode/image/upload/v1752477512377/e1e868c0-6968-49f0-8fc5-91083b01ef79.png)
![[React] React + localStorage로 하루에 한 번만 보이는 팝업 만들기](https://cdn.hashnode.com/res/hashnode/image/upload/v1751525304623/4d143f95-eeac-42fb-9a95-b21d12d2e476.png)