Ch 01. useFetch와 useAsyncData
Nuxt 3에서 데이터를 가져오는 방법은 크게 두 가지입니다. useFetch와 useAsyncData입니다. 둘 다 서버와 클라이언트 양쪽에서 안전하게 동작하고, SSR 과정에서 중복 요청을 방지해 줍니다. 차이점은 "얼마나 직접 제어하고 싶은가"에 달려 있습니다.
useFetch — URL 한 줄로 끝내기
useFetch는 URL을 넘기면 나머지를 Nuxt가 처리해 주는 단축어입니다. 내부적으로 useAsyncData + $fetch의 조합으로 구현되어 있습니다.
// pages/posts/index.vueconst { data: posts, pending, error, refresh } = await useFetch('/api/posts')
반환값은 다음 네 가지입니다.
data— 응답 데이터 (Ref)pending— 로딩 여부 (Ref<boolean>)error— 오류 객체 (Ref)refresh/execute— 수동 재요청 함수
TypeScript를 사용한다면 제네릭으로 응답 타입을 명시할 수 있습니다.
interface Post { id: number title: string body: string}const { data } = await useFetch<Post[]>('/api/posts')// data.value는 Post[] | null 타입으로 추론됩니다
useAsyncData — 비동기 로직을 직접 감싸기
URL이 아니라 커스텀 비동기 로직이 필요할 때는 useAsyncData를 사용합니다. 첫 번째 인자는 캐시 키, 두 번째 인자는 비동기 함수입니다.
// pages/users/[id].vueconst route = useRoute()const { data: user } = await useAsyncData('user-detail', async () => { const res = await $fetch(`/api/users/${route.params.id}`) return res})
같은 캐시 키를 가진 요청은 SSR 과정에서 한 번만 실행되고 결과가 클라이언트로 전달됩니다.
주요 옵션
두 함수 모두 세 번째 인자(또는 두 번째)로 옵션 객체를 받습니다.
| 옵션 | 설명 |
|---|---|
lazy: true |
SSR을 건너뛰고 클라이언트에서 로드합니다. pending이 true인 동안 스켈레톤을 보여줄 때 유용합니다. |
server: false |
서버에서 실행하지 않습니다. 브라우저 전용 API를 사용할 때 씁니다. |
transform |
응답 데이터를 가공한 뒤 저장합니다. |
pick |
응답에서 필요한 필드만 추출합니다. 전송 크기를 줄여 줍니다. |
const { data } = await useFetch('/api/articles', { transform: (res) => res.articles, pick: ['id', 'title', 'publishedAt']})
refresh와 execute로 수동 재요청하기
refresh()는 기존 캐시를 무효화하고 즉시 재요청합니다. execute()는 최초 호출 전까지 실행을 미루고 싶을 때 immediate: false 옵션과 함께 씁니다.
const { data, refresh } = await useFetch('/api/notifications')// 버튼 클릭 시 재요청function onClickRefresh() { refresh()}
useFetch는 단순하고 useAsyncData는 유연합니다. URL 하나로 충분하다면 useFetch를, 여러 API를 조합하거나 로직이 복잡하다면 useAsyncData를 선택하면 됩니다.