본문 바로가기
Front-End/NextJS

[NextJS] react-quill ReferenceError: document is not defined 에러 해결

by 흐암졸령 2022. 6. 10.
반응형

[ 문제점 ]

 Next js프로젝트에서 react-quill을 설치하고 일반적인 컴포넌트 가져오는 식으로 

import ReactQuill from react-quill

이처럼 코드를 작성하면 document is not defiend이라는 오류가 나오면서 정상적으로 작동되지 않는다.


[ 해결 방법 ]

Next JS는 SSR(Server Side Rendering)

 먼저 이러한 문제가 생긴 이유는 Next js는 SSR(server side rendering)을 하기 때문이다. SSR이란 화면에서 보여줄 페이지를 서버에서 먼저 렌더링을 한 후에 클라이언트에게 제공한다. CSR(client side rendering)을 화면을 조작한는 자바스크립트 파일을 모두 로드해야 해서 속도가 느리지만 SSR의 경우에는 서버에서 렌더링을 하고 화면을 구성하는 파일만을 전송하기 때문에 비교적 속도가 빠르다.

 

document is not defined가 생긴 이유

 그래서 왜 document is not defined라는 에러가 난 것일까. document는 모든 view 및 기능이 로두가 된 후에 정의된다. 그러나 react-quill을 로드하는데 document가 정의되지 않은 시점에서 document를 조작하려고 했기 때문에 오류가 난 것이다.

document 정의 → react quill 로드 → react quill이 document 조작

의 순서가 되어야 오류가 나지 않고 정상적으로 작동하지만, SSR이라는 점 때문에 우리의 경우에는

react quill 로드 → react quill이 document 조작 → document 정의

이런 순서대로 작동하여서 에러가 난 것이다. 이 문제를 해결하기 위해서는 어떻게 해야할까?

 

에러를 해결하기 위해서는?

 Next js는 dynamic import를 지원하는데 이는 동적으로 import를 할 수 있게한다. 이를 사용하면 react-quill을 서버 측 모듈에 포함하지 않는다. 그러면 서버에서 렌더링하는 과정에서는 import를 하지 않고, 런타임시에 모듈을 import한다. dynamic import를 사용해서 문제를 해결하는 방법은 두 가지가 있다. 처음에는 첫 번째 방법으로 사용하다가 여러 문제가 발생해 두 번째 방법을 사용함으로써 해결하였다.

 

 첫 번째 방법은 컴포넌트 파일에서 dynamic import를 하여서 React quill component를 사용하는 방법이다.

import dynamic from 'next/dynamic'

const QuillWrapper = dynamic(() => import('react-quill'), {
  ssr: false,
  loading: () => <p>Loading...</p>,
})

export default function Editor() {
  return <QuillWrapper  theme="snow" />
}

이렇게 dynamic import를 사용하면 에러가 해결된다. 그러나 처음에 이 방법대로 사용하였지만 여러 문제가 발생한다. react-quill을 그대로 사용만 하는게 아니라 custom하기 위해서 useRef를 이용해 설정하려고 했다. 그러나 dynamic import를 했기에 ref 속성을 사용할 수가 없었다. 그래서 위와는 다른 방법으로 import를 해서 해결하였지만 또 다른 문제가 있었다. 에디터를 custom하기 위해서 react-quill뿐만 아니라 'blots/inline' 또한 같이 import를 해야했다. 이렇게 여러개를 import하는 경우에는 dynamic import를 사용하자니 코드가 복잡해져서 다른 방법을 사용하기로 했다.

 

 두 번째 방법은 import를 해야 하는 것을 하나의 컴포넌트 파일로 빼고, 해당 컴포넌트를 dynamic import하는 것이다. 이렇게 하면 해당 컴포넌트 파일에서는 SSR을 신경쓰지 않고, 일반적인 React 파일처럼 작업을 할 수가 있다. 첫 번째 코드는 WirtePage.tsx의 코드이고 두 번째 코드는 Editor.tsx파일의 코드이다.

import dynamic from "next/dynamic";

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

export default function WritePage() {
  return (
    <div>
      글쓰기 페이지
      <DynamicEditor />
    </div>
  )
}
import { useRef } from "react";
import 'react-quill/dist/quill.snow.css';
import ReactQuill, { Quill } from "react-quill";

export default function Editor() {
  const editorRef = useRef<ReactQuill>(null)

  return (
    <ReactQuill
      theme={'snow'}
      ref={editorRef}
    />
  )
}

 

반응형

댓글