์‹œ์ž‘ํ•˜๋ฉฐ

Nuxt ๊ณต์‹ ๋ฌธ์„œ์— ์žˆ๋Š” Data Fetching w์— ๊ด€๋ จ๋œ ๋‚ด์šฉ์„ ๋ฒˆ์—ญํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

Data Fetching

Nuxt์—์„œ๋Š” API๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. fetch ๋ฉ”์„œ๋“œ์™€ asyncData ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Nuxt๋Š” client-side ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋”ฉํ•˜๊ธฐ ์œ„ํ•œ ์ „ํ†ต์ ์ธ Vue์˜ ํŒจํ„ด์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. (์ปดํฌ๋„ŒํŠธ์˜ mounted() ํ›…์—์„œ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ) ๊ทธ๋Ÿฌ๋‚˜ ๋ฒ”์šฉ์ ์œผ๋กœ๋Š” server-side ๋ Œ๋”๋ง ๋•Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก Nuxt์˜ ํŠน์ˆ˜ ํ›…๋“ค์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํŽ˜์ด์ง€์— ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Nuxt์˜ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋”ฉํ•˜๋Š” ๋‘๊ฐ€์ง€ hooks:

  • asyncData: ์ด ํ›…์€ page ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด ํ›…์€ client-side ๋ Œ๋”๋ง ๋™์•ˆ ๋กœ๋”ฉ๋˜๋Š” ๊ณต๊ฐ„์„ ํ‘œ์‹œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋Œ€์‹ ์—, ์ด ํ›…์€ ํ•ด๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ํŽ˜์ด์ง€ ์ด๋™์„ ๋ง‰๊ณ  ์‹คํŒจํ•  ๊ฒฝ์šฐ ์—๋Ÿฌ ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

  • fetch (Nuxt 2.12+): ์ด ํ›…์€ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋กœ๋”ฉ ์ƒํƒœ(client-side ๋ Œ๋”๋ง ์ค‘)์™€ ์—๋Ÿฌ๋ฅผ ๋ Œ๋”๋ง ํ•˜๊ธฐ ์œ„ํ•œ shortcuts๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์œ„ ํ›…๋“ค์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. HTTP API ์š”์ฒญ์„ ์œ„ํ•œ @nuxt/axios ๋‚˜ @nuxt/http ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ header ์„ค์ •์„ ์œ„ํ•œ ๊ฐ€์ด๋“œ์™€ ๊ฐ™์€ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์ •๋ณด๋Š” documentation๋ฅผ ์ฐพ์•„๋ณด์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋งŒ์•ฝ fetch๋‚˜ asyncData๋ฅผ mixin ๋‚ด์— ์ •์˜ํ•˜๊ณ  page ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ์ •์˜ํ•˜๋Š” ๊ฒฝ์šฐ, mixin ํ•จ์ˆ˜๋Š” ๋ฎ์—ฌ์”Œ์–ด์ง‘๋‹ˆ๋‹ค.

The fetch hook

Nuxt 2.12 ์ด์ „์˜ page ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ๋™์ž‘๋˜๊ณ  ์ปดํฌ๋„ŒํŠธ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” fetch ํ›…๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋งŒ์•ฝ fetch()๊ฐ€ context argument๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ๊ทธ๊ฒƒ์€ ๋ ˆ๊ฑฐ์‹œ fetch ์œผ๋กœ ์ทจ๊ธ‰๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ deprecated ๋˜์—ˆ์œผ๋ฉฐ asyncData ๋˜๋Š” anonymouse middleware๋กœ ๊ต์ฒดํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

fetch๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒ์„ฑ๋œ ํ›„ server-side ๋ Œ๋”๋ง ๋™์•ˆ client์—์„œ ๋ถˆ๋ ค์ง‘๋‹ˆ๋‹ค. fetch ํ›…์€ promise(๋ช…์‹œ์ , ๋˜๋Š” async/await๋ฅผ ์‚ฌ์šฉํ•œ ์•”์‹œ์ )๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์„œ๋ฒ„์—์„œ๋Š” ์ดˆ๊ธฐ ํŽ˜์ด์ง€ ๋ Œ๋” ์ „
  • ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ mounted ๋˜๊ณ  ์ผ์ • ์‹œ๊ฐ„ ๊ฒฝ๊ณผ

static hosting์—์„œ, fetch ํ›…์€ page ์ƒ์„ฑ ์ค‘์—๋งŒ ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฒฐ๊ณผ๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์บ์‹ฑ๋ฉ๋‹ˆ๋‹ค. ์บ์‹œ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด ์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ๊ณ ์œ ํ•œ fetchKey๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Usage

Fetching data

