필자는 프로젝트를 진행하면서 page 컴포넌트를 default export
방식으로 컴포넌트를 내보내어 코드를 작성하였다.
// Component default export
function MyPage () => { ... }
export default MyPage; // Component import
import MyPage from './pages/MyPage';
페이지 컴포넌트에 default export
로 굳어진 습관도 무시할 수 없지만, 페이지는 단 한개의 페이지 컴포넌트 뷰의 기능을 담당해야 하기 때문에 default로 작성하였다.
그러나 default export
의 단점으로 import 하는 과정에서 휴먼 에러가 발생할 수 있다는 단점과 import 코드 라인이 늘어나는 단점이 존재하기 때문에 이번에는 named export
를 통해 컴포넌트를 export 하였다.
// Component named export
export const MyPage= () => { ... } // Component import
import { MyPage } from './pages';
named export
로 변경 후 import 하는 과정에서 자동으로 컴포넌트 name을 선언해 주며, 여러 export된 컴포넌트 및 함수를 name으로 import 할 수 있는 장점이 생겼다.
React.lazy로 import
각 페이지 컴포넌트를 최적화 하기 위해 React.lazy 를 사용하여 동적으로 컴포넌트를 import 하였다.
React v16.6.0의 외부 라이브러리 없이 코드 분할을 할 수 있는 React.lazy를 도입하였다.
react.dev-lazy
즉, React.lazy 함수는 동적 import를 일반 컴포넌트처럼 렌더링할 수 있게 해준다.
Before:
import { MyPage } from './pages'; function AppComponent() { return ( <div> <MyPage /> </div> )
}
After:
const MyPage = React.lazy(() => import('./pages/MyPage')); function AppComponent() { return ( <div> <MyPage /> </div> )
}
그리고 바로 다음에서 문제가 발생, 아래에 다음과 같은 메시지가 있다.
React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component.
번역하면 이렇다.
React.lazy는 동적 import()를 호출하는 함수를 받습니다. 이 함수는 React 컴포넌트를 포함하는
default export
모듈로 해석되는 Promise를 반환해야 합니다.
그래서 아래와 같이 변경하라고 한다.
function MyPage () => { ... }
export default MyPage;
해결방법
하지만 default export
로 export 하지 않는다면 어떻게 해야 할까 고민 중에 ChatGPT를 통해 그 답을 얻을 수 있었으며 이 경우, 컴포넌트를 가져올 때 import() 코드를 약간 변경해야 한다.
const MyPage = React.lazy( () => import('./pages/MyPage/index.tsx').then((module) => ({ default: module.MyPage }))
);
필자는 MyPage라는 폴더를 두고 그 안에 index.tsx 파일로 컴포넌트를 생성해 주었다. 그리고 중요한 점은 확장자 명을 반드시 붙여 주어야 한다.
정리하자면 import()가 반환하는 Promise에 체이닝을 추가하여 default export
를 추가하는 작업을 하고 있는 것이다.
이렇게 React.lazy로 가져온 named export
된 컴포넌트의 경우 위와 같은 형식으로 lazy 함수를 작성해 주어야 한다.
그리고 기억해야 할 것으로 React.lazy로 가져온 컴포넌트는 반드시 React.Suspense 안에서 렌더링 되어야 한다는 점을 기억해야 한다.
최종적으로 변경된 전체 코드는 아래와 같다.
const MyPage = React.lazy( () => import('./pages/MyPage/index.tsx').then((module) => ({ default: module.MyPage })) function AppComponent() { return ( <div> <Suspense fallback="loading..." /> <MyPage /> <Suspense/> </div> )
}
Discover more from Coursity
Subscribe to get the latest posts sent to your email.