코드 분할 및 스마트 로드 전략으로 Next.js 앱의 속도를 높이는 방법
학습 내용
이 게시물에서는 다양한 유형의 코드 분할과 동적 가져오기를 사용하여 Next.js 앱의 속도를 높이는 방법을 설명합니다.
경로 기반 및 구성요소 기반 코드 분할
기본적으로 Next.js는 JavaScript를 각 경로별로 별도의 청크로 분할합니다. 사용자가 애플리케이션을 로드하면 Next.js는 초기 경로에 필요한 코드만 전송합니다. 사용자는 애플리케이션을 탐색할 때 다른 경로와 연결된 청크를 가져옵니다. 경로 기반 코드 분할은 한 번에 파싱하고 컴파일해야 하는 스크립트의 양을 최소화하므로 페이지 로드 시간이 단축됩니다.
경로 기반 코드 분할은 좋은 기본값이지만 구성요소 수준에서 코드 분할을 사용하여 로드 프로세스를 추가로 최적화할 수 있습니다. 앱에 큰 구성요소가 있는 경우 이를 별도의 청크로 분할하는 것이 좋습니다. 이렇게 하면 중요하지 않거나 특정 사용자 상호작용(예: 버튼 클릭)에서만 렌더링되는 대규모 구성요소를 지연 로드할 수 있습니다.
Next.js는 JavaScript 모듈(React 구성요소 포함)을 동적으로 가져오고 각 가져오기를 별도의 청크로 로드할 수 있는 동적 import()
를 지원합니다. 이를 통해 구성요소 수준의 코드 분할을 실행하고 리소스 로드를 제어하여 사용자가 보고 있는 사이트 부분에 필요한 코드만 다운로드하도록 할 수 있습니다. Next.js에서 이러한 구성요소는 기본적으로 서버 측 렌더링(SSR)됩니다.
동적 가져오기의 실제 작동 방식
이 게시물에는 버튼이 하나 있는 간단한 페이지로 구성된 샘플 앱의 여러 버전이 포함되어 있습니다. 버튼을 클릭하면 귀여운 강아지가 표시됩니다. 앱의 각 버전을 살펴보면 동적 가져오기가 정적 가져오기와 어떻게 다른지, 그리고 이를 사용하는 방법을 확인할 수 있습니다.
앱의 첫 번째 버전에서는 강아지가 components/Puppy.js
에 살고 있습니다. 페이지에 강아지를 표시하기 위해 앱은 정적 가져오기 문으로 index.js
의 Puppy
구성요소를 가져옵니다.
import Puppy from "../components/Puppy";
Next.js가 앱을 번들로 묶는 방법을 보려면 DevTools에서 네트워크 트레이스를 검사하세요.
사이트를 미리 보려면 앱 보기를 누른 다음 전체 화면을 누릅니다.
`Control+Shift+J`(Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
네트워크 탭을 클릭합니다.
캐시 사용 중지 체크박스를 선택합니다.
페이지를 새로고침합니다.
페이지를 로드하면 Puppy.js
구성요소를 비롯한 필요한 모든 코드가 index.js
에 번들로 묶입니다.
Click me 버튼을 누르면 강아지 JPEG 요청만 네트워크 탭에 추가됩니다.
이 접근 방식의 단점은 사용자가 강아지를 보려고 버튼을 클릭하지 않더라도 index.js
에 포함되어 있으므로 Puppy
구성요소를 로드해야 한다는 점입니다. 이 작은 예에서는 큰 문제가 아니지만 실제 애플리케이션에서는 필요한 경우에만 큰 구성요소를 로드하는 것이 큰 개선사항이 되는 경우가 많습니다.
이제 정적 가져오기가 동적 가져오기로 대체된 앱의 두 번째 버전을 살펴보겠습니다. Next.js에는 Next의 모든 구성요소에 동적 가져오기를 사용할 수 있는 next/dynamic
가 포함되어 있습니다.
import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";
// ...
const Puppy = dynamic(import("../components/Puppy"));
첫 번째 예의 단계에 따라 네트워크 트레이스를 검사합니다.
앱을 처음 로드하면 index.js
만 다운로드됩니다. 이번에는 Puppy
구성요소에 관한 코드가 없으므로 0.5KB로 더 작아집니다 (37.9KB에서 37.4KB로 감소).
이제 Puppy
구성요소는 버튼을 누를 때만 로드되는 별도의 청크 1.js
에 있습니다.
실제 애플리케이션에서는 구성요소가 훨씬 더 큰 경우가 많으며 지연 로드로 인해 초기 JavaScript 페이로드가 수백 KB 정도 줄어들 수 있습니다.
맞춤 로드 표시기가 있는 동적 가져오기
리소스를 지연 로드할 때는 지연이 발생할 경우 로드 표시기를 제공하는 것이 좋습니다. Next.js에서는 dynamic()
함수에 추가 인수를 제공하여 이를 실행할 수 있습니다.
const Puppy = dynamic(() => import("../components/Puppy"), {
loading: () => <p>Loading...</p>
});
로드 표시기의 작동 모습을 보려면 DevTools에서 느린 네트워크 연결을 시뮬레이션합니다.
사이트를 미리 보려면 앱 보기를 누른 다음 전체 화면을 누릅니다.
`Control+Shift+J`(Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
네트워크 탭을 클릭합니다.
캐시 사용 중지 체크박스를 선택합니다.
제한 드롭다운 목록에서 빠른 3G를 선택합니다.
Click me 버튼을 누릅니다.
이제 버튼을 클릭하면 구성요소를 로드하는 데 잠시 시간이 걸리고 그동안 앱에 'Loading…'(로드 중) 메시지가 표시됩니다.
SSR이 없는 동적 가져오기
클라이언트 측에서만 구성요소를 렌더링해야 하는 경우 (예: 채팅 위젯) ssr
옵션을 false
로 설정하면 됩니다.
const Puppy = dynamic(() => import("../components/Puppy"), {
ssr: false,
});
결론
동적 가져오기를 지원하는 Next.js를 사용하면 구성요소 수준의 코드 분할을 통해 JavaScript 페이로드를 최소화하고 애플리케이션 로드 시간을 개선할 수 있습니다. 모든 구성요소는 기본적으로 서버 측에서 렌더링되며 필요한 경우 언제든지 이 옵션을 사용 중지할 수 있습니다.