코드/Nuxt3

[Nuxt] useFetch 에 await 가 필요할까

Yeah-Panda 2024. 12. 28. 15:09

useFetch 를 사용하다보면 누군가는 await 를 선언해서 사용하고 누군가는 그대로 사용하는 것을 볼수 있습니다.

SSR (universal)로 페이지를 렌더링한다는 전제하에 페이지를 리프레시해보면 별다른 차이는 느낄수 없습니다.

다음과 같은 코드가 있다고 가정합니다.

// index.vue
<script lang="ts" setup>
const {data: pokemons} = await useFetch('/api/hello')
</script>

<template>
  <div>
    <h1>Poketmons</h1>
    <ul>
      <li v-for="pokenmon in pokemons">
        <span>{{ pokenmon.pokemon }}</span>
        <img :src="pokenmon.image_url" alt="pokenmon.name" />
      </li>
    </ul>
    <button @click="onClickPokemon()">Refresh</button>
  </div>
</template>

// about.vue
<template>
<h1> About </h1>
</template>

// Navie.vue
<script lang="ts" setup>
</script>
<template>
  <NuxtLink to="/">Home</NuxtLink>
  <NuxtLink to="/about">About</NuxtLink>
</template>

// server/api/hello.ts
function sleep (ms: number): Promise<void> {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms);
  })
}
export default defineEventHandler(async () => {
  await sleep(2000);
  const result = await $fetch('https://dummyapi.online/api/pokemon');
  return result;
})

server/api/hello.ts 는 약간의 제어를 위해 api endpoint 를 변경한 내용입니다.

꼭 위와 같은 형태일 필요는 없으며 dummyapi.online/api/pokemon 을 바로 호출하여도 동일한 결과가 나옵니다.

home 과 about 페이지가 있으며 home 에는 api 호출후 응답으로 포켓몬 목록이 노출됩니다.

about 로 라우트 이동한 다음 페이지를 리프레시, 그 다음 home  을 눌러보면 2초후 모든 응답이 완료되고 나서야 route navigate 가 발생합니다. 그 동안은 about.vue 페이지에 머무릅니다. (blocking navigation)

await 를 삭제 해보면 home 페이지가 바로 노출되고 api 응답이 완료된 2초후 포켓몬 목록이 노출되는 것을 볼수 있습니다  (non-blocking navigation)

이처럼 await 의 여부에 따른 동작 차이는 SPA 에서 페이지간 이동시 발생합니다.

전체 페이지 갱신시에는 서버가 모든 api 호출을 끝내고 화면을 응답하게 됨으로 await 여부에 따른 동작 차이는 없습니다.

이 부분을 잘 이해하여서 사용하시면 됩니다.

 

그리고 조금 더 명시적인 방법으로 non-blocking navigation 구현할수 있습니다.

const {data: pokemons} = useFetch('/api/hello', {
  lazy: true
});

페이지 이동시 await 가 선언되어 있는 것과 동일하게 동작하는 것을 보실수 있습니다.

어떤 형태로 구현할까는 개발자의 선택입니다.