첫 Next.js 프로젝트로 개인 포트폴리오 웹 사이트를 개발할 때의 이야기입니다. window 크기를 사용해야 할 일이 있어 React에서 했던 것처럼 자연스럽게 window 사이즈 Hook을 만들어 사용하려 했는데...
웬걸, window가 없답니다.
결론부터 말하면 클라이언트 사이드 렌더링과 서버 사이드 렌더링의 차이 때문이었습니다.
Next.js는 페이지를 최초로 렌더링할 때 서버에서 렌더링하는데(SSR) 여기에는 window, document와 같은 브라우저 전역 객체가 없습니다.
해당 전역 객체는 클라이언트 사이드에서만 사용할 수 있기에 코드를 약간 수정해 주어야 합니다.
if (typeof window !== undefined) {...}
window 객체가 있는지 확인하는 기본적인 방법입니다.
const windowInfo = useWindow(); // custom hook
useEffect(() => {
...
}), [windowInfo]);
클라이언트 렌더링 이후 동작하는 useEffect hook을 사용할 수 있습니다.
import dynamic from "next/dynamic";
const AppbarWithoutSSR = dynamic(() => import("./Appbar"), {
ssr: false,
});
export default AppbarWithoutSSR;
브라우저 전역 객체를 이용해야 하는 컴포넌트를 클라이언트에서 렌더링하도록 강제하면 정상적으로 window 등을 사용할 수 있습니다.
필자는 최종적으로 3번을 사용했습니다. 1번이나 2번으로도 충분히 문제를 해결할 수 있지만 기왕 Next.js를 사용한 만큼 next스럽게(?) 해결하고 싶었습니다.
한편, next/dynamic은 앞서 사용한 CSR 강제뿐 아니라 React의 suspense와 조합하여 컴포넌트 로딩이 완료되기 전에 표시할 fallback도 지정할 수 있습니다. next/dynamic이 React.lazy의 확장이기 때문입니다.
부족한 글 읽어 주셔서 감사합니다.