Next.js 는 모든 페이지를 기본적으로 Pre-Render 한다.
다시 말해, Client Side 의 JavaScript 가 모든 일을 하는 것이 아니라,
각 HTML 파일을 사전에 만들어 놓는다는 의미이다.
이렇게 Pre-Rendering 된 페이지들은 퍼포먼스 향상와 검색엔진최적화( SEO )에 더 좋다.
생성된 HTML 은 필요한 최소한의 JavaScript 코드만 존재하고,
브라우저에 의해 로드될 때 그 코드가 실행되어 완전한 페이지를 표한하게 되는 것이다.
Pre-Rendering 을 하지 않았을 때 JavaScript 를 껐을 때, 화면에 아무것도 나타나지 않을 것이다.
🔗 Chrome 개발자 도구 / JavaScript 끄기
아래의 결과 화면을 확인해보자.
JavaScript 가 꺼진 상태이기 때문에 CSS 가 적용되지 않고 API 호출이 막힌 상태이지만,
페이지 소스를 확인하면 head 태그 안에 설정한 title 과 meta 태그 정보가 설정한대로 잘 나타난다.
사용자가 빠르게 이 페이지로 들어올 수 있고, SEO 도 문제없이 잘 처리된다.
About 페이지도 CSS 가 적용되지 않을 뿐,
페이지 소스를 확인하면 head 태그 안에 설정한 title 이 올바르게 나타난다.
View 는 Server-Side Rendering 으로 구현되었다.
즉, 서버에서 데이터를 가져와서 HTML 로 만든 다음 내려준다는 의미이다.
그렇기 때문에 제품에 대한 이미지와 정보가 화면에 나타난다.
이 페이지에서 JavaScript 가 하는 역할은 CSS 를 가져오고 onClick 함수 등 최소한으로 구현되어 있다.
하지만 JavaScript 는 꺼진 상태이기 때문에 앞서 언급한 기능들만 작동하지 않는다.
💡 이 페이지에서 Next.js 의 장점을 확인할 수 있다...!!
SPA 환경에서 이렇게 SSR 으로 구현하면 Multi Page Application 못지않게
검색 엔진 최적화( SEO )에 대응하고, 퍼포먼스도 향상시킬 수 있다.
Pre-Rendering 을 하지 않으면
초기에는 아무것도 나타나지 않고, JS 가 로드된 이후에 페이지가 채워진다.
Pre-Rendering 를 하면
초기에 사전에 만들어진 HTML 요소들( meta 데이터 포함 )이 화면에 그려진다.
그 다음 JS 가 로드되면 <Link />
같은 컴포넌트들이 작동하게 된다.
이를 Hydration ( 정적인 무언가에 동적인 요소들을 입혀 생기를 불어 넣는 작업 ) 이라고 부른다.
다시 말해, 정적인 HTML 에 JS 를 입혀 동적으로 만들어 내는 것을 의미한다.
사전 렌더링 ( Pre-Rendering ) 은 2가지 방식으로 적용된다.
이 두 방법의 차이점은 "언제 HTML을 만드는가?"이다.
Static Generation 은 빌드 시에 HTML 을 생성한다.
미리 만들어 놓은 HTML 을 Client 에서 요청할 때마다 재사용해서 주는 것이다.
그렇다면 정적 생성( Static Generation ) 방식은 언제 사용하면 좋을까?
페이지를 빌드 시점에 만들어두고, CDN 을 통해 재사용하기 때문에 대부분의 경우 정적 생성 방식이 훨씬 빠르고 좋다.
⭐ 정적 생성( Static Generation ) 방식은
사용자가 요청하기 전에 페이지를 미리 만들어 놓아도 되는 경우 사용한다.
Next.js 에서는 다음과 같은 경우에 정적 생성 방식을 권장하고 있다.
- 마케팅 페이지
- 블로그 게시물
- 제품 목록
- 도움말, 문서
Client 에서 요청하면 그때 HTML 을 만들어서 보여준다.
⭐ SSR( Server-Side Rendering ) 방식은 다음과 같은 경우에 사용한다.
- 항상 최신 상태를 유지
- 관리자 페이지
- 분석 차트
Next.js 는 페이지별로 정적 생성 vs SSR 렌더링 방식을 개발자가 선택해서 구현할 수 있다.
SSR ( Server-Side Rendering ) 방식은 제품 상세 페이지를 구현할 때 적용했던 방식이다.
다시 한번 살펴보자.
📁 / pages / view / [id].js
📁 / pages / about.js
about 페이지의 경우에는 어떤 데이터도 필요없는 페이지로, 정적 생성 방식으로 구현되었다.
Next.js 에서 제품 목록 페이지는 정적 생성 방식을 권고하였으므로
외부 데이터를 받아오는 제품 목록 페이지에 정적 생성 방식을 적용시켜보자.
📁 / pages / index.js
Axios 로 데이터를 불러오는 getStaticProps 영역은 Client 영역이 아니기 때문에
환경 변수에 NEXT_PUBLIC_
을 붙일 필요가 없다.
따라서 환경 변수 파일에 apiUrl
변수를 추가로 생성한다.
📁 / .env.development
📁 / .env.production
npm run dev
명령으로 development mode 에서 결과를 확인해보자.
빈 화면을 그린 다음 API 호출을 통해서 데이터를 받아온 후 빈 화면을 채우는 것이 아니라,
미리 만들어진 Static HTML 을 제공한 것이다.
home 페이지로 이동하면 빈 화면 없이 제품 목록이 나타난다.
페이지 소스를 보면 모든 데이터가 잘 채워져 있는 것을 확인할 수 있다.
.next
폴더를 삭제한 후, npm run build
한다.
그 결과 .next
폴더가 다시 생기고 그 안에 필요한 파일들이 들어가게 된다.
📁 / .next / pages 안의 파일들을 살펴보면
Server 에서 사용되는 static 한 파일들이 만들어져 있는데 HTML 로 만들어져 있는 것을 확인할 수 있다.
이렇게 만들어진 HTML 파일을 재사용하는 것이다.
그 다음 ``npm run start``` 명령으로 production mode 에서 결과를 확인해보자.
개발자 도구의 Network 탭을 살펴보자.
용량은 22.8KB 로 처음 로드하는데 약 1s 정도 걸렸다.
다시 새로고침 하면 이미 만들어진 HTML 을 보여주는 방식이기 때문에 약 3ms 만에 로드되는 것을 확인할 수 있다.
Dynamic Router 는 정적 생성이 불가능한 것일까?
이 예시의 경우,
Dynamic Router 는 어떤 아이디가 들어올지 모르기 때문에 모든 제품에 대한 HTML을 생성하는 것은 불가능하다.
단, 개수가 한정적이고 들어올 아이디 번호를 미리 알 수 있으면 가능하다.
이 경우에 getStaticPaths
를 사용한다.
모든 제품에 대해 대응할 수 없으니, 가장 상단에 있는 3개의 제품에 대해서만 대응해보자.
( 740번 , 730 번 , 729 번 )
view 폴더를 복사하고, 복사한 폴더명을 detail 로 수정한다.
이 detail 폴더에 getStaticPaths
를 활용하여
740
번, 730
번, 729
번 제품의 Dynamic Router 에 정적 생성 방식을 적용해보자.
📁 / .src / component / ItemList.js
제품을 클릭했을 때 view 폴더가 아니라 detail 폴더로 이동해야 하므로 주소를 알맞게 수정한다.
📁 / pages / detail / [id].js
.next
폴더를 삭제한 후, npm run build
한다.
그 결과 .next
폴더가 다시 생기고 그 안에 필요한 파일들이 들어가게 된다.
그 다음 npm run start
명령으로 production mode 에서 결과를 확인해보자.
그 결과 home 과 제품 목록의 가장 상단에 있는 3개의 제품( 740번 , 730 번 , 729 번 )에 대한 상세페이지는
빠르게 로드 되는 것을 확인할 수 있다.
▶ HOME ( 제품 목록 )
▶ 제품 상세페이지 ( 740번 , 730 번 , 729 번 )
▶ 제품 상세페이지 ( 그 외 )
740번 , 730 번 , 729 번을 제외한 다른 제품들을 클릭하면 404 페이지가 뜬다.
이 현상은 fallback
을 false 로 설정했기 때문에 나타난다.
이제 fallback
을 ture 로 설정하고 그 결과를 확인하자.
처음에는 첫 번째 이미지처럼 제품 정보가 없는 상태의 페이지를 보였다가,
시간이 조금 지나고 두 번째 이미지처럼 제품 정보가 채워진 화면이 나타난다.
⭐ fallback
false
: 없는 페에지 대응을 하지 않는다. 그냥 404 에러가 나타나게 된다.ture
: getStaticPaths 로 전달된 경로들이 빌드 타임에 만들어지는 것은 변함없다.
다만, 나머지들은 최초 접속 시에 Props 가 빈 상태로 그려지고
이후에 background에서 정적 파일로 HTML 과 JS를 생성해준다.
그 다음에 Next.js 는 Pre-Rendering 목록에 추가한다.
두 번째 로드부터는 정적 생성된 페이지를 사용하기 때문에 새로고침 해도
데이터가 비어있는 상태의 페이지는 보이지 않게 된다.