🚨 발생 문제
Unhandled Runtime Error
Next.js에서 텍스트 에디터 라이브러리인 react-quill을 불러오는데 document is not defined라는 에러 메시지 발생
🤔 문제 원인
react-quill 라이브러리는 SSR을 지원하지 않음
- Next.js는 기본적으로 서버 사이드에서 렌더링을 하는데, react-quill 라이브러리는 SSR을 지원하지 않고, 클라이언트에서만 동작
- quill editor는 document 객체를 조작해 동작하므 document 객체가 로드 된 이후 quill 에디터를 import 하도록 해야 함
💊 해결 방법
Lazy Loading
- Next.js의 Lazy loading은 경로를 렌더링하는 데 필요한 JavaScript의 양을 줄여 애플리케이션의 초기 로딩 성능을 개선하는 데 도움됨
- 이를 통해 클라이언트 컴포넌트와 가져온 라이브러리의 로딩을 지연시키고 필요할 때만 클라이언트 번들에 포함할 수 있다. 예를 들어 사용자가 클릭하여 모달을 열 때까지 로딩을 지연시키고 싶을 수 있음
- Next.js에서 Lazy loading을 구현할 수 있는 방법 두 가지
- next/dynamic을 이용한 동적 가져오기(Dynamic Imports)
- Suspense와 함께 React.lazy()를 이용하는 방법
Dynamic Import
- Dynamic import는 개발자가 모든 것을 미리 로드하는 대신 필요에 따라 구성 요소 또는 모듈을 로드할 수 있도록 하는 기능
- 자바스크립트 모듈 또는 컴포넌트를 동적으로 로드하는데 사용됨
- 코드 분할이 가능하므로 필요할 때 코드의 필요한 부분만 로드되고, 초기 로딩 시간이 줄어들어 웹사이트가 더 빠르고 반응성이 좋아짐
import dynamic from 'next/dynamic';
import { useMemo, useRef } from 'react';
import Loading from '@/app/loading';
import ReactQuill, { ReactQuillProps } from 'react-quill';
import 'react-quill/dist/quill.snow.css';
interface ForwardedQuillComponent extends ReactQuillProps {
forwardedRef: React.Ref<ReactQuill>;
}
// dynamic import
const QuillWrapper = dynamic(
async () => {
const { default: QuillComponent } = await import('react-quill');
const Quill = ({ forwardedRef, ...props }: ForwardedQuillComponent) => (
<QuillComponent ref={forwardedRef} {...props} />
);
return Quill;
},
{ loading: () => <Loading />, ssr: false },
);
// ... 중간 생략
const TextEditor = ({content, setContent}: EditorProps) => {
const quillInstance = useRef<ReactQuill>(null);
// ... const modules, const formats 중간 생략
return (
<QuillWrapper
className="h-5/6"
forwardedRef={quillInstance}
value={content}
onChange={setContent}
modules={modules}
formats={formats}
theme="snow"
placeholder="내용을 입력해주세요."
/>
)
}
export default TextEditor
"use client';와 차이점
- Nextjs에서는 import로 모듈을 불러오는 것도 서버 사이드로 이루어진다.
- use client
- 서버 측 렌더링을 아예 비활성화 하는 경우에 사용
- “use client”;을 입력해주는 것은 그 파일을 클라이언트 컴포넌트로 취급하고 컴파일하겠다는 의미
- dynamic import
- SSR과 호환되지 않는 라이브러리를 클라이언트 측에서만 로드하고 실행할 때 사용하는 일반적인 방법
- "use client"를 사용하면 컴포넌트가 클라이언트 측에서만 렌더링되도록 제한할 수 있지만 react-quill은 초기 렌더링 시 서버 측에서는 사용할 수 없음
- “use client”를 사용해도 react-quill 라이브러리 자체가 서버에서 지원하지 않기 때문에 SSR 처리를 해주어야 하므로 근본적인 해결 방안이 아님
참고 사이트
nextjs에서 dynamic import로 quill editor 사용하기