[Next.js] Dynamic Import 적용

[Next.js] Dynamic Import 적용

NextJS환경에서 리포팅 툴을 테스트하면서 dynamic import 라는 흥미로운 기능이 있어 공유 해 봅니다.

리포팅 툴이란 시스템에서 추출한 결과 값을 보고서 양식으로 출력해주는 개발툴입니다.

기존 프로젝트에 다른 개발자가 개발한 서비스를 적용하는 것은 생각보다 쉽지 않은 일입니다. 저는 Next.js 로 구성된 환경에 active report에서 제공하는 Report Viewer를 적용하는 과정에서 몇 차례 시행착오를 겪었습니다.


위와 같은 Report Viewer 컴포넌트를 NextJS 환경에 적용하기 위해 먼저 npm에서 필요 패키지를 다운해 줍니다.

pnpm add @grapecity/activereports-react@latest
pnpm add @grapecity/activereports

App Router를 적용한 Next.js 프로젝트의 page.tsx에 위 뷰어 모듈을 적용합니다.

import { Viewer } from "@grapecity/activereports-react";

export default function Home() {
  return (
    <div>
      <Viewer />
    </div>
  );
}

코드 실행 후 접속 하면 아래와 같은 에러를 만나게 됩니다.

window is not defined 라는 에러메세지의 원인은 Next.jsSSR 때문이었습니다. 서버 사이드에서 렌더링을 할 때에는 windowdocument 전역 객체가 존재하지 않습니다.

window 객체는 웹 브라우저에서 제공하는 전역 객체로, 웹 페이지의 전역 속성과 브라우저 창에 대한 정보와 조작 방법을 제공합니다. HTML에 대한 루트로서의 역할을 하며, JavaScript를 통해 웹 페이지를 조작할 때 사용되는 함수 및 API의 진입점 입니다.

window 객체를 통한 브라우저 조작 예제 코드는 아래와 같습니다. 브라우저 콘솔 창에서 테스트 해볼 수 있습니다.

window.open("https://naver.com", "_blank");

해당 코드를 실행하면 새로운 창이 열리면서 네이버에 접속 하는 것을 확인 할 수 있습니다.


다시 window is not defined 에러 메세지로 돌아오면 서버 사이드 렌더링시 리포트 뷰어 모듈에서 사용하는 window 객체가 존재하지 않아 발생하는 에러 메시지였다는 것을 확인할 수 있습니다.

Active Report Viewer 같은 클라이언트 사이드 모듈을 Next.js 프로젝트에서 사용할 때는 이 모듈이 클라이언트 사이드에서만 실행되도록 해야 합니다. 이때 dynamic import 를 사용하여 문제를 해결할 수 있습니다.


먼저 components 폴더를 생성 후 npm package에서 import한 뷰어를 감싸는 Wrapper 컴포넌트를 생성해 줍니다.

// ViewerWrapper.tsx

"use client";

import { Viewer, Props } from "@grapecity/activereports-react";
import "@grapecity/activereports/styles/ar-js-ui.css";
import "@grapecity/activereports/styles/ar-js-viewer.css";

export type ViewerWrapperProps = Props;

const ViewerWrapper = (props: ViewerWrapperProps) => {
  return <Viewer {...props} />;
};

export default ViewerWrapper;

page.tsx에서는 위 Wrapper 컴포넌트를 dynamic import를 사용하여 불러옵니다.

import dynamic from "next/dynamic";
import { ViewerWrapperProps } from "../components/ViewerWrapper";

const ReportViewer = dynamic<ViewerWrapperProps>(
  () => {
    return import("@/components/ViewerWrapper");
  },
  { ssr: false }
);

export default function Home() {
  return (
    <div className="w-full h-screen">
      <ReportViewer />
    </div>
  );
}

이처럼 dynamic import를 사용하여 특정 컴포넌트의 서버 사이드 렌더링을 비활성화하고, 필요할 때만 클라이언트 사이드에서 로드 할 수 있습니다.


