우선 fetch와 $fetch를 사용한 각각의 예시코드부터 확인해보자.
fetch 사용 예시
import { useAsyncData } from 'nuxt3'
export default {
setup() {
const { data, pending, error, refresh } = useAsyncData('user', () =>
fetch('http://localhost:8080/api/user/1')
.then(response => response.json())
)
return { data, pending, error, refresh }
}
}
$fetch 사용 예시
const { data, pending, error, refresh } = await useAsyncData(
'mountains', // key
() => $fetch('https://api.nuxtjs.dev/mountains')
)
fetch, $fetch 차이점
위의 코드를 살펴보면 둘 다 useAsyncData의 두 번째 매개변수로 함수를 전달하고 있다. 이 함수는 데이터를 가져오는 데 필요한 비동기 작업을 수행하며, 이 함수가 반환하는 Promise의 결과값이 useAsyncData의 data로 설정된다.
이 중 첫 번째 코드는 fetch 함수를 직접 사용하여 HTTP 요청을 보낸 후 .then 메서드를 사용하여 응답을 처리하는 내용이다. 그리고 응답값을 JSON 형식으로 파싱하기 위해 response.json()을 직접 호출하고있다. response.json()은 Fetch API에서 제공하는 메서드로, 응답값을 JSON 형식으로 파싱한다.
두 번째 코드에서 $fetch를 사용하면 이 메서드가 자동으로 적용된다. $fetch는 내부적으로 fetch를 사용하되, 추가적인 처리를 수행한다. 그 중 하나가 바로 응답을 자동으로 JSON 형식으로 파싱하는것이기 때문에 $fetch를 사용하면 response.json()을 호출하지 않아도 된다.
fetch에 대하여
fetch는 웹 브라우저와 Node.js에서 모두 사용할 수 있는, HTTP 요청을 보내는 데 사용되는 함수이 함수를 통해 서버에 데이터를 요청하거나 서버에 데이터 전송 가능
fetch함수는 Promise를 반환. 따라서async/await구문을 사용하여 비동기적으로 데이터를 처리할 수 있다.
$fetch에 대하여
“Nuxt3”에서 제공하는 전역 함수로, 내부적으로
fetch를 사용하여 HTTP 요청을 보내는 함수내부적으로 에러 처리 등이 추가적으로 수행되므로, 좀 더 편리하게 HTTP 요청 가능
$fetch를 사용하게 되면 해당 api 호출을 클라이언트가 아니라, nuxt의 웹서버에서 직접 api 호출을 하고, 서버사이드 렌더링 후 그 결과를 클라이언트에게 보여준다. 따라서, 클라이언트에서 직접 API 호출했을 때와 달리 더 빠른 페이지 로딩 사용자 경험을 제공할 수 있다.
기존 fetch 방식 혹은 api 호출 방식 :
Nuxt 웹서버가 클라이언트에게 페이지 제공 → 브라우저에서 API 호출 → API 결과로 CSR
$fetch 사용 방식 :
Nuxt 웹서버가 직접 API 호출 → API 결과값으로 SSR된 페이지를 클라이언트에 제공
컴포넌트에서 $fetch를 useAsyncData로 래핑하지 않고 사용하면 $fetch가 서버에서 클라이언트로 ‘상태’를 전송하지 않기 때문에 처음에는 “서버”에서, 그리고 하이드레이션 중에 “클라이언트 측”에서 데이터를 두 번 가져오게 된다. 즉, 서버와 클라이언트 양쪽 모두에서 fetch가 실행된다.
이러한 이유로, 컴포넌트에서 ‘$fetch‘를 사용할 때는 반드시 ‘useAsyncData‘로 감싸주어야 한다. ‘useAsyncData‘를 사용하면 중복 호출을 방지할 수 있다.
<script setup lang="ts">
// SSR 동안 데이터는 서버에서 한 번, 클라이언트에서 한 번, 총 두 번 가져옵니다.
const dataTwice = await $fetch('/api/item')
// SSR 중에는 데이터가 서버 측에서만 가져와 클라이언트로 전송됩니다.
const { data } = await useAsyncData('item', () => $fetch('/api/item'))
// useAsyncData + $fetch의 바로가기로 Fetch를 사용할 수도 있습니다.
const { data } = await useFetch('/api/item')
</script>