티스토리 뷰
[Next.js] Dynamic Import(Lazy load) & Hydration & Static Export
doeunnkimm 2023. 6. 27. 12:29
Dynamic Import
Dynamic Import는 컴포넌트를 사용하는 시점에 로드하는 것인데요. Next.js에서는 이미지나 Link 컴포넌트 두 가지 모두 Viewport 안에 들어왔을 떄 로드하는 것들이 있었습니다. 그런 것들을 Lazy Load라고 합니다.
컴포넌트 마저도 상단에서 모두 한번에 import해서 사용하는 것이 아니라 필요한 타이밍에 로드해서 사용할 수 있는 방법을 제공합니다. Next.js에서는 그것을 Dynamic이라는 개념으로 사용됩니다.
Dynamic Import를 사용하면 모듈을 빌드 타임이 아닌 런타임에 불러오도록 합니다. 이를 통해 번들 파일을 분리하고 초기 렌더링 시간 단축이란느 퍼포먼스 향상을 기대할 수 있습니다.
애플리케이션에는 초기 로딩부터 사용하지 않는 부분이 존재할 수 있으며, 또 그 부분의 사이즈가 생각보다 클 수 있기 때문입니다.
next/dynamic을 이용해서
`next/dynamic`을 사용하면 페이지의 초기 번들에 포함되지 않습니다. 페이지는 Suspense를 통해 fallback을 먼저 렌더링한 다음 로드가 되면 그때 구성 요소를 렌더링합니다.
import dynamic from 'next/dynamic'
const Button = dynamic(() => import('../../components/Button'), {
loading: () => <div>Loading...</div>,
})
Dynamic Import를 사용하면 따로 빌드가 되게 됩니다. 반면 Dynamic Import를 사용하지 않으면 따로 쪼개지 않고 chunk에 같이 묶이게 됩니다.
Automatic Static Optimization
Next.js가 정적 페이지는 .html으로 요청에 맞춰 동작하는 페이지는 .js로 빌드하는 것을 말합니다.
Next.js는 자동적으로 정적인 것은 최적화해서 정적인 파일로, 동적인 것은 동적인 파일로 만들어줍니다.
작동 원리
`getServerSideProps`또는 `getInitialProps`가 페이지에 있는 경우 Next.js는 요청에 따라 페이지를 렌더링하도록 전환합니다. 위 경우가 아니라면 페이지를 HTML로 미리 렌더링하여 자동으로 페이지를 정적으로 최적화합니다.
router의 query
dynamic하다 static하다라는 것을 보았을 때, router의 query의 경우 client-side의 경우 hydration 이후 query 값을 읽어올 수 있습니다.
Next.js의 hydrate
Server Side 단에서 렌더링된 정적인 페이지와 번들링된 JS 파일을 클라이언트에게 보낸 뒤, 클라이언트 단에서 HTML 코드와 JS코드를 서로 매칭시키는 과정이다. React는 JS만을 사용해 화면을 painting한다. Next.js는 Server Side에서 미리 웹페이지를 Pre-rendering하여 generate된 HTML document를 클라이언트에게 전송한다.
Next.js를 통해 클라이언트가 받은 정적 웹페이지는 JS가 없기 때문에 interactive하지 않다. 개발자 도구의 네트워크 탭을 보면, document Type의 파일을 다운로드 받은 뒤 JS파일들이 다운로드되는 것을 확인할 수 있다.
그리고 이 JS코드들이 이전에 보내진 HTML DOM 요소 위에서 한번 더 렌더링을 하면서 각자 자기 자리를 찾아가며 매칭이 된다.
간단하게 확인해봅시다. 정적인 파일에서 Client Side 부분에 다음과 같은 코드를 추가해봅시다.
const router = useRouter()
useEffect(() => {
console.log(router.query)
}, [router.query])
`build`하고 실행해서 살펴보면 새로고침 했을 때, 분명 query가 있음에도 처음에 빈 객체가 먼저 뜹니다. 이는 dydration 즉, 사용자와 interaction할 준비가 될 때까지는 query가 없다고 판단하여 빈 객체가 콘솔에 찍힌 것이고, 그 이후에 query가 보여진 것입니다.
client side에서 코드를 작성하고 있다면 query의 존재가 이후에 주입될 수 있다는 점을 염두하고 있는 것이 좋습니다.
Next.js이 Hydration함으로써 얻게되는 이점
React와 다르게 Pre-rendering된 Document는 자바스크립트 요소가 빠진 가벼운 상태이기 때문에 클라이언트 측에서 빠르게 로딩이 가능한 장점이 있습니다. 또한, 이후에 Chunk 단위로 다운로드된 자바스크립트 요소들이 렌더링될 때는 먼저 받아진 document의 DOM 요소에 자바스크립트 속성이 매칭되는 것이기 때문에 웹 페이지를 다시 그리는 과정이 일어나지 않게 됩니다.
좀더 쉽게 이해해보자면, React는 CSR(Client-side Rendering)로, 처음에 브라우저에 빈 HTML을 파일을 받아 아무것도 보여주지 않다가, 사용자 기기에서 렌더링이 진행되어 한 번에 화면을 보여줍니다.
반면, Next.js는 모든 페이지를 미리 렌더링(pre-render)합니다. 이는 Next.js가 모든 일을 클라이언트 측에서 모든 작업을 수행하는 것이 아니라, 각 페이지의 HTML을 미리 생성하는 것입니다. 생성된 HTML은 해당 페이지에 필요한 최소한의 JS코드와 연결됩니다. 그 후 브라우저에 의해 페이지가 로드되면, JS코드가 실행되어 페이지와 유저가 상호작용(interaction)할 수 있게 됩니다.
→ 이러한 과정을 hydration이라 합니다.
Static Export
Next.js 프로젝트를 정적인 파일들만으로 build하는 것을 말합니다. CDN 등에 정적인 파일들만을 올려서 서비스를 제공하는 것도 가능합니다.
즉, Node.js 서버가 있어야만 동작하는 기능들을 포기해야 한다는 말과 같습니다. 공식 문서에서는 다음과 같이 Static Export를 사용했을 때 지원받지 못하는 것들을 나열하고 있습니다.
공식 문서에 사용하는 방법도 자세히 설명되어 있으니 같이 참고하면 좋을 것 같습니다 bb
실행해보면, 위에 지원하지 않는 기능이 포함된 경우 export할 떄 에러가 발생합니다. 그래서 적절히 변경해주고 다시 export를 해보면 .next에 `out`이라는 폴더가 생기는데, 그 안에는 모두 html로 이루어진 파일들이 존재하며, next의 기본 동작을 위한 파일들만 js로 구성되어 있는 것을 확인할 수 있습니다.
이번 글에서는 Dynamic Import와 Hydration 그리고 Static Export에 대해 알아보았습니다.
1. Dynamic Import
Lazy load로 초기 청크 사이즈 줄이기
2. Suspense
Promise resolved 되어야 렌더
3. Automatic Static Optimize
알아서 정적 파일과 동적 파일 구분
4. Static HTML Export
의도적으로 정적 파일로 export 가능
'프론트엔드 > Next.js' 카테고리의 다른 글
[Next.js] Custom App - 생산성을 높이는 _app.js에서 할 수 있는 일들 (0) | 2023.06.27 |
---|---|
[Next.js] ../ 때문에 길어지는 import문은 별칭 절대경로 @ 사용하기 (0) | 2023.06.27 |
[Next.js] /post/write 페이지에서 새로운 글을 쓸 수 있도록 해보세요 (0) | 2023.06.26 |
[Next.js] SSG를 활용해서 다이나믹한 page 생성 with getStaticPaths, fallback 에러 해결 (0) | 2023.06.25 |
[Next.js] SSG 선택 기준과 SSG를 하는 두 가지 방법(with data, without data) (0) | 2023.06.23 |
- Total
- Today
- Yesterday
- 프론트엔드 공부
- next.js
- 인프런
- styled-components
- CSS
- 머신러닝
- JSP
- 자바스크립트 기초
- HTML
- rtl
- 자바스크립트
- frontend
- 딥러닝
- 프론트엔드 기초
- 자바
- TypeScript
- testing
- 데이터분석
- 스타일 컴포넌트 styled-components
- 파이썬
- 디프만
- 프론트엔드
- react-query
- 프로젝트 회고
- 타입스크립트
- Python
- 리액트
- jest
- 리액트 훅
- react
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |