Next.js가 현재 12까지 나와있다. Next.js 9.3 버전 부터는 이제 pre-rendering을 위한 data-fetching을 위해 사용하던 getInitialProps가 getStaticProps, getServerSideProps, getStaticPaths 세가지로 분리되었다.
그 중에서 오늘 주로 다룰 것은 getServerSideProps와 getStaticProps이다.
가장 큰 차이점이라고 하면 SSR와 SSG의 차이일 것이다.
If you export a function called getStaticProps (Static Site Generation) from a page, Next.js will pre-render this page at build time using the props returned by getStaticProps.
해당 웹 앱이 처음 빌드 시(next build)에 딱 한번만 호출되고 해당 내용은 static file로 빌드되게 된다. 그렇기 때문에 이후 수정이 불가능하다.
getServerSideProps only runs on server-side and never runs on the browser. If a page uses getServerSideProps, then:
- When you request this page directly, getServerSideProps runs at request time, and this page will be pre-rendered with the returned props
- When you request this page on client-side page transitions through next/link or next/router, Next.js sends an API request to the server, which runs getServerSideProps
page가 요청을 받을때마다 호출되어 pre-render 하게 된다. 하지만 SSG에 비해 효율적으로 떨어지는 측면이 있다. 하지만 언제든지 내용을 동적으로 수정할 수 있는게 장점이다. 우리는 url 내 쿼리를 활용하여 api 요청 후 해당 데이터를 props로 넘겨주기 때문에 getServerSideProps를 활용하여 개발을 해볼 것이다.
Context Object가 parameter로 해당 함수에 함께 넘어오게 되는데 이때 아래의 key값을 통해서 접근을 할 수 있다. 해당 함수는 Client에서 돌아가는게 아닌 server에서 돌아가기 때문이다.
- params: If this page uses a dynamic route, params contains the route parameters. If the page name is [id].js , then - params will look like { id: ... }.
- req: The HTTP IncomingMessage object.
- res: The HTTP response object.
- query: An object representing the query string.
- preview: preview is true if the page is in the Preview Mode and false otherwise.
- previewData: The preview data set by setPreviewData.
- resolvedUrl: A normalized version of the request URL that strips the _next/data prefix for client transitions and - includes original query values.
typescirpt를 적용하기 위해선 먼저 GetServerSideProps라는 type을 import 해줘야 한다. 그리고 개인적으로 fetch보단 axios와 try-catch를 통한 promise 핸들링을 좋아하기 때문에 아래와 같이 코드를 작성해줄 수 있다.
import { GetServerSideProps } from 'next'
...
export const getServerSideProps : getServerSideProps = async (context) => {
try{
....
return {
props : {
PropsName : data...
}
}
} catch(err){
console.log(err);
return {
props : {},
}
}
}
그리고 아래처럼 api 호출을 해준다. 이때 api url은 .env로 빼서 개발을 하는것이 더욱 좋다.
혹은 headers가 반복되면 이를 customHook으로 빼서 개발을 하는 것도 방법이 될 수 있다.
export const getServerSideProps: GetServerSideProps = async (context) => {
try {
const { menuId } = context.query;
const response = await axios.get<CategoryType[]>(
"http://localhost:8080/category/get/menu",
{
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
params: {
menuId: menuId,
},
}
);
const data = response.data;
console.log(data);
return {
props: {
CategoryData: data,
},
};
} catch (err) {
console.log(err);
return {
props: {},
};
}
};