이 글은 Next.js 공식 문서의 Data Fetching Overview를 번역한 글입니다.
Next.js에서 Data fetching(데이터 불러오기)은 애플리케이션의 사용 사례에 따라 다양한 방식으로 콘텐츠를 렌더링할 수 있습니다. 여기에는 서버 측 렌더링(SSR) 또는 정적 생성(SSG)을 사용한 사전 렌더링과 Incremental Static Regeneration을 통한 런타임시 콘텐츠의 업데이트나 생성하는 방식이 서술되어 있습니다.
페이지에서 getServerSideProps
라는 함수를 export할 경우, Next.js는 각 요청에서 getServerSideProps
에서 반환된 데이터를 사용하여 페이지를 미리 렌더링합니다.
export async function getServerSideProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
getServerSideProps
는 서버 측에서만 실행되고 브라우저에서는 실행되지 않습니다. 페이지에서 getServerSideProps
를 사용하는 경우:
getServerSideProps
는 요청 시에 실행되며 이 페이지는 반환된 props로 미리 렌더링됩니다.next/link
또는 next/router
가 요청되면 Next.js는 API 요청을 서버에 보내게 되고 getServerSideProps
가 동작하게 됩니다.이는 getServerSideProps
를 실행하게 하는 JSON을 반환하고, 그 JSON은 페이지를 렌더링하는데 사용됩니다. 이 모든 작업은 Next.js에서 자동으로 처리되므로 getServerSideProps
를 사용하면 추가 작업을 수행할 필요가 없습니다.
next-code-elimination 도구 를 사용 하여 Next.js가 클라이언트 측 번들에서 제거하는 항목을 확인할 수 있습니다.
getServerSideProps
는 하나의 페이지에서만 export할 수 있습니다. 페이지가 아닌 파일에서는 export할 수 없습니다.
getServerSideProps
독립적인 함수로 export해야 합니다. 페이지 컴포넌트 속성으로 추가하면 작동하지 않습니다.
getServerSideProps API 참고자료는 getServerSideProps
와 함께 사용할 수 있는 모든 매개변수와 props를 다룹니다.
요청 시 데이터를 가져와야 하는 페이지를 미리 렌더링해야 하는 경우에만 getServerSideProps
를 사용해야 합니다. 서버가 모든 요청에 대한 결과를 계산해야 하고 cache-control
헤더를 사용하여 CDN에서만 결과를 캐시할 수 있기 때문에(추가 configuration이 필요할 수 있음) TTFB(Time to First Byte)가 getStaticProps
보다 높습니다.
데이터를 미리 렌더링할 필요가 없다면 클라이언트 측에서 데이터를 가져오는 것을 고려해야 합니다.
서버에서 데이터를 가져온 다음 에서 해당 API 경로를 호출하려는 경우 API 경로 에 도달 하고 싶을 수 있습니다 getServerSideProps. getServerSideProps이는 서버에서 실행되는 API 경로와 둘 다로 인해 추가 요청이 발생하기 때문에 불필요하고 비효율적인 접근 방식 입니다.
다음 예를 들어보세요. API 경로는 CMS에서 일부 데이터를 가져오는 데 사용됩니다. 그런 다음 해당 API 경로가 에서 직접 호출됩니다 getServerSideProps. 이렇게 하면 추가 호출이 발생하여 성능이 저하됩니다. 대신 API 경로 내에서 사용되는 로직을 getServerSideProps. 이는 내부에서 직접 CMS, 데이터베이스 또는 기타 API를 호출하는 것을 의미할 수 있습니다 getServerSideProps.
페이지에 자주 업데이트되는 데이터가 포함되어 있고, 데이터를 미리 렌더링할 필요가 없는 경우 클라이언트 측에서 데이터를 가져올 수 있습니다 . 아래는 사용자별 데이터에 대한 예시입니다.
이 접근 방식은 예를 들어 사용자 대시보드 페이지에 적합합니다. 대시보드는 각 사용자에게 특화된 비공개 페이지이므로 SEO는 관련이 없으며 페이지를 미리 렌더링할 필요가 없습니다. 데이터는 자주 업데이트되므로 요청 시 데이터를 가져와야 합니다.
다음 예는 요청 시 데이터를 가져오고 결과를 미리 렌더링하는 방법을 보여줍니다.
function Page({ data }) {
// Render data...
}
// This gets called on every request
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(`https://.../data`)
const data = await res.json()
// Pass data to the page via props
return { props: { data } }
}
export default Page
getServerSideProps
내부에 오류가 발생하면 pages/500.js
파일이 나타나게 됩니다. 500페이지를 만드는 방법에 대한 자세한 내용은 공식문서를 확인하세요. 개발 중에는 이 파일이 사용되지 않고 대신 개발 오버레이가 표시됩니다.
페이지에서 getStaticProps
(정적 사이트 생성)이라는 함수를 export하는 경우, Next.js는 빌드 시 getStaticProps
에서 반환된 props를 사용하여 이 페이지를 미리 렌더링합니다.
export async function getStaticProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
다음과 같은 경우 getStaticProps
를 사용해야 합니다.
getStaticProps
가 HTML
및 JSON
파일을 생성할 때, 둘 다 성능을 위해 CDN에 캐시될 수 있습니다.getStaticProps
항상 서버에서 실행되고 클라이언트에서는 실행되지 않습니다.
getStaticProps
은 항상 next build시에 실행revalidate
를 사용할 때, getStaticProps
를 백그라운드에서 실행unstable_revalidate
를 사용할 때, 요청에 따라 getStaticProps
백그라운드에서 실행Incremental Static Regeneration
과 결합할 경우, 오래된 페이지가 재검증되는 동안 getStaticProps
가 백그라운드에서 실행되고 새로운 페이지가 브라우저에 제공되게 됩니다.
getStaticProps
정적 HTML을 생성하므로 새로운 요청(예: 쿼리 매개변수 또는 HTTP 헤더)에 접근할 수 없습니다. 요청에 따라 데이터 접근이 필요한 페이지일 경우 Middleware를 추가할 수 있습니다.
다음 예는 CMS에서 블로그 게시물 목록을 가져오는 방법을 보여줍니다.
// posts will be populated at build time by getStaticProps()
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export async function getStaticProps() {
// Call an external API endpoint to get posts.
// You can use any data fetching library
const res = await fetch('https://.../posts')
const posts = await res.json()
// By returning { props: { posts } }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts,
},
}
}
export default Blog
getStaticProps
API 참고자료는 와 함께 사용할 수 있는 모든 매개변수와 props를 다룹니다.
getStaticProps
는 서버 측에서만 실행 되므로 클라이언트 측에서는 실행되지 않습니다. 브라우저용 JS 번들에도 포함되지 않으므로 브라우저로 보내지 않고 직접 데이터베이스 쿼리를 작성할 수 있습니다.
즉, API route 를 getStaticProps
(자체적으로 외부 소스에서 데이터를 가져옴)로 가져오는 대신 에 직접 서버 측 코드를 getStaticProps
내부에 작성할 수 있습니다.
다음 예를 들어보세요. API route는 CMS에서 일부 데이터를 가져오는데 사용됩니다. 그런 다음 해당 API route가 getStaticProps
에서 직접 호출됩니다. 이렇게 하면 추가 호출이 발생하여 성능이 저하됩니다. CMS에서 데이터를 가져오는 로직 대신에 lib/
디렉토리를 사용하여 데이터를 공유할 수 있습니다.
// lib/fetch-posts.js
// The following function is shared
// with getStaticProps and API routes
// from a `lib/` directory
export async function loadPosts() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts/')
const data = await res.json()
return data
}
// pages/blog.js
import { loadPosts } from '../lib/load-posts'
// This function runs only on the server side
export async function getStaticProps() {
// Instead of fetching your `/api` route you can call the same
// function directly in `getStaticProps`
const posts = await loadPosts()
// Props returned will be passed to the page component
return { props: { posts } }
}
또는 API route를 사용하여 데이터를 가져 오지 않는 경우, fetch()
API를 직접 사용하여 getStaticProps 내부에서 데이터를 가져올 수 있습니다.
Next.js가 클라이언트 측 번들에서 무엇을 제거하는지 확인하기 위해 next-code-elimination tool을 사용할 수 있습니다 .
getStaticProps
가 포함 된 페이지가 빌드 시 미리 렌더링되면 페이지의 HTML 파일 외에 Next.js가 getStaticProps
의 실행 결과를 담은 JSON 파일을 생성합니다.
이 JSON 파일은 next/link
이나 next/router
를 통한 클라이언트 측 라우팅에 사용됩니다. getStaticProps
를 사용하여 미리 렌더링된 페이지로 이동하면 Next.js는 이 JSON 파일(빌드 시 미리 계산됨)을 가져와 페이지 컴포넌트의 props로 사용합니다.
Incremental Static Generation을 사용할 경우, getStaticProps
는 클라이언트 측 탐색에 필요한 JSON을 생성하기 위해 백그라운드에서 실행됩니다. 동일한 페이지에 대한 여러 요청의 형태로 이를 볼 수 있지만 이는 의도된 것이며 최종 사용자 성능에 영향을 미치지 않습니다.
getStaticProps
는 페이지에서만 export할 수 있습니다.
이 제한의 이유 중 하나는 페이지가 렌더링되기 전에 React에 필요한 모든 데이터가 있어야 하기 때문입니다.
getStaticProps
는 반드시 독립적인 함수로 export해야 합니다. 페이지 컴포넌트의 속성으로 getStaticProps
를 사용하면 작동하지 않습니다.
개발모드(next dev
)에서는 getStaticProps
는 모든 요청에 호출됩니다.
Client-side data fetching은 SEO 인덱싱이 필요하지 않거나, 데이터를 미리 렌더링할 필요가 없거나, 페이지 콘텐츠를 자주 업데이트해야 할 때 유용합니다. 서버 측 렌더링 API와 달리 component level에서 data fetching을 사용할 수 있습니다.
페이지 수준에서 data를 fetch하면 런타임에 데이터를 가져오고, 데이터가 변경되면 페이지 내용이 업데이트됩니다. 컴포넌트 레벨에서 사용되는 경우, 컴포넌트 마운트 시 데이터를 가져오고 데이터가 변경되면 컴포넌트의 내용이 업데이트됩니다.
클라이언트 측 데이터 가져오기를 사용하면 애플리케이션의 성능과 페이지의 로드 속도에 영향을 미칠 수 있다는 점에 유의하는 것이 중요합니다. 이는 컴포넌트나 페이지가 마운트되는 시점에 데이터 fetching이 이루어지고 해당 데이터는 캐싱되지 않기 때문입니다.
다음 예제는 useEffect hook을 사용하여 클라이언트 측에서 데이터를 가져오는 방법을 보여줍니다.
function Profile() {
const [data, setData] = useState(null)
const [isLoading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
fetch('api/profile-data')
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
}, [])
if (isLoading) return <p>Loading...</p>
if (!data) return <p>No profile data</p>
return (
<div>
<h1>{data.name}</h1>
<p>{data.bio}</p>
</div>
)
}
Next.js 팀은 data feching을 위한 SWR을 사용하기 위해 React hook 라이브러리를 만들었습니다. 클라이언트 측에서 데이터를 가져오는 경우 사용을 적극 권장합니다. 캐싱, revalidation, focus tracking, refetching on intervals 등을 처리합니다.
위와 같은 예를 이제 SWR을 사용하여 프로필 데이터를 가져올 수 있습니다. SWR은 자동으로 데이터를 캐싱하고 데이터가 오래되면 유효성을 다시 검사합니다.
SWR 사용에 대한 자세한 내용은 SWR 문서를 확인하십시오.
import useSWR from 'swr'
const fetcher = (...args) => fetch(...args).then((res) => res.json())
function Profile() {
const { data, error } = useSWR('/api/profile-data', fetcher)
if (error) return <div>Failed to load</div>
if (!data) return <div>Loading...</div>
return (
<div>
<h1>{data.name}</h1>
<p>{data.bio}</p>
</div>
)
}
페이지에 Dynamic Routes가 있고 getStaticProps
를 사용하는 경우, 경로들의 목록을 정적으로 정의해야 합니다.
동적 경로를 사용하는 페이지에서 getStaticPaths
(정적 사이트 생성) 함수를 export할 때, Next.js는 에서 지정한 모든 경로를 정적으로 미리 렌더링합니다.
export async function getStaticPaths() {
return {
paths: [
{ params: { ... } }
],
fallback: true // false or 'blocking'
};
}
getStaticPaths
는 반드시 getStaticProps
와 함께 사용해야 합니다. getServerSideProps
와 함께 사용할 수 없습니다.
getStaticPaths
API 참고자료는 모든 매개변수와 props을 다루고 있습니다.
Dynamic routes를 사용한 페이지를 정적으로 사전 렌더링할 경우 getStaticPaths
사용해야 합니다.
getStaticProps
는 HTML및 JSON파일을 생성하고, 둘 다 성능을 위해 CDN에 의해 캐시될 수 있음getStaticPaths
는 프로덕션 환경에서 빌드하는 동안에만 실행되며 런타임에는 호출되지 않습니다.
getStaticProps
는 next build
중에 반환된 paths
에 실행getStaticProps
는 fallback: true
설정할 경우 백그라운드에서 실행getStaticProps
는 fallback: blocking
사용할 때 초기 렌더링 전에 호출getStaticPaths
은 getStaticProps
를 사용하는 dynamic route에서만 export할 수 있습니다. 페이지가 아닌 파일(예: components
폴더)에서 export할 수 없습니다.
getStaticPaths
는 독립적 함수로 export해야 합니다. 페이지 컴포넌트의 속성으로 추가할 경우 작동하지 않습니다.