본문 바로가기
코딩이야기/트러블슈팅

[Next.js] build시 정적 페이지 생성 오류

by TaeHyeon0412 2024. 9. 6.

 

프로젝트 build시 정적 페이지를 생성하는 도중 발생한 문제가 생겼습니다.

수정 버튼을 누르고 useSearchParams() 훅을 사용할 때 발생한 오류인데 원인을 분석해보니 

 

아이템 수정을 누르면 url에 ?id=113으로 동적으로 id를 useSearchParams() 로 불러오고 있는데 페이지를 정적 페이지로 만들려고 해서 난 오류인 것 같습니다.

정적 페이지 SSG - 누가보더라도 똑같은 페이지일 때

동적 페이지 SSR - 누가 보는지에 따라 변하는 페이지

 

// 동적 페이지로 설정
export const dynamic = "force-dynamic";

동적 페이지로 강제로 설정하여 build 해보았으나 해결이 되지 않았습니다.

 

오류 내용대로 useSearchParams() 훅이 Suspense로 감싸져야 하기 때문에 upload form을 component로 만들고 Suspense로 form을 감싸주었습니다.

 

여기서 Suspense란?

Suspense는 React에서 비동기 데이터 로딩을 다루기 위한 컴포넌트입니다. 주로 비동기 데이터가 준비되기 전에 로딩 상태를 사용자에게 보여주기 위해 사용됩니다.

Suspense 사용 사례

  1. 데이터 페칭:
    •   서버에서 데이터를 불러오는 동안, 화면이 빈 상태로 남아있기보다는 로딩 상태를 보여주기 위해 사용됩니다. 예를 들어, 서버에서 API 요청으로 데이터를 받아오고, 그 데이터가 준비되면 화면에 렌더링하는 구조에서 유용합니다.
  2. 코드 스플리팅:
    •   React의 Lazy Loading(지연 로딩)을 통해 컴포넌트를 비동기적으로 로드할 때 Suspense를 사용하여 로드되는 동안 로딩 UI를 표시할 수 있습니다.
  3. 클라이언트 사이드 렌더링:
    •   Next.js에서는 useSearchParams()useRouter() 같은 클라이언트 전용 훅을 사용하여 클라이언트 사이드에서 동작하는 데이터를 처리할 때, Suspense를 사용하여 비동기 로딩 상태를 관리할 수 있습니다.

 

즉, Next.js에서는 서버 사이드 렌더링(SSR)과 정적 사이트 생성(SSG)이 기본적으로 사용되는데, 이러한 렌더링 방식에서는 서버에서 모든 데이터를 미리 받아와서 페이지를 렌더링합니다.

그러나, 클라이언트에서만 사용할 수 있는 useSearchParamsuseRouter 같은 훅은 서버에서는 동작하지 않으며, 클라이언트 사이드에서 동작해야만하고 그 데이터를 처리하기 위해서는 Suspense를 이용하여야 한다는 것!

upload form을 component화 & Suspense 적용

import TopNav from "@/app/_components/common/top_nav";
import UploadForm from "@/app/_components/common/upload/uploadForm";
import React, { Suspense } from "react";

// 동적 페이지로 설정
export const dynamic = "force-dynamic";

export default function Upload() {
  return (
    <>
      <TopNav kind="upload" />

      <div className="nav_h layout_px grid grid-cols-1 md:grid-cols-12 w-full min-h-screen">
        {/* 사이드 */}
        <div className="hidden md:flex flex-col md:col-span-2 "></div>

        {/* 본문 */}
        <div className="col-span-full md:col-span-8 ">
          <Suspense>
            <UploadForm />
          </Suspense>
        </div>

        {/* 사이드 */}
        <div className="hidden md:flex flex-col md:col-span-2 ">
          </div>
        </div>
      </div>
    </>
  );
}

 

 

build 오류 해결 완료!