Next.js - window is not defined?

베이시스·2022년 7월 18일
0
post-thumbnail

배경

첫 Next.js 프로젝트로 개인 포트폴리오 웹 사이트를 개발할 때의 이야기입니다. window 크기를 사용해야 할 일이 있어 React에서 했던 것처럼 자연스럽게 window 사이즈 Hook을 만들어 사용하려 했는데...

웬걸, window가 없답니다.

왜 그럴까?

결론부터 말하면 클라이언트 사이드 렌더링과 서버 사이드 렌더링의 차이 때문이었습니다.
Next.js는 페이지를 최초로 렌더링할 때 서버에서 렌더링하는데(SSR) 여기에는 window, document와 같은 브라우저 전역 객체가 없습니다.
해당 전역 객체는 클라이언트 사이드에서만 사용할 수 있기에 코드를 약간 수정해 주어야 합니다.

해결 방법 1: typeof

if (typeof window !== undefined) {...}

window 객체가 있는지 확인하는 기본적인 방법입니다.

해결 방법 2: useEffect (componentDidMount)

const windowInfo = useWindow(); // custom hook

useEffect(() => {
  ...
}), [windowInfo]);

클라이언트 렌더링 이후 동작하는 useEffect hook을 사용할 수 있습니다.

해결 방법 3: dynamic import

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의 확장이기 때문입니다.

부족한 글 읽어 주셔서 감사합니다.

profile
사진찍는 주니어 프론트엔드 개발자

0개의 댓글