✔️ $fetch
- nuxt 는 기본적으로 ofetch 라이브러리를 포함하고 있다.
- useFetch 뒤에서 실행된다.
- 기본적으로 client side 에서만 사용한다.
- 서버와 클라이언트 환경에서의 중복 호출 문제
- Top level await 를 통한 SSR 시 fetch 를 통해 data 를 가져오면 안 된다
<script setup lang="ts">
// During SSR data is fetched twice, once on the server and once on the client.
const dataTwice = await $fetch('/api/item')
// During SSR data is fetched only on the server side and transferred to the client.
const { data } = await useAsyncData('item', () => $fetch('/api/item'))
// You can also useFetch as shortcut of useAsyncData + $fetch
const { data } = await useFetch('/api/item')
</script>
$fetch 파라미터
- url : 요청 url
- options :
- method : 요청 메서드 설정
- query : URL 에 붙일 query params. ufo 라이브러리를 통해 만들어진다.
- params : query 와 똑같다.
- body : 요청 body
- headers : 요청 headers
- baseURL : 요청 baseURL
✔️ useAsyncData
- 일반적으로 GET 방식의 통신을 위해 사용된다.
- setup function, plugin, 또는 route middleware 에서만 사용이 가능하다.
const { data, pending, error, refresh } = await useAsyncData(
'mountains',
() => $fetch('<<a href=https://api.nuxtjs.dev/mountains>https://api.nuxtjs.dev/mountains</a>>')
)
useAsyncData 파라미터
- key : 해당 비동기 메서드의 중복 불가한 key 값을 설정한다. 해당 key 를 통해 server 와 client 의 두 번의 호출을 방지한다.
- handler : 실행할 비동기 함수
- options :
- lazy : useAsyncData 의 결과를 기다리지 않고 먼저 화면을 렌더링한다. (default - false)
- default : 함수를 통해 비동기 함수가 완료되기 전에 보여줄 값을 세팅할 수 있다.
- server : useAsyncData 실행을 server side 에서 실행할 여부 (default - true)
- transform : 함수를 통해 비동기 함수 실행 결과를 변형시킨다.
- pick : 비동기 함수 실행결과에서 특정 key 값을 가진 data 만 return 시킨다.
- watch : 특정 값이 변경될때 자동으로 useAsyncData 를 재호출한다.
- immediate : useAsyncData 를 페이지 진입 시 바로 호출한다. (default - true)
- boolean 값을 넘기는 lazy, server, immediate 의 default 값을 변경시키면 Server Side 에서 data 에 대한 정보를 모르므로 SEO 에 useAsyncData 의 결과값은 포함되지 않는다고 한다.
useAsyncData 의 Return Value
- data : 비동기 함수의 결과가 담긴다.
- 반응성이 있는 ref 객체이다.
- pending : 비동기 함수가 실행 중인지 여부를 boolean 으로 반환한다.
- refresh, execute, error, status
useAsyncData 를 사용했을 때 API 중복 호출이 일어나지 않는 원리
- useAsyncData 의 경우 script setup 안에서 Top level await 를 사용해도 중복 호출이 일어나지 않는다. 중복 호출을 막는 핵심은 key!
- 페이지 첫 진입 시 SSR 을 통해 HTML 을 먼저 만들어내는데 useAsyncData 가 실행될 경우 Server Side 에서 handler (비동기 함수) 를 먼저 실행한다.
- 실행된 결과 값을 캐싱하여 Client Side 에 넘기고, hydration 이 일어나 Client Side 에서 useAsyncData 를 다시 실행하면 먼저 캐싱 Object 를 먼저 검사해 해당 key 값의 value 가 있으면 handler 를 호출 하지 않고 그 value 를 사용한다.
- hydration : HTML 코드와 JS 코드를 서로 매칭 시켜 동적인 웹 사이트를 브라우저에 렌더링 하는 기술
- Server Side 단에서 먼저 정적 페이지를 렌더링 하고, JS 파일들도 번들링한 후에 둘 다 Client Side 로 보내주는 것
✔️ useFetch
- 일반적으로 POST 방식의 통신을 위해 사용된다.
- useAsyncData 를 좀 더 간결하게 쓰기 위한 메서드이다.
- 마찬가지로 전역 메서드이고 useAsyncData 가 내부적으로 사용된다.
- setup function, plugin, 또는 route middleware 에서만 사용이 가능하다.
<script setup>
const { data, pending, error, refresh } = await useFetch('/api/modules', {
pick: ['title']
})
</script>
useFetch 의 파라미터
- key : 해당 비동기 메서드의 중복 불가한 key 값을 설정한다. 해당 key 를 통해 server 와 client 의 두 번의 호출을 방지한다.
- method : 요청 메서드 설정
- query : URL 에 붙일 query params. ufo 라이브러리를 통해 만들어진다.
- params : query 와 똑같다.
- body : 요청 body
- headers : 요청 headers
- baseURL : 요청 baseURLoptions :
- lazy : useAsyncData 의 결과를 기다리지 않고 먼저 화면을 렌더링한다. (default - false)
- default : 함수를 통해 비동기 함수가 완료되기 전에 보여줄 값을 세팅할 수 있다.
- server : useAsyncData 실행을 server side 에서 실행할 여부 (default - true)
- transform : 함수를 통해 비동기 함수 실행 결과를 변형시킨다.
- pick : 비동기 함수 실행결과에서 특정 key 값을 가진 data 만 return 시킨다.
- watch : 특정 값이 변경될때 자동으로 useAsyncData 를 재호출한다.
- immediate : useAsyncData 를 페이지 진입 시 바로 호출한다. (default - true)
useAsyncData 의 Return Value
- data : 비동기 함수의 결과가 담긴다.
- 반응성이 있는 ref 객체이다.
- pending : 비동기 함수가 실행 중인지 여부를 boolean 으로 반환한다.
- refresh, execute, error, status
- useFetch 도 useAsyncData 와 같은 캐싱 시스템으로 Top level await 를 사용하여도 중복 호출을 막아준다.
useAsyncData 와 useFetch 의 차이점???
- 여기까진 useFetch 가 useAsyncData 를 포함한 정도, 상위 버전 정도라고 생각했다.
- 하지만 몇 가지 차이가 있는데 그 중 가장 큰 차이는 실행 context 의 차이라고 한다.
- 단순한 호출은 항상 같은 결과를 내지만 dynamic 하게 호출 url 이 바뀐다거나 요청 body 의 값이 바뀌는 코드는 어떨까?
- useAsyncData 는 page 값이 바뀌면서 url 의 params 도 맞춰서 변경된다.
- useFetch 는 page 의 값이 바뀌어도 params 는 바뀌지 않는다.
- useAsyncData 의 refresh 함수가 호출될 때에는 콜백 함수가 호출되고 해당 콜백 함수 실행 시점에 외부 값들을 참조한다.
- useFetch 의 경우는 초기 호출 시 객체로 넘기기 때문에 refresh 호출 시에 항상 해당 객체만을 이용해서 호출한다. 그래서 useFetch params 의 값은 변경되지 않는다.
- Nuxt3 는 해당 현상을 freezing 이라고 부른다 한다.
GET 예제 code
const {data: contents} = await useFetch('contents api url')
POST 예제 code (검색 기능)
const router = useRouter()
const route = useRoute()
onMounted(() => {
searchValue.value = route.query.search
})
//검색값
const searchValue = ref()
const result = ref();
const searchValueHandler = (value) => {
searchValue.value = value
}
//검색
const search = async () => {
const {data} = await useFetch('search api url', {
method:'POST',
headers:{
'Content-Type':'application/json',
authorization : 'token',
},
body: { "word" : searchValue.value },
});
result.value = data;
}
🚨 API 호출하면서 삽질한 부분
- 먼저 api 호출 구조에서 헤맸다. 제공 받은 api 구조를 이해하지 못하고 무작정 호출하고자 했던 실수였다. body 에 잘 담아 보내주기!
- 두 번째는 console.log 했을 때나 개발자 도구 preview 상에서도 검색 값이 api 에서 잘 걸러 주는 걸 확인했는데 컴포넌트에 값이 전달되지 않아서 페이지 상에서 빈 값만 호출됐다.
- 알고 보니! 애먼 searchValue 에서 값을 찾고 있어서 “스트레칭” 을 검색하면 스 하나, 트 하나, 레 하나, 칭 하나로 인식해서 컴포넌트가 불러지고 있었다. 검색값 글자 하나 하나가 배열 값으로 들어갔던 것…
- const result = ref(); 해서 result 를 따로 만들어주고 result.value = data; 이렇게 한 번 덧씌워준 후 result 를 불러오는 방식으로 일단 해결했다.
- 전체적인 api 호출 구조를 모르는 바보 이슈로,,, 일어난 일인 것 같다! 관련하여 더 연습하고 공부해서 더 깔끔하게 값 담아주고… 보내주고,,. 불러오고 하고 싶다…
- 나는 Nuxt3 사용하면서 보통 usefetch 사용했다 useAsyncData 와 useFetch 의 차이점이 아직 헷갈려서 정확하게 왜 사용했는지 말할 수가 없다... 좀 더 Nuxt3 사용하면서 작동 원리를 정확하게 알고 공부해야겠다고 생각했다.
[참고 자료]
useFetch · Nuxt Composables
Fetch data from an API endpoint with a SSR-friendly composable.
nuxt.com
useAsyncData · Nuxt Composables
useAsyncData provides access to data that resolves asynchronously in a SSR-friendly composable.
nuxt.com
Nuxt3 $fetch, useAsyncData, useFetch 의 차이
이 글은 제가 회사에서 Nuxt3 에 대해 발표하기 위해 준비했던 자료를 토대로 정리 한 글입니다. 읽기 전 Universal Rendreing 이 뭔지 알아야 하므로 먼저 이전글을 읽어주세요. Nuxt3 의 Universal Rendering
jongmin4943.tistory.com
'Nuxt.js 아는 척 하기' 카테고리의 다른 글
[Nuxt] CSR, SSR, SPA, MPA (0) | 2024.03.06 |
---|