6.1 Axios란?
Http 요청을 처리하는 자바스크립트 오픈 소스 경량 라이브러리
fetch와 마찬가지로 프로미스 기반 HTTP 클라이언트이며, 서버(노드)와 브라우저에서 모두 사용할 수 있는 동질성 라이브러리
HTTP 요청을 가로채거나 최소할 수 있으며 사이트 간 요청 위조(CSRF) 방지 기능 내장
응답 데이터를 JSON 형식으로 자동 변환
6.2 Axios 설치
npm install axios
6.3 라이프사이클 훅과 Axios로 데이터 가져오기
created 또는 beforeMounted를 선택해야 하며, beforeMounted는 SSR에서 사용할 수 없으며 created 훅은 컴포지션 API에 대응하는 라이프사이클 함수가 없다.
가장 좋은 방법은 setup() 또는 <script setup>에서 반응형 컴포지션 함수로 외부 데이터를 가져오는 것
- 프로미스 반환형
axios.get('https://api.github.com/users/mayashavin')
.then(response => {
user.value = response.data
}).catch ((err) => {
error.value = err as Error
})
- await/async 방식
async function getUser() {
try {
const response = await axios.get('https://api.github.com/users/mayashavin')
user.value = response.data
} catch (err) {
error.value = err as Error
}
}
컴포넌트의 라이프사이클은 동기식으로 진행되므로 Vue의 비동기 요청과 무관하게 컴포넌트 생성 작업을 계속 진행한다. 그래서 컴포넌트에서 서로 다른 데이터 요청을 처리하려면 특수한 조치가 필요하다(계속)
6.4 런타임 중 비동기 데이터 요청
컴포넌트 생성 프로세스가 끝나면 비동기 요청 실행 순서에 따라 해결/거부 결과를 차례로 처리
비동기 요청이 해결/거부되고 컴포넌트 데이터가 변경되면 Vue 렌더러가 컴포넌트 업데이트 프로세스 트리거
Vue가 DOM에 컴포넌트를 마운팅하는 시점은 아직 응답 데이터가 없기 때문에 컴포넌트의 로딩 상태를 관리해야 한다
컴포넌트 데이터에 loading프로퍼티를 추가하여 v-if로 로딩 상태관리 가능
6.5 재사용 fetch 컴포넌트 생성
<slot>을 이용해 loading 상태 및 data 관리
부모 컴포넌츠
<FetchComponent url="https://api.github.com/users/mayashavin">
<template #default="defaultProps">
<div class="user-profile">
<img :src="(defaultProps.data as User).avatar_url" alt="`${user.name} Avattar`" width="200" />
<div>
<h1>{{ (defaultProps.data as User).name }}</h1>
<p>{{ (defaultProps.data as User).bio }}</p>
<p>Twitter: {{ (defaultProps.data as User).twitter_username }}</p>
<p>Blog: {{ (defaultProps.data as User).blog }}</p>
</div>
</div>
</template>
</FetchComponent>
자식 컴포넌츠
<template>
<slot name="loading" v-if="loading">
<div class="loading-message">Loading...</div>
</slot>
<slot :data="data" v-if="data">
</slot>
<slot name="error" :error="error" v-if="error">
<div class="error">
<p>Error: {{ error.message }}</p>
</div>
</slot>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import axios from 'axios';
const data = ref<object | undefined>();
const error = ref<Error | undefined>();
const loading = ref<boolean>(false);
const props = defineProps({
url: {
type: String,
required: true,
},
method: {
type: String,
default: "GET",
}
})
async function fetchData () {
try {
loading.value = true;
const response = await axios(props.url, {
method: props.method,
headers: {
'Content-Type' : 'application/json',
}
})
data.value = response.data
} catch (err) {
error.value = err as Error
} finally {
loading.value = false;
}
}
fetchData();
</script>
6.6 애플리케이션과 외부 데이터베이스 연결
Vue가 컴포넌트를 생성할 때마다 데이터를 가져오는 방식은 최선이 아니다. 특히 컴포넌트의 데이터가 자주 변경되지 않는 경우라면 더욱 그렇다.
페이지 데이터는 뷰를 처음 로드할 때 한 번만 가져와야 한다. 브라우저 로컬 저장소를 외부 데이터베이스로 삼거나 Vuex, 피니아 등 상태 관리 서비스로 데이터를 캐시에 저장해야 한다.
-LoccalStorage 사용 예시-
localStorage는 브라우저가 사설/익명 세션의 localStorage를 매번 초기화하고 사용자 또한 기능을 끌 수 있기 때문에 피니아 등의 상태 관리 도구를 사용하는 것이 좋다.
Nuxt3에서 useFetch 사용
useFetch · Nuxt Composables
Fetch data from an API endpoint with an SSR-friendly composable.
nuxt.com
useFetch
사용 이유
- 리액티브 데이터 관리 : 데이터를 가져온 결과를 리액티브 데이터로 반환하여 반응형으로 활용 가능
- SSR 지원 : 서버에서 데이터를 가져올 때 자동으로 SSR과 통합. SSR 환경에서 요청 결과를 HTML에 포함하고, 클라이언트에서 이를 하이드레이션
- 자동 캐싱 : 같은 요청이 여러 번 발생하면 캐싱된 데이터 반환
$fetch를 SSR에서 사용하면 두번 호출되는 이유
- 서버사이드 렌더링(SSR)과 클라이언트 하이드레이션(hydration) 과정이 각각 실행
- 서버에서 렌더링된 HTML에는 데이터가 포함되어 있지만, 클라이언트는 이를 상태(state)로 자동으로 복원하지 않음
- 클라이언트가 자체적으로 데이터를 요청해 상태를 초기화하려 하기 때문에 $fetch와 같은 함수가 다시 호출
하이드레이션
- 서버에서 렌더링된 HTML을 클라이언트에서 동적으로 활성화(reactivate)하는 과정.
- 서버에서는 초기 페이지를 렌더링하고, 클라이언트는 그 페이지를 받아서 JavaScript로 실행 가능한 상태로 만듬(활성화)
- Vue와 Nuxt가 클라이언트 측에서 상태를 동기화 하려 하기 때문에 함수가 다시 호출될 수 있음.
useAsyncData
- SSR 단계에서 데이터를 가져오고, 클라이언트로 전달된 HTML에 데이터를 JSON으로 직렬화하여 포함시킴
- 클라이언트는 서버에 전달된 데이터를 직렬화된 상태로 읽어와 하이드레이션하여 데이터가 재호출되지 않음
- useAsyncData를 사용하지 않으면 클라이언트는 자신의 초기 상태를 알 수 없으므로, 데이터를 다시 요청 보냄
- useFetch는 useAsyncData와 $fetch를 함께 사용하는 기능을 제공(페이지 파라미터 변경 탐지 등과 같은 차이는 있음)
'독후감' 카테고리의 다른 글
[클린 코드] 9. 단위 테스트 (0) | 2024.11.24 |
---|---|
[실전 코드로 배우는 Vue.js] Chapter 11. vue 테스트 (0) | 2024.11.17 |
[실전 코드로 배우는 Vue.js] Chapter 2. Vue의 기본 작동 방식 정리 (1) | 2024.11.11 |