목록
Fetching Data for Pages
지금까지 next.js의 routing API를 활용하는 방법에 대해 배웠습니다. 이것만으로도 꽤 괜찮은 앱을 만들 수 있지만, 실제로 서비스 되는 앱들은 보통 데이터를 가지고 와서 앱에 뿌려주어야 합니다. Next.js에는 데이터를 가지고 오는 표준 API가 제공됩니다. 우리는 비동기 함수인 'getInitialProps'를 사용할 것입니다.
이를 통해 데이터를 가지고 올 수 있고 props를 통해 우리의 페이지에 전달 할 수 있습니다. getInitialProps를 사용함으로써 서버와 클라이언트에서 모두 작동하게 할 수 있습니다.
이번 장에서는 getInitialProps를 사용해 TVmaze API에서 배트맨 tv show의 정보를 가지고 와서 앱을 만들어 보겠습니다.
Setup
아래의 예제를 다운로드 해주세요
git clone https://github.com/zeit/next-learn-demo.git
cd next-learn-demo
cd 6-fetching-data
npm install
npm run dev
Fetching Batman Shows
현재 데모 앱에는 블로그 포스트 리스트가 있습니다. 지금부터 할 것은 batman TV shows 리스트를 보여줄 것입니다. 하드코딩하지 않고 원격 서버로 부터 데이터를 가지고 와서 만들겠습니다.
TV show를 검색하는 API인 TVMaze API 를 사용해서 데이터를 가지고 올 것입니다.
먼저 우리는 isomorphic-unfetch 를 설지해야 합니다. 데이터를 가지고 올 때 사용할 라이브러리 입니다. 브라우저의 fetch API를 간단하게 구현한 것이지만 클라이언트와 서버에서 모두 작동합니다.
npm install --save isomorphic-unfetch
'pages/index.js'에 아래의 코드를 입력하세요
import fetch from 'isomorphic-unfetch'
const Index = props => (
<Layout>
<h1>Batman TV Shows</h1>
<ul>
{props.shows.map(show => (
<li key={show.id}>
<Link href="/p/[id]" as={`/p/${show.id}`}>
<a>{show.name}</a>
</Link>
</li>
))}
</ul>
</Layout>
)
Index.getInitialProps = async function() {
const res = await fetch('https://api.tvmaze.com/search/shows?q=batman')
const data = await res.json()
console.log(`Show data fetched. Count: ${data.length}`)
return {
shows: data.map(entry => entry.show)
}
}
export default Index
위의 페이지에서 Index.getInitialProps를 제외하고는 익숙한 내용일 것입니다. Index.getInitialProps를 살펴 봅시다
Index.getInitialProps = async function() {
const res = await fetch('https://api.tvmaze.com/search/shows?q=batman')
const data = await res.json()
console.log(`Show data fetched. Count: ${data.length}`)
return {
shows: data.map(entry => entry.show)
}
}
앱의 어느 페이지에나 추가할 수 있는 정적인 비동기 함수 입니다. 이를 사용해서 가지고 온 데이터를 페이지에 props로 넘겨줄 수 있습니다.
index페이지를 확인해 보면 show props로 가지고온 정보를 넘겨주어 화면에 리스트가 나오는 것을 확인 할 수 있습니다.
여기서 확인해야 할 것은 데이터를 서버에서 가지고 오는지 클라이언트에서 가지고 오는지 입니다. 새로 고침을 했을 때 getInitialProps 안에 있는 console.log의 내용이 어디에 찍히는지 보면 확인을 할 수 있습니다. 새로 고침을 할 경우 서버의 콘솔에서만 메세지가 출력되는 것을 볼 수 있습니다.
Only on the Server
서버에서 이미 데이터를 가지고 왔기 때문에 클라이언트에서는 다시 데이터를 가지고 올 필요 없이 서버에서 가져온 데이터를 기반으로 페이지를 렌더합니다. 이는 초기 url로 접속시에는 서버사이드 렌더링이 되기 때문입니다. 브라우저 내부에서 페이지를 이동할 경우에는 클라이언트 사이드 렌더링이 되므로 브라우저의 개발자 도구 콘솔에 메세지가 나타날 것 입니다.
Implement the Post Page
이제 TV show의 상세한 정보를 보여주는 페이지를 추가합시다.
'pages/p/[id].js' 파일에 아래 내용을 코딩하세요
import Layout from '../../components/MyLayout'
import fetch from 'isomorphic-unfetch'
const Post = props => (
<Layout>
<h1>{props.show.name}</h1>
<p>{props.show.summary.replace(/<[/]?p>/g, '')}</p>
<img src={props.show.image.medium} />
</Layout>
)
Post.getInitialProps = async function(context) {
const { id } = context.query
const res = await fetch(`https://api.tvmaze.com/shows/${id}`)
const show = await res.json()
console.log(`Fetched show: ${show.name}`)
return { show }
}
export default Post
이 페이지의 getInitialProps를 살펴 봅시다
Post.getInitialProps = async function(context) {
const { id } = context.query
const res = await fetch(`https://api.tvmaze.com/shows/${id}`)
const show = await res.json()
console.log(`Fetched show: ${show.name}`)
return { show }
}
첫 번째 인수로 context객체를 넣었습니다. 'query'객체를 fetch 에서 사용할 수 있습니다.
예를 들면 query에서 show ID를 선택해서 TVMaze API의 show 데이터를 가지고 올 수 있습니다.
Fetch Data in Client Side
서버와 브라우저 콘솔을 모두 열고 이번에는 콘솔 메세지가 어디에 나타나는지 확인해 봅시다. index페이지에 생성된 링크를 클릭 했을 때 브라우저의 콘솔 창에 콘솔 메세지가 나타나는 것을 확인 할 수 있습니다. 위에서 설명 했듯이 브라우저 내부에서의 이동은 클라이언트 사이드 렌더링이 됩니다.
Finally
지금까지 Next.js에서 가장 중요한 기능 중 하나인 서버사이드 렌더링과 데이터를 가지고 오는 방법에 대해 배웠습니다. 기본적인 방법만 배웠지만 대부분의 경우 문제가 없을 것 입니다. 더 자세히 알고 싶다면 Next.js document의 data fetching 를 확인 하세요
Next js 튜토리얼 5편 : 동적 라우팅
Next js 튜토리얼 6편 : 데이터 가져오기 - 현재 글
Next js 튜토리얼 7편 : 컴포넌트 스타일링
Next js 튜토리얼 8편 : 배포