useFetch(), $fetch(), useAsyncData() 비교 요약
- $fetch는 사용자의 상호작용(POST, PUT, DELETE 등)에 따른 요청 시 사용합니다.
- 페이지 초기 렌더링에 필요한 데이터 요청 시에는 useAsyncData 또는 useFetch를 사용합니다.
- 동적 파라미터가 필요한 복잡한 로직에서는 useAsyncData 사용을 권장합니다.
- 서버에서 호출 시 쿠키나 로컬스토리지 사용이 제한되므로, Nuxt의 useState나 Pinia를 활용합니다.
- 전역적으로 요청 헤더 등을 커스터마이징하려면 $fetch를 확장하여 사용할 수 있습니다.
기능 | useFetch() | $fetch | useAsyncData() |
서버 사이드 렌더링(SSR) | ✔️ | ✔️ | ✔️ |
자동 상태 관리 | ✔️ | ❌ | ✔️ |
캐싱 및 중복 호출 방지 | ✔️ | ❌ | ✔️ |
Suspense 호환 | ✔️ | ❌ | ✔️ |
복잡한 데이터 로딩 전략 지원 | ❌ (단순 사용에 적합) | ❌ | ✔️ (복잡한 전략에 적합) |
데이터 요청 컴포저블이 필요성
Nuxt와 같은 프레임워크에서 클라이언트와 서버 양쪽에서 데이터를 요청할 때 몇 가지 중요한 문제들이 발생합니다. Nuxt는 이러한 문제들을 해결하기 위해 특별한 컴포저블을 제공합니다.
주요 문제
- 네트워크 호출 중복 방지: 서버에서 이미 데이터를 가져왔음에도 클라이언트에서 다시 요청하는 불필요한 중복 호출을 방지해야 합니다.
- 페이로드 관리: 서버에서 가져온 데이터를 클라이언트로 효율적으로 전달해야 합니다.
- Suspense 활용: 데이터가 준비될 때까지 렌더링을 보류하여 사용자에게 일관된 경험을 제공해야 합니다.
페이로드(Payload)
Nuxt는 서버에서 가져온 데이터를 클라이언트에 넘겨줄 때 useNuxtApp().payload 객체를 활용하여 캐싱합니다. 이를 통해 중복된 요청을 방지합니다.
Suspense
데이터 요청이 완료될 때까지 Vue의 <Suspense> 컴포넌트를 이용해 렌더링을 지연시켜 부드러운 페이지 전환을 제공합니다.
$fetch()
$fetch는 Nuxt 3의 기본 데이터 요청 메서드로, 내부적으로는 Fetch API 기반의 ofetch 라이브러리를 사용합니다. Axios 대신 $fetch를 사용하는 이유는 Axios가 구형 XMLHttpRequest 기반의 API를 사용하기 때문입니다. 반면 $fetch는 보다 현대적인 Fetch API를 기반으로 Node.js 및 브라우저 환경에서 모두 일관되게 작동합니다.
기본 사용법
<script setup lang="ts">
const username = ref('');
const result = ref(null);
async function submitUser() {
result.value = await $fetch('/api/users', {
method: 'POST',
body: { username: username.value }
});
}
</script>
<template>
<input v-model="username" placeholder="사용자 이름 입력" />
<button @click="submitUser">사용자 등록</button>
<div>{{ result }}</div>
</template>
주요 기능
- Node.js 환경에서는 node-fetch-native, 브라우저 환경에서는 기본 fetch API 사용
- 자동 JSON 파싱, 인터셉터, 자동 재시도 기능 제공
- 클라이언트 사이드에서의 사용 권장 (서버 렌더링 시 중복 호출 방지 불가)
- 이벤트 핸들러나 클라이언트 측 로직에서 주로 사용하거나, useAsyncData와 함께 사용
useAsyncData()
useAsyncData는 데이터를 보다 세부적으로 관리할 수 있게 해주는 컴포저블입니다.
중요한 예외 사항은 이 메서드가 setup function, plugin, 또는 route middleware에서만 사용 가능하다는 점입니다.
기본 사용법
template>
<button @click="refresh">useAsyncData 테스트</button>
<div>결과: {{ data }}</div>
</template>
<script setup lang="ts">
const { data, refresh } = await useAsyncData<number>("useAsyncDataTest",
() => $fetch("/api/temp"));
</script>
주요 파라미터
- key: 데이터 중복 호출 방지를 위한 유니크한 키. 지정하지 않으면 자동 생성됩니다. 자동 생성된 키는 파일과 라인을 기준으로만 생성되므로, 사용자 정의 컴포저블을 작성할 때는 항상 명시적으로 키를 정의하여 원치 않는 동작을 방지해야 합니다.
- handler: 비동기 데이터 요청을 처리할 함수
- options:
- lazy: 데이터를 기다리지 않고 렌더링 (기본값: false, 변경시 SEO에 영향을 미침)
- default: 데이터 로딩 전 기본값 설정
- server: 서버 측에서 실행 여부 (기본값: true, 변경시 SEO에 영향을 미침)
- transform: 데이터 결과 변형
- pick: 특정 키의 데이터만 반환
- watch: 특정 값 변경 시 자동 재호출
- immediate: 초기 로딩 시 자동 호출 여부 (기본값: true, 변경시 SEO에 영향을 미침)
반환 값
- data: 결과 데이터(ref 객체)
- pending: 요청 중인지 여부(boolean)
- refresh/execute: 데이터 재요청
- error: 에러 발생 시 오류 객체
- status: 비동기 메서드의 상태 (idle, pending, success, error)
중복 호출 방지 메커니즘
useAsyncData는 서버에서 실행 후 결과를 클라이언트로 넘겨주며, 클라이언트에서 다시 실행될 때 캐싱된 데이터를 활용하여 중복 호출을 방지합니다.
병렬 호출 처리
useAsyncData를 사용하면 여러 개의 병렬 요청을 처리하여 응답을 하나로 묶을 수도 있습니다.
const { data, pending } = await useAsyncData('cart-discounts', async () => {
const [coupons, offers] = await Promise.all([
$fetch('/cart/coupons'),
$fetch('/cart/offers')
]);
return { coupons, offers };
});
useFetch()
useFetch()는 가장 간편한 데이터 요청 컴포저블이며 내부적으로 useAsyncData와 $fetch를 결합하여 데이터를 가져옵니다.
useAsyncData와 마찬가지로 전역 메서드이고 setup function, plugin, 또는 route middleware 에서만 사용이 가능합니다.
파라미터
- useAsyncData의 handler 를 제외한 모든 파라미터와 $fetch 의 options 파라미터를 포함한다.
반환
- useAsyncData 와 동일
기본 사용법
<script setup lang="ts">
const { data, pending, error, refresh } = await useFetch('/api/data', {key: "test"});
</script>
<template>
<div v-if="pending">로딩 중...</div>
<div v-else-if="error">에러 발생: {{ error }}</div>
<div v-else>데이터: {{ data }}</div>
</template>
⚖️ useAsyncData vs useFetch의 실행 컨텍스트 차이
두 메서드의 가장 큰 차이는 실행 컨텍스트(context)입니다.
- useAsyncData는 두번째 매개변수로 콜백 함수를 사용하여 항상 최신 값을 참조합니다.
- useFetch는 두번째 매개변수로 초기 실행 시 전달된 객체만을 사용하며 상태 변화에 따라 값이 동적으로 바뀌지 않습니다.
- Nuxt3 진영에서는 해당 현상을 freezing 이라고 부릅니다. https://github.com/nuxt/nuxt/issues/15359#issuecomment-1397377561
useFetch is not using new value from reactive object · Issue #15359 · nuxt/nuxt
Environment Operating System: Darwin Node Version: v18.11.0 Nuxt Version: 3.0.0-rc.13 Nitro Version: 0.6.1 Package Manager: npm@8.19.2 Builder: vite User Config: ssr, runtimeConfig, nitro, modules ...
github.com
'Javascript > NuxtJS' 카테고리의 다른 글
[Nuxt3] 스토리지: vueuse (0) | 2025.03.15 |
---|---|
[Nuxt3] 헬스 체크 (1) | 2025.03.15 |
[Nuxt3] Nitro (0) | 2025.03.15 |
[Nuxt3] Server (0) | 2025.03.15 |
[Nuxt3] storeToRefs() (0) | 2025.03.12 |