Next.js는 SSR이 가능한 특징을 가진 React 프레임워크이다.
Next의 ServerSide Cycle
- Server가 GET 요청을 받는다.
- 요청에 맞는 Page를 찾는다.
- _app.js에 getInitialProps가 있다면 실행한다.
- 하위 Component의 getInitialProps가 있다면 실행하고 pageProps를 받아온다.
- 모든 props를 구성하고, _app.js => Component 순서로 렌더링을 한다.
- Content를 구성하면 _document.js를 실행해 html 형태로 출력한다.
여기서, 모든 페이지에서 공통적인 데이터 패칭이 필요하면, _app.js에서 데이터 패칭을 하고,
페이지마다 다른 데이터가 필요하면 각 페이지에서 데이터 패칭을 해주면 된다.
Next.js 9.3 이전 버전에는 getInitialProps만 사용했지만,
이후 버전부터는 getStaticProps, getStaticPath, getServerSideProps로 나누어졌다.
모두 pre-render가 필요한 경우에만 사용하는 것이 좋다.
_app.js에서 전역 데이터 패칭이 필요한 경우 getStaticProps나 getServerSideProps는 지원하지 않기 때문에
getInitialProps를 사용해야 한다.
getInitialProps
Next.js는 getInitialProps가 없으면, 페이지를 정적 HTML로 사전 렌더링을 해서 정적 최적화를 합니다.
하지만 getInitialProps를 사용하게 되면, 최적화 과정이 일어나지 않습니다.
그래서 전역적으로 SSR 데이터 패칭이 필요한 경우에만 사용하는 것을 추천한다.
function MyApp({ Component, pageProps }) {
return (
<>
// ...
</>
);
}
MyApp.getInitialProps = async (context) => {
const { ctx, Component } = context;
let pageProps = {title : 123123};
return { pageProps };
};
return을 통해 해당 컴포넌트의 props로 데이터를 보내준다.
기본적으로 getInitialProps는 한 페이지에서 하나만 실행된다.
즉, _app에서 실행한다면, 하위 컴포넌트에서는 실행되지 않는다는 뜻이다. 하위 컴포넌트의 getInitialProps를 반영하려면
MyApp.getInitialProps = async (context) => {
const { ctx, Component } = context;
let pageProps = {title : 123123};
// 추가
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
};
기본적으로 제공하는 content를 활용해야 한다.
Component는 하위 컴포넌트를 의미하고, ctx는 Component의 구성이다.
- pathname : 현재 pathname
- query : 현재 query를 object로 가짐
- asPath : 전체 path
- req
- res
- err
※ 주의사항
- 서버에서 실행되기 때문에 Client에서 실행 가능한 Window, document 등은 피해야 한다.
- 한 페이지에 하나의 로직만 실행되기 때문에 하위 컴포넌트의 getInitialProps를 실행하기 위해선 커스텀이 필요하다.
getStaticProps
" 빌드 시 딱 한 번만 호출 " 되는 특성을 가지고 있다. 즉, 최초 빌드 시 빌드되는 값이 수정되는 일이 없는
경우 사용한다.
const DATA = [
{
id: 1,
title: "first data",
},
{
id: 2,
title: "second data",
},
];
const HomeComponent = (props) => {
return (
<>
{props.data.map((data) => (
<h1 key={data.id}>{data.title}</h1>
))}
</>
);
};
export async function getStaticProps() {
return {
props: {
data: DATA,
},
};
}
export default HomeComponent;
getStaticProps는 다음과 같이 return 할 수 있다.
- props : 해당 컴포넌트로 리턴할 값
- revalidate : 페이지 업데이트 주기
- notFound : boolean 값으로 404 신호를 보내는 것을 허용한다.
data를 빌드 시 가져와 static 하게 제공하기 때문에 빠른 속도로 페이지가 렌더링 된다. 그래서 페이지별 유저의 요청마다
fetch 할 필요가 없는 데이터를 가진 경우 렌더링에 유리하다.
getStaticPaths
페이지가 동적 라우팅을 쓰고 있으면서, getStaticProps를 사용할 경우 getStaticPaths를 추가해서
빌드 타임에 정적으로 렌더링 할 경로를 설정한다.
여기서 정의하지 않은 경로는 접근해도 화면이 나타나지 않는다. 만약 동적 라우팅 시, 라우팅 해야 하는 경우의 수를 전부 넣어줘야 한다.
// pages/posts/[id].js
function post() {
return {
// ...
}
}
export const getStaticPaths = async () => {
const res = await fetch('https://.../posts')
const posts = await res.json();
const paths = posts.map(post => ({
params: { id: post.id },
})
return { paths, fallback: false }
}
export const getStaticProps = async ({params}) => {
const res = await fetch(`https://.../posts/${params.id}`);
// ...
}
getStaticPaths는 paths에 정의되지 않은 경로로 접근할 경우 아무런 화면이 나오지 않고
404 화면이 나와진다.
하지만 fallback이 true의 경우 만들어지지 않은 것도 요청이 들어올 경우 만들어 준다는 뜻이 된다.
getServerSideProps
" 요청이 들어올 때마다 호출 " 되며, 그때마다 렌더링을 진행한다.
요청할 때마다 다시 호출되기 때문에 빌드 이후에도 자주 바뀌게 될 동적 데이터가 들어갈 경우에 사용한다.
const HomeComponent = (props) => {
return (
<>
// ...
</>
);
};
export async function getServerSideProps(context) {
const req = await fetch("http://.../data");
const data = await res.json()
if(!data) {
redirect: {
destination: '/',
permanent: fasle,
},
}
return {
props: {
data,
},
};
}
export default HomeComponent;
서버 쪽에서 렌더링 되는 방식으로 파라미터로 context를 받아서 서버의 요청 및 응답하거나, 직접 데이터를 받아온다.
또 만약에 특정 경로로 이동시켜야 할 경우 ( data가 없다던지 ,... ) redirect를 사용해서 이동이 가능하다.
요청이 들어올 때마다 호출되기 때문에 getStaticProps에 비해 성능상으로는 안 좋지만, 내용을 언제든지 수정할 수 있다.
'Next.js > 이론' 카테고리의 다른 글
[Next.js] _document & _app (0) | 2022.09.10 |
---|---|
[Next.js] 404 페이지 (3) | 2022.07.05 |
[Next.js] Dynamic Routes (1) | 2022.07.05 |
[Next.js] Server Side Rendering (1) | 2022.07.04 |
[Next.js] Redirect & Rewrite (1) | 2022.07.03 |