ViewerWrapper.tsx가 "use client" 지시어를 사용하므로 클라이언트 컴포넌트이기 때문에 dynamic import 없이 아래처럼 사용해도 되지 않을까 생각해봤습니다.

import dynamic from "next/dynamic";
import ViewerWrapper, { ViewerWrapperProps } from "../components/ViewerWrapper";

// const ReportViewer = dynamic<ViewerWrapperProps>(
//   () => {
//     return import("@/components/ViewerWrapper");
//   },
//   { ssr: false }
// );

export default function Home() {
  return (
    <div className="w-full h-screen">
      {/* <ReportViewer /> */}
      <ViewerWrapper />
    </div>
  );
}

하지만 위에서처럼 직접 ViewerWrapper 컴포넌트를 사용할 경우 화면은 렌더링 되지만 내부적으로는 ReferenceError: window is not defined 가 발생합니다. 그 이유는 "use client" 지시어를 사용하더라도 page.tsx의 import 구문은 서버 사이드에서도 평가되기 때문에 ViewWrapper 내부에서 window 객체를 접근하려 한다면 서버사이드 렌더링 시점에서 에러가 발생하게 됩니다.


위 경우 외에도 dynamic import는 아래와 같은 상황에 사용할 수 있습니다.

  1. 초기 로딩에 필요하지 않는 코드를 동적 로드(code splitting)함으로써 속도 개선
  2. 기능 별 코드 분할이 필요한 경우

단점

  1. dynamic import 사용 시 코드가 별도의 파일로 분리되어 추가 적인 HTTP 요청이 발생합니다.

Read more

ISACA 2024 학술대회 발표자료

ISACA 2024 학술대회 발표자료

ISACA_2024_공동_학술대회_발표자료ISACA_2024_공동_학술대회_발표자료.pdf125 MBdownload-circle[2024. 11. 20.] 연세대, 2024 바른ICT연구소 리서치 콘퍼런스 성료 | 연세대학교연세대학교 * 키워드 * 데이터 * 신뢰 * 윤리 * 보안 * 2024 노벨상 * 물리학상, 제프리 힌튼 (인공지능, 컴퓨터 과학자) * 화학상, 데미스 허사비스 (구글 딥마인드) * 라인 경영권 이슈 * 데이터 주권 확보에 대한 노력 (경영권 분쟁이 아님.

By Hyonsok
3회 Digital ESG Conference 세미나 자료, 누빅스, 2024/10/24

3회 Digital ESG Conference 세미나 자료, 누빅스, 2024/10/24

DEA 컨퍼런스 행사 프로그램 순서DEA 컨퍼런스 행사 프로그램 순서.pdf503 KBdownload-circle[공유용] DEA 컨퍼런스 오프닝 및 DEA 업데이트_강명구[공유용] DEA 컨퍼런스 오프닝 및 DEA 업데이트_강명구.pdf3 MBdownload-circle[공유용] 콜린스_케이에너지세이브 발표자료[공유용] 콜린스_케이에너지세이브 발표자료.pdf3 MBdownload-circle[공유용]Digital ESG Alliance Conference_김정연[공유용]Digital ESG Alliance Conference_

By Hyonsok

Datadog Live Seoul 2024 (발표자료)

3개월 차 DevOps팀의 Datadog 활용 - 이병호 박상욱 김경보 김태수, 뉴넥스 & 이성욱, Datadog3개월 차 DevOps팀의 Datadog 활용 - 이병호 박상욱 김경보 김태수, 뉴넥스 & 이성욱, Datadog.pdf2 MBdownload-circle12년차 스타트업의 아키텍처 리팩토링 돌아보기 - 이정민, 드라마앤컴퍼니12년차 스타트업의 아키텍처 리팩토링 돌아보기 - 이정민, 드라마앤컴퍼니.pdf3 MBdownload-circleAsset-HighlightsDatadogLiveSeoul2024Asset-HighlightsDatadogLiveSeoul2024.pdf3 MBdownload-cir

By Hyonsok