Zustand

Next.js에서 Zustand와 Supabase를 사용할 때 새로고침 시 상태가 초기화되는 문제 해결

해보구 2025. 2. 20. 16:27
반응형

React에서 상태를 관리할 때 useState나 useStore(Zustand)를 사용할 경우, 브라우저 새로고침 후 상태가 초기화되는 문제가 발생할 수 있다. 특히, Supabase와 같은 외부 데이터베이스에서 데이터를 불러와 Zustand에 저장한 후 사용할 때, 새로고침을 하면 UI에는 데이터가 없지만, Supabase에서 데이터를 다시 불러와야 하는 상황이 반복될 수 있다.

이 문제는 클라이언트 사이드에서만 데이터를 가져오도록 설정했기 때문에 발생했다. Next.js의 App Router에서는 클라이언트 컴포넌트가 처음 렌더링될 때 상태가 초기화되며, 서버에서 데이터를 미리 가져오지 않으면 클라이언트가 비어 있는 상태로 시작하게 된다.

발생한 문제

Zustand를 이용해 보드 목록을 상태로 저장하고 있었지만, 새로고침 시 상태가 초기화되어 보드가 렌더링되지 않았다.

const { boards, setBoards } = useStore();

const fetchBoards = async () => {
  const { data, error } = await supabase.from("boards").select("*");
  if (!error && data) {
    setBoards(data);
  }
};

useEffect(() => {
  fetchBoards();
}, []);

위 코드는 보드를 가져오는 fetchBoards()를 useEffect에서 실행하는 방식이다. 이 경우 새로고침을 하면 Zustand의 상태가 초기화된 후 비어 있는 배열에서 시작하기 때문에, 보드 목록이 보이지 않고 빈 상태가 된다. create 페이지에서 다시 데이터를 추가하면 fetchBoards()가 실행되면서 목록이 정상적으로 갱신되지만, 이는 올바른 동작 방식이 아니다.

 

해결 방법

이 문제를 해결하기 위해 서버에서 초기 데이터를 불러와서 클라이언트 컴포넌트에 전달하는 방식을 적용했다. Next.js의 App Router에서는 page.tsx 같은 서버 컴포넌트에서 데이터를 미리 불러와 props로 전달할 수 있다.

import Home from "./Home";
import { supabase } from "../lib/supabase";

export default async function Page() {
  const { data: boards, error } = await supabase.from("boards").select("*");
  return <Home initialBoards={boards || []} />;
}

이제 클라이언트 컴포넌트에서는 initialBoards라는 props를 받아 초기 상태를 설정하면 된다.

 

 

"use client";

import { useState } from "react";
import BoardList from "../components/BoardList";

export default function Home({ initialBoards }: { initialBoards: any[] }) {
  const [boards, setBoards] = useState(initialBoards);

  return (
    <div>
      <BoardList boards={boards} />
    </div>
  );
}

이렇게 변경하면, 초기 렌더링 시 서버에서 받아온 보드 목록을 initialBoards로 전달하기 때문에, 새로고침을 해도 Zustand의 상태가 초기화되면서 빈 상태로 시작하지 않는다.

 

 

회고

Next.js에서 Zustand와 Supabase를 함께 사용할 때, 클라이언트 상태를 직접 관리하면 새로고침 후 상태가 사라지는 문제가 발생할 수 있다. React의 상태 관리 방식은 새로고침이나 페이지 이동과 같은 이벤트에서 유지되지 않기 때문이다.

이 문제를 해결하려면 서버에서 초기 데이터를 받아와 상태를 초기화하는 방식이 필요하다. Next.js의 App Router에서는 서버 컴포넌트를 활용하여 데이터를 미리 가져오고, 이를 클라이언트 컴포넌트에서 활용할 수 있다.

초기에는 useEffect에서 데이터를 불러오는 방식만 사용했지만, Zustand의 상태는 클라이언트에서 관리되므로 브라우저 새로고침 후에는 상태가 유지되지 않는다는 점을 간과했다. 결국, 서버에서 데이터를 미리 가져와 클라이언트에서 초기 상태를 설정하는 것이 더 안정적인 방법이라는 것을 확인할 수 있었다.

이 과정에서 Next.js의 서버 컴포넌트와 클라이언트 컴포넌트의 역할을 명확히 이해할 수 있었고, 데이터 페칭과 상태 관리를 함께 고려해야 한다는 점을 다시 한번 확인하게 되었다.

반응형