본문 바로가기
FE/Nuxt.js

Nuxt.js asyncData vs Fetch

by Day0404 2021. 4. 16.
728x90
반응형

asyncData vs Fetch

Nuxt.js 를 사용하다 보면 페이지가 마운트되기 전에 백엔드에서 API 를 호출하여 데이터를 가져와야 할 때가 많이 있습니다.

이러한 경우

<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>

이렇게 asyncData() 를 사용하거나

<template>
  <p v-if="$fetchState.pending">Fetching mountains...</p>
  <p v-else-if="$fetchState.error">An error occurred :(</p>
  <div v-else>
    <h1>Nuxt Mountains</h1>
    <ul>
      <li v-for="mountain of mountains">{{ mountain.title }}</li>
    </ul>
    <button @click="$fetch">Refresh</button>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        mountains: []
      }
    },
    async fetch() {
      this.mountains = await fetch(
        'https://api.nuxtjs.dev/mountains'
      ).then(res => res.json())
    }
  }
</script>

fetch() 를 사용하여 데이터를 가져오게 됩니다.

Nuxt.js 로 개발을 진행하면서 asyncData() 와 Fetch() 의 차이점을모르겠다고 생각했습니다. (물론 저만 이해 못했을지도..ㅎㅎ)

As far as page components are concerned, new fetch seems way too similar to asyncData() because they both deal with the local data. But there are some key differences worth taking note of as below.

Nuxt 공식 블로그의 내용을 인용했습니다.

풀이하자면 new Fetch() 와 asyncData() 모두 로컬 데이터를 처리하기 때문에 비슷해보이지만 몇가지 차이점이 있다고 합니다. 여기서 new Fetch() 는 Nuxt 2.12 이후 버전의 Fetch() 를 말합니다.

 

두 가지 메서드의 차이점을 살펴보면

asyncData

  1. asyncData is limited to only page-level components
  2. this context is unavailable
  3. Adds payload by returning the data

페이지 레벨에서만 제한되며, this 사용이 불가능하고, 데이터를 반환하여 페이로드를 추가한다.

data 를 컴포넌트 내에 선언할 필요가 없으며, asyncData 는 local data 와 merge 된다. 라고 설명하고 있습니다.

asyncData는 자동으로 data()의 데이터들과 병합을 합니다.

export default {
  async asyncData(context) {
    const data = await context.$axios.$get(
      `https://jsonplaceholder.typicode.com/todos`
    )
    // `todos` does not have to be declared in data()
    return { todos: data.Item }
    // `todos` is merged with local data
  }
}

 

Fetch

  1. fetch is available in all Vue components
  2. this context is available
  3. Simply mutates the local data

모든 뷰 컴포넌트에서 사용이 가능하며, this 사용이 가능하고, 단순 로컬 데이터를 변경한다. 라고 합니다.

 

export default {
  data() {
    return {
      todos: []
    }
  },
  async fetch() {
    const { data } = await axios.get(
      `https://jsonplaceholder.typicode.com/todos`
    )
    // `todos` has to be declared in data()
    this.todos = data
  }
}

Fetch 의 경우 Nuxt 2.12 버전 이전의 경우에는 component 가 initiating  되기 전에 호출이 되어 this 사용이 불가능 했지만 이후 버전은 server-side 에서 component instance 가 만들어지고 나서 호출이 되어 this 사용이 가능합니다.

 

Nuxt 2.12 Nuxt LifeCycle Hooks

출처 : https://nuxtjs.org/blog/understanding-how-fetch-works-in-nuxt-2-12/

또한 Nuxt 2.12 이후 Fetch 는 여러번 호출이 가능합니다.

 

watch 를 사용하여 쿼리 문자열에 대한 감시를 하려면 별도의 methods 를 구현해야 했습니다. 하지만 Fetch() 를 이용하여 해결이 가능합니다.

 

Nuxt 2.12 이전

{
    watch: {
        '$route.query' (query) {
            this.fetchCourses(query)
        }
    },

    methods: {
        async fetchCourses (query) {
            this.courses = await this.$axios.$get('courses', queryString.stringify(query))
        }
    },

    async asyncData ({ $axios, query }) {
        let courses = await $axios.$get('courses', queryString.stringify(query))

        return {
            courses
        }
    }
}

 

Nuxt 2.12 이후

{
    // ... other page stuff
    
    watch: {
        '$route.query': '$fetch'
    },

    async fetch () {
        this.courses = await this.$axios.$get('courses', queryString.stringify(this.$route.query))
    }
}

asyncData를 사용하여 다시 가져올 수 없기 때문에 watch가 호출 할 수있는 다른 methods를 만들어야 했는데 이러한 불필요한 코드를 줄일 수 있게 되었습니다.

 

 

Loading

asyncData는 asynData 메서드 내의 로직이 끝날 때 까지 페이지 전환을 차단합니다.

이는 자칫 사용자가 페이지를 보기전에 오래 기다릴 수 도 있음을 의미합니다.

fetch는 $fetchState.pending 속성을 통해 로딩 콘텐츠를 구성할 수 있습니다.

<template>
  <div>
  	<!-- 로딩 콘텐츠 -->
    <p v-if="$fetchState.pending">Fetching posts...</p>
    <p v-else-if="$fetchState.error">Error while fetching posts</p>
    <ul v-else>
      …
    </ul>
  </div>
</template>

Error

asyncData는 페이지에서 오류가 발생하면 렌더링되지 않습니다.

fetch는 $fetchState.error 속성을 통해 에러 콘텐츠를 구성할 수 있습니다.

 

<template>
  <div>
    <p v-if="$fetchState.pending">Fetching posts...</p>
    <!-- 에러 콘텐츠 -->
    <p v-else-if="$fetchState.error">Error while fetching posts</p>
    <ul v-else>
      …
    </ul>
  </div>
</template>

 

스택오버플로우에서 많이 찾아보았지만 서비스의 아키텍쳐에 따라 뭘 쓰는지가 달라진다고 합니다.

asyncData, fetch 그냥 차이점들만 보이며 이런 상황에서는 이걸 써라! 라는 정답은 아직 못 찾았습니다.

Nuxt에서도 fetch를 업데이트한 걸 보면 fetch를 더 밀고 있는건 아닌가? 라는 생각을 해봅니다. (물론 한낱 주니어 개발자의 개인적인 생각입니다.)

또한 this 를 사용할 수 있다는게 큰 메리트로 느껴집니다.

그래서 지금 진행중인 프로젝트에서도 fetch를 많이 사용중입니다.

 

반응형

'FE > Nuxt.js' 카테고리의 다른 글

Nuxt.js Toast Ui Editor 적용  (1) 2021.04.26
Nuxt.js routing 알아보기  (0) 2021.04.23
Nuxt.js 에서 Props 사용하기  (0) 2021.04.15
Nuxt.js 에서 Vuex Store 사용하기  (0) 2021.04.15
Nuxt.js 란? (feat. SSR, CSR)  (0) 2021.04.09

댓글