[TIL] NextJS는 window를 바로 접근할 수 없다. (window is not defined)

2022. 10. 28. 16:32React/Next.js

요즘 Next.js랑 three.js를 공부해보고 있는데,

대지를 그려주거나 할 때 window 객체에 접근할 일이 자주 있습니다.

하지만 Next.js는 SSR을 기본으로 하기 때문에 서버에서 렌더링 하는 시점에선 전역변수 window를 가져올 수 없습니다.

 

방법은 두 가지가 있습니다.

 

1. dynamic 사용

import styles from "../styles/Home.module.css";
import dynamic from "next/dynamic";

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

export default function Home() {
  return (
    <>
      <div className={styles.h1}>HELLO THREEJS!!</div>
      <ThreeJSSetting/>
    </>
  )
}

 

dynamic 안에는 React.ComponentType이 들어갑니다.

import() 안에 원하는 컴포넌트를 넣고 중요한 두 번 째 속성에서 ssr을 false로 넣어주세요.

이러면 클라이언트에서 렌더링이 되기 때문에 window 객체에도 접근이 가능해집니다.

 

https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr

 

Advanced Features: Dynamic Import | Next.js

Dynamically import JavaScript modules and React Components and split your code into manageable chunks.

nextjs.org

 

2. useEffect를 사용한 사이드이펙트 처리

csr로 돌리지 않아도 useEffect로 처리할 수 도 있습니다.

뭔가 많아서 생략했지만 이런느낌..?

밖에서 ref로 다 넣어주고 useEffect 처리에서 초기화를 해줘도 됩니다.

 

import styles from "../styles/Home.module.css";
import dynamic from "next/dynamic";
import * as THREE from "three";

export default function Home() {
  const scene = useRef<THREE.Scene | null>(null);
  const camera = useRef<THREE.Camera | null>(null);
  const canvasRef = useRef<HTMLDivElement>(null);
  
  useEffect(() => {
    if (!scene.current && !camera.current) return;
    const cube = new THREE.Mesh();
    scene.current.add(cube);
    
    camera.current = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
    //..
  }, []);
  
  return (
    <>
      <div className={styles.h1}>HELLO THREEJS!!</div>
      <div ref={canvasRef} />
    </>
  )
}