[NuxtJS] asyncData와 fetch 비교 및 사용법
asyncData VS fetch
NuxtJS를 사용하게 되면 자주 보게 되는 혹은 꼭 알고 있어야 하는 개념 중에 하나가 asyncData와 fetch가 아닐까 싶다.
asyncData와 fetch의 경우에는 VueJS에서는 제공하지 않았던 것이기 때문에 Vue를 쓰다가 Nuxt를 사용하게 된다면 알고 가야 할 개념이다.
물론 그 뿐만아니라 vue랑은 lifecycle이 좀 달라졌기 때문에 전반적으로 새롭게 알아야 하는 개념들이 많아졌다.
라이프 사이클을 머릿속에 넣어두고 asyncData와 fetch에 대해 알아보자.
asyncData
라이프 사이클을 보면 알겠지만 asyncData의 경우에는 서버사이드에서 실행되는 녀석이다.
asyncData의 경우 아래와 같은 특징을 가진다.
- 서버사이드에서 실행된다. (beforeCreate 훅 이전에)
- 페이지(Page) 컴포넌트에서만 사용이 가능하다.
- this를 사용할 수 없다.
- return 값은 컴포넌트의 data와 병합되어 사용이 가능하다.
- context 객체를 첫 번째 인수로 받아 사용할 수 있다.
이러한 특징들을 가지고 있고 공식문서에 적혀있는 예제를 한번 살펴보자.
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.description }}</p>
</div>
</template>
<script>
export default {
async asyncData({ params, $http }) {
const post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post }
}
}
</script>
나중에 context 객체에 대해 대략적으로나마 공부할 겸 정리하긴 할 건데,
그 context 객체 안에 params가 존재하며 $http는 라이브러리를 사용한 것이라고 한다.
보통 저런 식으로 비동기 통신에 사용하고 받아온 데이터를 return 하여 template에서 바로 사용이 가능하다.
(여기서 return을 하게 되면 data와 합쳐지기 때문에 사용이 가능한 것이다.)
fetch
fetch의 경우 라이프 사이클을 보면 좀 의아하게 서버사이드와 클라이언트사이드 두 곳에 적혀있다.
fetch는 asyncData와 다르게 재밌게도 두 가지 상황에서 호출이 발생하는데,
처음에는 컴포넌트 인스턴스가 생성된 후 서버사이드 렌더링 동안에 실행되며 다음에는 클라리언트 사이드에서 내비게이션 되는 동안 호출된다.
역시 아무래도 말로 설명하기가 참 어렵기 때문에 아래 사이트를 참고하여 fetch의 동작 원리를 배워보면 좋을 듯싶다.
https://joshua1988.github.io/vue-camp/nuxt/data-fetching.html#fetch
동작원리를 대충 알았으면 fetch의 특징부터 한번 배워보자.
- 페이지 컴포넌트뿐만 아니라 일반 컴포넌트에서도 사용이 가능하다.
- 컨텍스트 객체를 첫 번째 인수로 받으며, 데이터를 스토어에 넣어 사용할 수 있다.
- fetch의 return값은 Promise이다.
- asyncData와 다르게 아래와 같은 속성들을 제공한다.
$fetchState : 데이터 호출 상태를 나타내는 속성으로 pending, error, timestamp를 제공
$fetch : fetch 로직을 다시 실행시킬 수 있다.
fetchOnServer : 서버 사이드 렌더링에서 fetch의 실행을 제어하는 속성이다. (기본값 true)
fetchDelay : 실행 시간을 설정한다.(기본값 200)
공식문서의 예제를 한번 살펴보자.
<script>
export default {
data() {
return {
posts: []
}
},
async fetch() {
this.posts = await this.$http.$get('https://api.nuxtjs.dev/posts')
},
fetchOnServer: false,
// multiple components can return the same `fetchKey` and Nuxt will track them both separately
fetchKey: 'site-sidebar',
// alternatively, for more control, a function can be passed with access to the component instance
// It will be called in `created` and must not depend on fetched data
fetchKey(getCounter) {
// getCounter is a method that can be called to get the next number in a sequence
// as part of generating a unique fetchKey.
return this.someOtherData + getCounter('sidebar')
}
}
</script>
여기서 fetchKey의 경우는 Nuxt버전에 따라 안될 수도 있으니 버전을 잘 살펴보아야 한다. (2.15 이상)
그리고 예제에는 없지만 $fetch의 경우에는 methods 같은 곳에서 "this.$fetch()" 이런 식으로 사용하게 되면 그 fetch 로직을 다시 실행시켜 사용할 수 있다.
참고: https://nuxtjs.org/docs/components-glossary/fetch/
만약 Nuxt3을 쓰거나 Composition API를 쓰게 된다면 보통 asyncData와 fetch 보다는 useAsyncData와 useFetch를 쓰게 될 터인데, 아마 컨셉자체를 동일할 것으로 생각된다.
그래도 Vue3 자체가 굉장히 많이 변하기도 했고 다음에 시간 내서 useAsyncData와 useFetch에 대해 공부해 봐야겠다.
참고: https://nuxtjs.org/announcements/understanding-how-fetch-works-in-nuxt-2-12/