NextJS는 기본적으로 페이지를
SSR
를 이용해pre-rendering
한다. SSR를 활용할 수 있는 기능들 중 getServerSideProps 함수가 있다.
NextJS 공식문서 👍
export async function getServerSideProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
getServerSideProps
함수를 export
하는 경우 Next.js
는 getServerSideProps
가 반환하는 데이터를 사용하여 페이지를 pre-render
한다.props
로 전달된다.Example
👉 영화 GET api를 호출하여 Home Page에 영화 정보들을 렌더링하려 한다.
// pages/index.tsx
import { useQuery } from "react-query";
import CustomHead from "../components/CustomHead";
import Movie from "../components/Movie";
import { getMovies, IMovieProps } from "../lib/api/movies";
import styled from "styled-components";
// ... styled components 생략
const Home = () => {
const { data: movies, status } = useQuery(["movies", "popular"], () =>
getMovies()
);
if (status === "loading") {
return <h4>Loading...</h4>;
}
return (
<HomeMain>
<CustomHead title="Home" />
{movies.map((movie: IMovieProps) => (
<Movie key={movie.id} movie={movie} />
))}
</HomeMain>
);
};
export default Home;
// lib/api/movies.ts
import axios from "axios";
export const getMovies = async () => {
const { data } = await axios.get("/api/movies");
return data.results;
};
export interface IGetMoviesProps {
page: number;
results: IMovieProps[];
total_pages: number;
total_results: number;
}
export interface IMovieProps {
id: number;
backdrop_path: string;
original_title: string;
overview: string;
poster_path: string;
title: string;
vote_average: number;
genre_ids: number[];
}
🔎 확대해서 보면 Home Page
html
파일 body에는<h4>Loading...</h4>
만 있고 영화 데이터는 없다.
getServerSideProps
함수에서 영화 GET api를 호출하고 영화 데이터를 반환하여 pre-render
하기// pages/index.tsx
import type {
GetServerSideProps,
InferGetServerSidePropsType,
} from "next";
import CustomHead from "../components/CustomHead";
import Movie from "../components/Movie";
import { IMovieProps } from "../lib/api/movies";
import styled from "styled-components";
// ... styled components 생략
const Home = ({ results }: InferGetServerSidePropsType<GetServerSideProps>) => {
return (
<HomeMain>
<CustomHead title="Home" />
{results?.map((movie: IMovieProps) => (
<Movie key={movie.id} movie={movie} />
))}
</HomeMain>
);
};
export default Home;
// 페이지 request마다 실행됨.
export async function getServerSideProps() {
const { results } = await (
await fetch("http://localhost:3000/api/movies") // absolute URL (Server Side)
).json();
return {
props: { results }, // props를 통해 page에 data전달
};
}
import "../styles/globals.css";
import type { AppProps } from "next/app";
import Layout from "../components/Layout";
import { QueryClient, QueryClientProvider } from "react-query";
const queryClient = new QueryClient();
function MyApp({ Component, pageProps }: AppProps) {
return (
<QueryClientProvider client={queryClient}>
<Layout>
<Component {...pageProps} /> // getServerSideProps함수가 반환한 데이터는 페이지 컴포넌트에 pageProps로 전달됨
</Layout>
</QueryClientProvider>
);
}
export default MyApp;
🔎 확대해서 보면 Home Page
html
파일 body에 영화 데이터가 있다.
👍
getServerSideProps
함수를 이용하면 페이지를pre-render
할 때 필요한 데이터를 포함시킬 수 있다.
👍 html 파일에 데이터가 있기 때문에SEO
에 좋다.
👎 만약 API 속도가 느리다면, 유저는 아무것도 보지 못한 채로 오래 기다려야 한다.
Client Side
Server Side
getServerSideProps
함수를 호출하면 context paramerter
가 들어오게 된다.params
: 만약 페이지가 dynamic route가 사용한다면, params는 라우팅 파라미터를 포함한다.page/movies/[id].tsx
-> params : { id: ...}
query
: 쿼리 문자열을 나타내는 객체Example
// pages/movies/[...params].tsx
import { GetServerSideProps, InferGetServerSidePropsType } from "next";
import CustomHead from "../../components/CustomHead";
type MovieDetailParams = [string, string] | [];
const Detail = ({
params,
}: InferGetServerSidePropsType<typeof getServerSideProps>) => {
const [title, id] = params as MovieDetailParams;
return (
<main>
<CustomHead title={title as string} />
<h1>{title}</h1>
</main>
);
};
export default Detail;
export const getServerSideProps: GetServerSideProps = async (context) => {
const params = context.params!.params as MovieDetailParams;
return {
props: { params },
};
};