데이터 통신과 관련한 거의 모든 내용은 "Nuxt-개요 > 데이터 가져오기" 에 담겨있다.
이번 장에서 간단하게 실습한 후 위 내용을 참고하면 이해에 더 도움이 될 것이다.
useFetch 컴포저블을 사용하는 것이 적절하지 않은 경우가 있다 (예: CMS 또는 자체적으로 API 통신 레이어를 제공해야 하는 경우). 이 경우 useAsyncData 를 사용하여 호출을 래핑하면서도 컴포저블에서 제공하는 이점을 계속 유지할 수 있다.
앞 장에서 useFetch 컴포저블을 이용한 todos 의 예를 useAsyncData 로 바꿔보자. 데이터를 캐싱하는데 필요한 문자열 키가 필요하다. 키가 주어지지 않으면 파일명과 해당 소스라인으로 자동으로 구성된 키가 할당된다.
/pages/todos.vue
<script setup lang="ts">
// const { data: todos, pending, error, refresh } = await useFetch('https://jsonplaceholder.typicode.com/todos', { method:'get', server: false })
const { data: todos, error, refresh } = await useAsyncData("todos", () =>
$fetch('https://jsonplaceholder.typicode.com/todos', { method:'get' })
)
</script>
<template>
<div>
<table class="min-w-full table-auto bg-blue-950">
<thead>
<tr>
<th class="px-4 py-2">ID</th>
<th class="px-4 py-2">Title</th>
<th class="px-4 py-2">Completed</th>
</tr>
</thead>
<tbody>
<!-- Loop through todosData to populate the table rows -->
<tr v-for="todo in todos">
<td class="border px-4 py-2">{{ todo.id }}</td>
<td class="border px-4 py-2">{{ todo.title }}</td>
<td class="border px-4 py-2">
<!-- Use a checkmark if completed, otherwise a cross -->
<span :class="{ 'text-green-500': todo.completed, 'text-red-500': !todo.completed }">
{{ todo.completed ? '✔' : '❌' }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<style scoped>
</style>
브라우저 소스보기를 보면 결과는 useFetch 를 사용한 것과 동일한 것을 알 수 있다.
클라이언트 측 렌더링도 살펴보자.
/pages/todos.vue
<script setup lang="ts">
// const { data: todos, pending, error, refresh } = await useFetch('https://jsonplaceholder.typicode.com/todos', { method:'get', server: false })
const { data: todos, error, refresh } = await useAsyncData("todos", () =>
$fetch('https://jsonplaceholder.typicode.com/todos', { method:'get'}), {server: false}
)
</script>
...
브라우저 소스보기 결과는 아래와 같다.
브라우저 개발자도구를 보면 클라이언트 측에서 호출되는 것을 확인할 수 있다.
위에서 본 것처럼 useAyncData("key", $fetch(url)) 은 useFetch 와 거의 동일하다.
자신만의 데이터 통신 컴포저블을 만들때는 useAsyncData를 통해서 구현할 수 있음을 알 수 있다.
Promise.all 을 이용해 동시에 데이터를 가져와서 변수에 할당 할 수도 있다.
/pages/todos-users.vue
<script setup lang="ts">
// const { data: todos, pending, error, refresh } = await useFetch('https://jsonplaceholder.typicode.com/todos', { method:'get', server: false })
// const { data: todos, error, refresh } = await useAsyncData("todos", () =>
// $fetch('https://jsonplaceholder.typicode.com/todos', { method:'get'}), {server: false}
// )
//https://jsonplaceholder.typicode.com/users
const { data, pending } = await useAsyncData('todos-users', async () => {
const [todos, users] = await Promise.all(
[$fetch('https://jsonplaceholder.typicode.com/todos', { method:'get'}),
$fetch('https://jsonplaceholder.typicode.com/users', { method:'get'})
])
return {
todos,
users
}
})
</script>
<template>
<div>
<table class="min-w-full table-auto bg-blue-950">
<thead>
<tr>
<th class="px-4 py-2">ID</th>
<th class="px-4 py-2">Title</th>
<th class="px-4 py-2">Completed</th>
</tr>
</thead>
<tbody>
<!-- Loop through todosData to populate the table rows -->
<tr v-for="todo in data.todos">
<td class="border px-4 py-2">{{ todo.id }}</td>
<td class="border px-4 py-2">{{ todo.title }}</td>
<td class="border px-4 py-2">
<!-- Use a checkmark if completed, otherwise a cross -->
<span :class="{ 'text-green-500': todo.completed, 'text-red-500': !todo.completed }">
{{ todo.completed ? '✔' : '❌' }}
</span>
</td>
</tr>
</tbody>
</table>
<table class="min-w-full table-auto bg-green-950">
<thead>
<tr>
<th class="px-4 py-2">ID</th>
<th class="px-4 py-2">Name</th>
<th class="px-4 py-2">Email</th>
</tr>
</thead>
<tbody>
<!-- Loop through todosData to populate the table rows -->
<tr v-for="user in data.users">
<td class="border px-4 py-2">{{ user.id }}</td>
<td class="border px-4 py-2">{{ user.name }}</td>
<td class="border px-4 py-2">{{ user.email }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<style scoped>
</style>
아래와 같이 동시 호출 후 변수 할당이 동작하는 것을 확인할 수 있다.
실습을 통해서 useAsyncData를 통해서 useFetch 의 기능을 대신하거나, 더 확장할 수 있음을 확인했다. 이 외 useLazyFetch, useLazyAsyncData 는 기본 컴포저블에 lazy 옵션만 추가하여 별도의 컴포저블로 정의한 컴포저블이다.
$fetch 는 unjs 의 ofetch 를 Nuxt 에 내장한 유틸리티 함수이다. ofetch 는 순수 자바스크립트 fetch 함수를 확장한 라이브러리 이다. 주요 특징은 다음과 같다.
- 파싱응답
- JSON Body
- 오류처리 : await ofetch("url").catch(err);
- 자동 재시도
- 타임아웃관리
- 제네릭 지원 : await<Await> ofetch("url");
- baseURL지원 : await ofetch("url", { baseURL});
- 쿼리검색 매개변수 지원
- 인터셉터
자신만의 통신 함수 혹은 모듈을 만든다면 ofetch 를 시작점으로 하는 것도 좋은 방법인 것 같다. 예를 들어 파일 업로드/다운로드 기능을 시각적 요소를 갖고 있는 별도의 커스텀 컴포넌트로 만든다면 컴포넌트에 내장된 통신 함수는 ofetch 로 하면 좋을 것이다.
'Nuxt 개발 가이드 > 04. Data fetching' 카테고리의 다른 글
3. 풀스택을 위한 API 서버 구축 (0) | 2024.01.14 |
---|---|
1. useFetch (0) | 2024.01.13 |