data fetching & pre-rendering | React vs. Next
React.js에서 데이터를 받아오는 방식과 문제점은 다음과 같다.
- useEffect 내부에서 필요한 데이터를 backend api에게 요청한다.
- 성공적으로 받아온 데이터를 state로 업데이트한다.
- 데이터를 화면에 보여준다.
- 결론 | 사용자는 html 코드와 js 코드를 한 번에 받아오고, js 코드가 실행되면 동적으로 html을 구성한다.
- 문제점
- js가 실행되어야 데이터를 받아올 수 있다는 것은, 온전한 페이지를 보여줄 때 까지 시간 지연이 발생한다는 것을 의미한다.
- 뿐만 아니라 최초의 html 코드(page source에서 확인할 수 있는 html 코드)에는 동적으로 생성되는 데이터가 포함되어 있지 않기 때문에, SEO에 나쁜 영향을 끼칠 수 있다.
- +) 리액트에서는 fetched data 뿐만 아니라 모든 html 코드가 페이지 소스에 포함되어 있지 않다. 넥스트는 기본적으로 정적으로 구성되는 모든 html 코드를 페이지 소스에 포함한다.
Next.js는 pre-rendering을 이용해 위와 같은 문제를 해결한다.
- 기본적으로, initial load에서 dynamic data가 없는 모든 페이지를 pre rendering 한다. 그 이후에는 이전과 같은 방식으로 client side에서 어플리케이션의 컨텐츠를 동적으로 제어한다.
- +) dynamic parameter를 갖는 페이지는 pre rendering 대상이 아니다.
- html을 pre rendering 하는 데 필요한 최소한의 js 코드 만이 initial load에 포함된다(동적으로 data를 받아오는 코드는 처음에 포함되지 않는다).
- 브라우저에 의해 페이지가 load 될 때 그 페이지에 포함된 모든 js 코드를 재전송하는데, 이를 hydration이라고 하고 ,이 때부터 페이지는 다시 client side에서 제어된다.
- 부가적인 코드를 작성하면, data fetching을 필요로 하는 page도 pre rendering 할 수 있다.
- next.js가 미리 렌더링된 페이지(pre-rendered page)를 반환하면 크롤러가 이 페이지의 정보를 수집하기 때문에, SEO에 좋다.
- 결론 | 사전에 html 페이지를 완전히 구성하고, 이를 사용자에게 제공한다.
- static generation, server side rendering 두 가지 방법을 이용해 pre rendering을 구현할 수 있다.
static site generation
1) getStaticProps
- next.js에게 해당 페이지를 pre-rendering 할 것을 명령하는 메서드라고 할 수 있다.
- 어플리케이션을 build 할 때 pre rendering할 페이지(pre-generate page, html)를 만든다.
- build 명령어를 실행한 뒤, .next/server/pages 에서 생성된 페이지(html)를 확인할 수 있다.
- start 명령어를 실행하면, 개발용이 아닌 production ready page를 확인할 수 있다.
- 어플리케이션을 deploy 하면 서버에서 1에서 만든 페이지를 CDN의 형태로 cache 한다.
- request가 발생할 때 마다 1에서 만들어진 페이지를 재사용 할 수 있다.
- next.js는 pre rendering 페이지를 만들 때, 성능의 측면에서 static generation을 이용할 것을 추천한다.
- 자주 변하지 않는, 정적인 데이터를 이용해 페이지를 구축할 때 적절하다.
- incremental static regeneration with revalidate option
- revalidate 옵션을 사용하면, ISR을 이용할 수 있다.
- build 할 때 생성된 pre-generate page를 server에서 일정 시간 간격으로 업데이트할 수 있다.
- page에 필요한 데이터가 변화하는 빈도에 따라 그 시간 간격을 정할 수 있다.
- 마지막으로 페이지가 생성된 시간 ~ 현재 request가 발생한 시간 사이의 간격을 확인한다. => 기존에 생성된 page를 반환할지, 새로운 페이지를 생성하고 이를 반환할지 결정한다.
- npm start 명령어를 이용해 local에서 production ready page를 확인해 보면, dev 모드에서와 달리, request가 발생하더라도 정해둔 시간이 지나지 않으면 page가 재생성되지 않는 것을 알 수 있다.
- other options
export async function getStaticProps() {
// get data from data directory
return {
props: {
products: data.products,
},
revalidate: 60,
};
}
- context parameter
export async function getStaticProps(context) {}
- context는 다음의 key를 갖는 객체이다.
- params | 현재 url에서 dynamic params의 구체적인 값을 알려 준다. => ex) { productId: 'p1' }
2) getStaticPaths
- dynamic url에 대한 pre-rendering을 구현하려면 getStaticPaths를 사용한다.
- paths | 구체적으로 어떤 경로의 페이지(concrete instances)를 미리 생성해 둘 것인지 지정한다.
- fallback | paths에서 지정하지 않은 segment 경로에 접근했을 때 어떻게 동작할지 지정한다.
- false | 404 페이지를 반환한다.
- true | server에서 html이 생성되기 전까지 fallback page(loading...)를 렌더링하다가, 생성이 완료되면 그 full page를 반환한다. 한번 접근한 페이지는 pre-renderd page list에 추가되어 재사용된다.
- 'blocking' | server에서 html이 생성될 때 까지 기다렸다가 full page를 반환한다. 마찬가지로, 한번 접근한 페이지는 pre-renderd page list에 추가되어 재사용된다(identical to ssr).
- +) true, blocking 옵션은 request가 발생하면, 서버 측에서 그때 그때 html 페이지를 생성한다.
- +) true일 때, anchor 태그를 이용해 지정하지 않은 경로에 접근한 경우에는, fallback => full page가 아니라, server side에서 생성되는 페이지를 기다렸다가 full page를 바로 반환한다. 즉 'blocking' 옵션과 같은 방식으로 동작한다.
- +) true 일 때, 현재 페이지가 fallback 상태인지 아닌지 확인하려면?
server side rendering
- static site generation은 어플리케이션을 build 할 때 미리 페이지를 생성한다.
- 예외적으로 ISR은 지정해 둔 revalidate 시간에 따라 ssr을 이용한다.
- server side rendering은 요청이 발생할 때 마다, 서버 측에서 해당 페이지를 생성한다. 즉, 유입되는 모든 요청에 대해 새로운 페이지가 pre rendering 된다.
- 어떤 페이지를 구성하고 있는 data가 자주 변경된다면, 요청이 발생할 때 마다 서버 측에서 해당 page를 rendering 하는 것이 더 낫다.
getServerSideProps
- next.js는 페이지에 request가 발생할 때 마다 getServerSideProps을 실행한다.
- getStatic~과 달리 context parameter에서 req, res 객체에 접근할 수 있다.
- request에 함께 attach 되어있는 header, cookie 등에 접근할 수 있고, 요청을 보낸 사람이 누구인지 특정할 수 있다.
- +) getStaticProps와 같은 페이지에서 사용할 수 없다(사전에 렌더링할 페이지를 무엇으로 할 것인지 충돌이 일어남).
client side data fetching
- 미리 페이지에 필요한 데이터를 받아 놓는 것이 아니라, 사용자가 페이지에 방문 했을 때 data를 받아오는 것이 더 나은 경우도 여전히 존재한다. => 실시간으로 변화하는 최신 데이터(ex. 주식) 등
example code here
- 기존의 data fetching 방식의 문제점
- pre-rendering
- static site generation(SSG)
- getStaticProps
- static page 구축하기
- incremental static regeneration 설정하기 => revalidate
- data fetching 실패 시 유용하게 사용할 수 있는 return 객체의 key 살펴보기 => notFound, redirect
- next.js가 (기본 값으로) 동적 경로를 포함하는 페이지를 pre-rendering하지 않는 이유
- getStaticPaths
- 동적 경로를 포함하는 페이지 pre-rendering 하기
- return 객체의 key 살펴보기 => paths, fallback
- getStaticProps
- server side rendering(SSR)
- getServerSideProps
- getStaticProps와 차이점
- 동적 경로와 SSR
- getServerSideProps
'Study > Next' 카테고리의 다른 글
optimization with <head> & <image> (1) | 2022.10.18 |
---|---|
client side data fetching (0) | 2022.10.17 |
how useRouter works (0) | 2022.10.09 |
what is _app.js? (0) | 2022.10.09 |
file based routing (1) | 2022.10.04 |