[트러블슈팅] Scroll to Top 버튼 및 페이지 이동 시 스크롤 맨 위 미작동 이슈 해결

송수빈송수빈
4 min read

이런 식으로 버튼들을 오른쪽 하단에 빼주었다 ✨

아무래도 글이 많아지면 스크롤을 아래로 계속 내렸다가 다시 위로 올리는 게 꽤 귀찮고 요즘 대부분의 웹사이트에서도 이 기능을 제공하고 있다..! (다들 아시다시피 😘)

근데 작동을 안 해요🙂‍↔️ ㅋㅋㅋㅋㅋㅋ

👻 기존코드

(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는 동작하지 않는 문제…👿

해결해보자 ‼️

  1. 스크롤이 브라우저 window에서 발생하도록 구조와 CSS를 조정했다
  html,
  body {
    @apply w-full h-full min-h-screen p-0 m-0 overflow-auto;
  }

이 부분에서

  1. h-full : 부모 요소의 높이를 따라가야만 제대로 작동함
  • htmlbody#root → 그 하위 컴포넌트

  • 여기서 h-full부모가 정확한 높이를 가지고 있어야 의미 있음

    • 그런데 html이나 bodyh-full을 주면, 그 안의 콘텐츠가 넘쳐도 확장되지 않고 스크롤이 생기지 않음
      → 브라우저는 window 전체를 높이로 딱 맞춰버림!!!!
  1. overflow-auto높이가 초과될 때만 스크롤 생성

    • 그런데 위에서 h-full로 높이를 딱 맞췄기 때문에, overflow가 안 생김

    • 페이지 내용이 1000000000px이어도 body가 100vh로 고정돼 있어서 window에 스크롤이 안 생기고
      실질적으로는 자식 요소에서 스크롤이 생기거나, 아무 데서도 안 생김!!!!!!!

🤦🏻‍♀️ 어떤 관련성이 있냐고 ?

window.scrollTo는 브라우저 window 객체에 스크롤이 존재할 때만 작동하는데

→ 내가 작성한 코드에서는 실제 스크롤이 window가 아니라 내부 요소에 생겨서 window.scrollTo({ top: 0 })가 아무 반응을 하지 않게 되는 것…

🌱 수정 코드

  1. h-full, overflow-auto 제거
html,
  body {
    @apply w-full p-0 m-0;
    overflow: visible;
  }
  1. ScrollAndWriteButton.jsx 수정

    • #root를 삭제해주었다(#root는 스크롤 요소가 아니기 때문) + 실제 스크롤이 window에서 일어나고 있음
const handleTop = () => {
  window.scrollTo({
    top: 0,
    behavior: 'smooth',
  })
}

  • 위로 올라가는 버튼 완성!

  • 그리고 화면 이동시에 맨 위로 스크롤 되는 부분도 확인 👍🏻

🌱 느낀점 & 배운점

  1. 스크롤 컨테이너가 어디인지 정확히 파악하는 게 중요하다.

    • 특정 레이아웃이나 CSS 구조에 따라 내부 특정 요소가 스크롤 컨테이너가 되는 경우가 많다.!!
  • 당연히 window.scrollTo가 잘 작동할 거라 생각하고 작성했는데.. 실제 스크롤 이벤트와 스크롤 위치는 언제나 최상위 window가 아닐 수 있다는 점
  1. CSS 높이(height) 설정에 따른 스크롤 발생 원리를 이해하게 되었다

    • html, body, #root 등 부모 요소의 height: 100% 설정이 콘텐츠 확장과 스크롤 생성에 어떻게 영향을 주는지 그리고 overflow-auto와 함께 어떻게 동작하는지 실제로 경험하며 배웠다.

    • 잘못된 height 설정은 의도와 다르게 스크롤이 사라지고 이로 인해 window.scrollTo가 작동하지 않는 상황이 발생할 수 있다는 것을 깨달았다

  2. React Router에서 페이지 이동 후 스크롤 위치 초기화도 같은 맥락에서 문제를 재점검
    페이지가 전환될 때 window.scrollTo가 동작하지 않았는데! 이 문제는 스크롤 컨테이너 문제 때문임을 알게 되었고 이를 해결하기 위해 구조와 스타일을 점검하는 습관을 들여야겠다고 느꼈다.

  3. UI/UX 개선에 있어 디테일한 부분까지 놓치지 않고 점검하는 과정이 중요하다
    단순히 버튼을 띄우고 이벤트를 연결하는 것뿐 아니라 사용자가 실제 경험하는 인터랙션에 문제가 없는지 꼼꼼히 확인해야 한다는 점을 다시 한번 느꼈다.

0
Subscribe to my newsletter

Read articles from 송수빈 directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

송수빈
송수빈