fetch ํ›… ๋‚ด์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ this ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์†์„ฑ์„ ์ˆ˜์ •ํ•˜๋ ค๋ฉด data() ์•ˆ์— ๋ฏธ๋ฆฌ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  fetch์—์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋Š” data์—์„œ ์„ ์–ธํ•œ ์†์„ฑ์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Changing fetch behavior

fetchOnServer: Boolean ๋˜๋Š” Function (default: true) ํŽ˜์ด์ง€๊ฐ€ server-rendering ๋•Œ fetch๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

fetchKey: String ๋˜๋Š” Function (์ปดํฌ๋„ŒํŠธ scope ID ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ช…์ด ๊ธฐ๋ณธ) ์ปดํฌ๋„ŒํŠธ์˜ fetch ๊ฒฐ๊ณผ๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋Š” key (๋˜๋Š” ๊ณ ์œ  ํ‚ค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜) (Nuxt 2.15+ ์‚ฌ์šฉ ๊ฐ€๋Šฅ). ํŽ˜์ด์ง€๊ฐ€ server-rendered ๋  ๋•Œ ์ด ํ‚ค๋Š” ์„œ๋ฒ„ ์ธก ๊ฒฐ๊ณผ๋ฅผ fetch() ํด๋ผ์ด์–ธํŠธ ์ธก ๊ตฌ์„ฑ ์š”์†Œ ๋ฐ์ดํ„ฐ ์— ๋งคํ•‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์›๋ณธ PR ์—์„œ ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

fetchDelay: Integer (default: 200), ์ตœ์†Œ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์ดˆ๋‹จ์œ„๋กœ ์„ค์ •ํ•œ๋‹ค. (๋น ๋ฅธ ๊นœ๋นก์ž„์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด)

fetchOnServer๋Š” ์ฐธ/๊ฑฐ์ง“, fetch๋Š” clinet-side์—์„œ๋งŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ณ , server-side ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” $fetchState.pending๋Š” true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

export default {
  data: () => ({
    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')
  }
}

Accessing the fetch state

fetch ํ›…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์„ฑ์„ ๊ฐ€์ง„ ์ปดํฌ๋„ŒํŠธ์˜ ๋ ˆ๋ฒจ์—์„œ this.$fetchState์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • pending์€ clinet-side ์—์„œ fetch๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ์„ ๋•Œ Boolean ๊ฐ’์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • error๋Š” fetch ํ›…์œผ๋กœ๋ถ€ํ„ฐ null์ด๊ฑฐ๋‚˜ Error๋ฅผ ๋ฐ˜ํ™˜ํ•œ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.
  • timestamp๋Š” ๋งˆ์ง€๋ง‰ fetch๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. keep-alive๋ฅผ ์‚ฌ์šฉํ•ด ์บ์‹ฑํ•˜๋Š”๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ถ”๊ฐ€๋กœ Nuxt์—์„œ ๋ถˆ๋ ค์ง€๋Š” fetch ์™ธ์—๋„, ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ this.$fetch()๋ฅผ ํ†ตํ•ด fetch๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. (e.g. ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฆฌ๋กœ๋“œ)

<template>
  <div>
    <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>
  </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 ํ›… ๋ง๊ณ ๋„ this.$nuxt.context๋ฅผ ์‚ฌ์šฉํ•ด Nuxt context ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

Listening to query string changes

fetch ํ›…์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฟผ๋ฆฌ ์ŠคํŠธ๋ง์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ฟผ๋ฆฌ ๋ณ€๊ฒฝ์„ ๊ฐ์‹œํ•˜๋ ค๋ฉด $route.query๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผํ•œ๋‹ค.

export default {
  watch: {
    '$route.query': '$fetch'
  },
  async fetch() {
    // Called also on query changes
  }
}

Caching

<nuxt />์™€ <nuxt-child />์ปดํฌ๋„ŒํŠธ์— keep-alive ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋ฏธ ๋ฐฉ๋ฌธํ•œ ํŽ˜์ด์ง€์—์„œ ํ˜ธ์ถœํ•œ fetch๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<template>
  <nuxt keep-alive />
</template>

๋˜ํ•œ <nuxt> ์ปดํฌ๋„ŒํŠธ์— keep-alive-props ๋“ฑ์˜ props ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<nuxt keep-alive :keep-alive-props="{ max: 10 }" />

10๊ฐœ์˜ ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ๋งŒ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

Error handling

๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ์ •์ƒ์ ์ธ Nuxt ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. fetch() ๋‚ด์˜ Nuxt redirect๋‚˜ error ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋Œ€์‹ ์— ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ $fetchState.error๋ฅผ ์‚ฌ์šฉํ•ด ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘ error๊ฐ€ ์žˆ๋‹ค๋ฉด $fetchState.error๋ฅผ ํ™•์ธํ•ด ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

<template>
  <div>
    <p v-if="$fetchState.pending">Loading....</p>
    <p v-else-if="$fetchState.error">Error while fetching mountains</p>
    <ul v-else>
      <li v-for="(mountain, index) in mountains" :key="index">
        {{ mountain.title }}
      </li>
    </ul>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        mountains: []
      }
    },
    async fetch() {
      this.mountains = await fetch(
        'https://api.nuxtjs.dev/mountains'
      ).then(res => res.json())
    }
  }
