[SoundLink] URL이 부여되는 모달시트 구현하기

강수영·2025년 7월 22일
0
post-thumbnail

❗ 기존 방식의 한계

이전에는 사용자가 게시글을 클릭하면 useState로 모달 시트를 제어하고, 선택된 게시글 데이터는 props로 전달했습니다.

하지만 이 방식에는 몇 가지 문제가 있었습니다:

  • 새로고침 시 상태가 초기화되어 모달이 닫혀버림
  • URL에 선택된 게시물 정보가 없으므로 다른 사람에게 공유할 수 없음
  • 모달을 열고 닫는 이력이 브라우저 히스토리에 남지 않아 뒤로 가기 UX가 어색함

URL이 부여되는 모달 구현하기

아래 두 가지 요구사항을 기준으로 설계했습니다.

  1. postId를 포함한 URL로 직접 접근 할 수 있어야 한다.
  2. 목록 ↔ 모달 전환 및 뒤로가기 시 스크롤 위치가 유지되어야 한다.

📌 React Router의 Outlet 기반 모달 오버레이

사용자가 게시물을 클릭해도 스크롤이 초기화되지 않고, 상세 내용을 모달로 띄운 뒤 닫았을 때 다시 원래 위치로 돌아오게 만들고 싶었습니다.

이를 위해 :postId 파라미터를 중첩 라우팅 구조로 설정하고, <Outlet />을 활용해 기존 페이지 위에 모달 시트를 오버레이하는 방식으로 설계했습니다.

// app.tsx
<Route path="/mypage" element={<MyPage />}>
  <Route path=":postId" element={<CardDetailModal />} />
</Route>

// MyPage.tsx
export default function MyPage() {
  return (
    <div>
      <MyProfileSection />
      <Outlet />
    </div>
  );
}

✅ React Router의 state를 활용한 스크롤 이동 제어

React Router는 페이지 전환 시 스크롤을 자동으로 맨 위로 올려주지 않기 때문에, 이를 위해 ScrollToTop 컴포넌트를 사용해 스크롤을 수동으로 관리하고 있었습니다.

function ScrollToTop() {
  const { pathname } = useLocation();

  useEffect(() => {
    window.scrollTo({
      top: 0,
    });
  }, [pathname]);

  return null;
}

/mypage에서 /mypage/:id로 이동시 모달은 기존 페이지 위에 띄워지지만, React Router는 페이지 이동으로 간주해 스크롤을 맨 위로 올리는 문제점이 있었습니다.

이를 React Router의 state 값을 활용해 스크롤을 제어했습니다.

모달 페이지로 이동할 때 navigate, Link 태그를 사용하는 경우 다음과 같이 state 값을 전달했습니다.

// navigate를 사용하는 경우
navigate(`${basePath}/${record.recordId}`, {
  state: { scrollLock: true },
});

// Link 태그를 사용하는 경우
<Link
  to={newPath}
  state={{ scrollLock: true }}
>

그리고 ScrollToTop 컴포넌트에서는 useLocation을 통해 전달된 state 값을 활용하여, scrollLocktrue인 경우에는 스크롤을 수행하지 않도록 설정했습니다.

function ScrollToTop() {
  const { pathname, state } = useLocation();

  useEffect(() => {
    if (state?.scrollLock) return; // scrollLock이 true면 스크롤 안 함

    window.scrollTo({
      top: 0,
    });
  }, [pathname]);

  return null;
}

이렇게 하면 모달 열기/닫기 시에는 스크롤이 유지되고, 그 외의 일반적인 페이지 이동에서는 정상적으로 스크롤이 맨 위로 이동되도록 처리할 수 있습니다.

🚀 정리

URL 파라미터(postId) 기반으로 데이터 페칭하도록 바꿔, 새로고침 및 직접 접근이 가능해졌습니다.

또한 React Router의 중첩 라우팅과 state를 활용해 모달 시트를 오버레이로 렌더링하고,열림/닫힘·뒤로가기 시 스크롤 위치를 유지하도록 설계했습니다.

출처

profile
프론트엔드 개발자

0개의 댓글