My Boundary As Much As I Experienced

Next.js에서 window is not defined 에러 해결법 본문

FrontEnd/Browser Optimization

Next.js에서 window is not defined 에러 해결법

Bumang 2024. 7. 21. 19:54

"window is not defined" 오류는 서버 사이드 렌더링(SSR) 환경에서

클라이언트 측 객체인 window가 정의되지 않아서 발생한다.

Next.js는 기본적으로 SSR을 사용하기 때문에,

클라이언트 측에서만 접근 가능한 객체(window, document, 등)를 직접 사용하면 이 오류가 발생한다.

이 문제를 해결하려면 클라이언트 측 코드가 서버 측 코드와 분리되어 실행되도록 만들어야 한다.

 

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

typeof 연산자를 사용하여 window 객체가 정의되었는지 확인하고, 클라이언트 측에서만 실행되도록 할 수 있다.

import { useEffect, useState } from 'react';

export default function ExampleComponent() {
  const [windowWidth, setWindowWidth] = useState(0);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      // 클라이언트 측에서만 실행됨
      setWindowWidth(window.innerWidth);

      const handleResize = () => setWindowWidth(window.innerWidth);

      window.addEventListener('resize', handleResize);
      return () => window.removeEventListener('resize', handleResize);
    }
  }, []);

  return (
    <div>
      <p>Window width: {windowWidth}px</p>
    </div>
  );
}

 

2. useEffect

useEffect 훅은 클라이언트 측에서만 실행되기 때문에,

클라이언트 전용 코드를 useEffect 안에 넣어서 클라이언트 환경을 보장하는 방법이 있다.

import { useEffect, useState } from 'react';

export default function ExampleComponent() {
  const [windowWidth, setWindowWidth] = useState(0);

  useEffect(() => {
    // 클라이언트 측에서만 실행됨
    setWindowWidth(window.innerWidth);

    const handleResize = () => setWindowWidth(window.innerWidth);

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return (
    <div>
      <p>Window width: {windowWidth}px</p>
    </div>
  );
}

 

 

3. Dynamic Import

다이나믹 임포트를 사용하여 클라이언트 측에서만 특정 모듈을 로드하도록 처리할수도 있다.

특히 Next.js는 Next.js만의 다이나믹 임포트 기능을 제공하기 때문에 이를 사용하여 이 문제를 해결할 수 있다.

다이나믹 임포트를 사용하면 클라이언트 측에서만 필요한 모듈을 로드할 수 있으므로

서버 사이드 렌더링 시 발생하는 문제를 피할 수 있다.

 

import dynamic from "next/dynamic";

const ReactRTE = dynamic(() => import("../../components/Editor"), {
	ssr: false,
});

// ... use <ReactRTE /> as your component.