</script>

Using activated hook

Nuxt๋Š” ๋งˆ์ง€๋ง‰ fetch ํ˜ธ์ถœ(ssr ํฌํ•จ)์„ this.$fetchState.timestamp์— ๋‹ด์•„๋‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. activatedํ›…์ด ํฌํ•จ๋œ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ fetch์˜ 30์ดˆ ์บ์‹œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<template> ... </template>

<script>
  export default {
    data() {
      return {
        posts: []
      }
    },
    activated() {
      // Call fetch again if last fetch more than 30 sec ago
      if (this.$fetchState.timestamp <= Date.now() - 30000) {
        this.$fetch()
      }
    },
    async fetch() {
      this.posts = await fetch('https://api.nuxtjs.dev/posts').then(res =>
        res.json()
      )
    }
  }
</script>

๋งˆ์ง€๋ง‰ fetch ํ˜ธ์ถœ์ด 30์ดˆ ์ „์ธ ๊ฒฝ์šฐ ๋™์ผ ํŽ˜์ด์ง€๋กœ์˜ ํƒ์ƒ‰์ด ํ˜ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Async Data

asyncData๋Š” pages์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  ํ›… ๋‚ด์—์„œ this์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

asyncData๋Š” ๋ฒ”์šฉ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ๋‹ค๋ฅธ ํ›…์ž…๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ์†์„ฑ ์ •์˜๊ฐ€ ํ•„์š”ํ•œ fetch์™€ ๋‹ฌ๋ฆฌ asyncData๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ๋กœ์ปฌ state์™€ ๋ฐ˜ํ™˜ ๊ฐ’์„ ๋ณ‘ํ•ฉํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ @nuxt/http ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

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

fetch์™€ ๋‹ฌ๋ฆฌ asyncData ํ›…์œผ๋กœ ๋ฆฌํ„ด๋œ promise๋Š” route ์ „ํ™˜ ์ค‘์— ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ client-side ์ „ํ™˜ ์ค‘์—๋Š” โ€œloading placeholderโ€๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š”๊ฑธ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. (loading bar๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋กœ๋“œ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Œ). ๋Œ€์‹  Nuxt๋Š” ๋‹ค์Œ ํŽ˜์ด์ง€๋‚˜ ์—๋Ÿฌ ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์ „์— asyncData ํ›…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

์ด ํ›…์€ page-level ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. fetch์™€๋Š” ๋‹ค๋ฅด๊ฒŒ asyncData๋Š” ์ปดํฌ๋„ŒํŠธ์˜ this์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€์‹ , argument๋กœ the context ๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•ด ๋ช‡๋ช‡์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ณ  Nuxt๋Š” ์ž๋™์œผ๋กœ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฐ์ดํ„ฐ์™€ ๋ฆฌํ„ด ๊ฐ์ฒด๋ฅผ ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์‹œ๋Š”, API๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๊ถŒ์žฅํ•˜๋Š” @nuxt/http ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

Async data in components?

์ปดํฌ๋„ŒํŠธ๋Š” asyncData๋ฅผ ๊ฐ–๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ์ง์ ‘ server-side ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ œํ•œ์„ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•ด 3๊ฐ€์ง€ ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. Nuxt 2.12 ์ดํ›„ ๋ฒ„์ „์—์„œ๋ถ€ํ„ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ƒˆ๋กœ์šด fetch hook ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  2. mounted ํ›… ์•ˆ์—์„œ API ํ˜ธ์ถœ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  loaded ์‹œ์ ์— data ์†์„ฑ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ : server side rendering ์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  3. page ์ปดํฌ๋„ŒํŠธ์˜ asyncData ์•ˆ์—์„œ API๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ data๋ฅผ props๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. Server rendering์€ ์ž˜ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

๋‹จ์ : ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋”ฉํ•˜๊ธฐ ์œ„ํ•ด page์˜ asyncData๋Š” ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Listening to query changes

๊ธฐ๋ณธ์ ์œผ๋กœ asyncData๋Š” query string ๋ณ€๊ฒฝ์— ์˜ํ•ด ํ˜ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. page ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ์ฒ˜๋Ÿผ ๋™์ž‘์„ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด page ์ปดํฌ๋„ŒํŠธ์˜ watchQuery ์†์„ฑ์œผ๋กœ ๋ฐ›๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.