owned this note
owned this note
Published
Linked with GitHub
---
tags: vue-router
---
# 데이터 fetching - 데이터는 언제 fetch해야할까?
vue-router를 적용하기 전에는 라이프사이클 메서드인 created 메서드 안에서 data를 fetch해왔다.
이제 라우팅을 적용하였으니, navigation이 되기 전에 data를 fetch해올 수 있을 것 같다.
관련한 글이 vue-router 공식문서에 적혀있었다. 내가 좋아하는 공식문서ㅋ-ㅋ
[vue-router 공식문서의 Data Fetching](https://router.vuejs.org/guide/advanced/data-fetching.html)을 보고 언제, 어떻게 data fetching을 할 것인지 정리해보고 어떻게 할 것인지를 생각해본다.
정리를 마친 후의 내 생각은, 네비게이션 후에 data를 fetch하는 것이다. 이동 자체가 느린 것은 UX적으로 좋지 않을 것 같다. 이동해서 data를 fetch한 다음에 기본적인 컴포넌트와 skeleton component를 보여주는 것이 더 좋을 것 같다.
---
컴포넌트를 렌더링하기 전에 data를 fetch하는 시점은 두 지점이 있을 것이다.
1. **네비게이션 후에 Fetching** : 네비게이션을 한 이후에, 컴포넌트의 라이프사이클 훅에서 데이타를 fetch한다. 데이타가 fetch되기 전에는 로딩 상태를 보여준다.
2. **네비게이션 전에 Fetching** : 네비게이션 전에 data를 fetch한다. 데이타가 Fetch된 이후에 네비게이션을 한다.
## 1. 네비게이션 후 Fetching
컴포넌트로 즉시 navigate하고, 렌더링한다. 그리고 컴포넌트의 `created` hook에서 데이터를 Fetch한다. 이 방식으로 하면, 데이타가 fetch되는 동안 로딩 상태를 보여줄 수 있다. 그리고 각 상태에 따라 로딩을 다르게 처리할 수 있다.
라우트는 갖고 param이 다를 경우엔 라이프사이클 훅이 호출되지 않는다. 따라서 $route를 watch해서, params가 변경되었을 때 필요한 작업들을 해줘야 한다.
```javascript
const User = {
template: '...',
watch: {
'$route' (to, from) {
// 경로 변경에 반응하여...
}
}
}
```
```javascript
export default {
data () {
return {
loading: false,
post: null,
error: null
}
},
created () {
// fetch the data when the view is created and the data is
// already being observed
this.fetchData()
},
watch: {
// 라우트가 변경되는 것을 watch로 확인하여 데이타를 fetch해야한다. -> 라우트는 같고, Params만 변경되면 컴포넌트가 재사용되어 라이프사이클 메서드가 호출되지 않기 때문이다.
'$route': 'fetchData'
},
methods: {
fetchData () {
this.error = this.post = null
this.loading = true
const fetchedId = this.$route.params.id
// replace `getPost` with your data fetching util / API wrapper
getPost(fetchedId, (err, post) => {
// make sure this request is the last one we did, discard otherwise
if (this.$route.params.id !== fetchedId) return
this.loading = false
if (err) {
this.error = err.toString()
} else {
this.post = post
}
})
}
}
}
```
## 2. 네비게이션 전에 Fetching
새로운 라우트로 네비게이트되기 전에 데이터를 fetch해온다.
이 방법은 들어갈 컴포넌트의 `beforeRouteEnter` 안에서 데이터를 Fetch하는 것이다.
fetch가 끝나면, `next()`를 호출한다.
next()는 다음 파이프라인에 있는 훅을 호출할 것이고 호출할 훅이 없으면 navigation이 이루어진다.
만약, 문제가 생기면 next(false)로 네비게이션을 취소할 수 있다.
- beforeRouteEnter
- 컴포넌트가 그려지기 전에 호출된다. 컴포넌트가 아직 생성되기 전이므로, this로 컴포넌트 인스턴스에 접근할 수 없다.
- 이 훅에서 첫 데이터를 fetch해온다.
- beforeRouteUpdate
- 이 컴포넌트가 변경되어 렌더링될 때 호출된다.
- 컴포넌트는 재사용된다. 예를 들어 /foo/1에서 /foo/2로 라우트가 변경되었을 때, Foo 컴포넌트는 그대로 사용하게 된다. 그리고 이 시점에 이 훅이 호출된다.
- 컴포넌트가 생성된 이후의 시점이므로 this로 컴포넌트 인스턴스에 접근할 수 있다.
- 이 훅에서 동적으로 라우팅이 변경될 경우, 데이타를 Fetch한다.
```javascript
export default {
data () {
return {
post: null,
error: null
}
},
beforeRouteEnter (to, from, next) {
getPost(to.params.id, (err, post) => {
next(vm => vm.setData(err, post))
})
},
// when route changes and this component is already rendered,
// the logic will be slightly different.
beforeRouteUpdate (to, from, next) {
this.post = null
getPost(to.params.id, (err, post) => {
this.setData(err, post)
next()
})
},
methods: {
setData (err, post) {
if (err) {
this.error = err.toString()
} else {
this.post = post
}
}
}
}
```
## Stale-while-revalidate
SWR이라고 캐쉬된 값 가져오고, 이후에 fetch한 data로 리프레쉬해주는 방식이 있다.
이미 가져온 데이터를 사용함으로써, 유저에게 더 빠른 응답을 줄 수 있다.
vue에서 SWR 개념을 사용할 수 있게 해주는 라이브러리가 swrv이다.
- SWR관련 참고하면 좋은 블로그 : https://blog.logrocket.com/advanced-data-fetching-techniques-in-vue/
- SWRV : https://markus.oberlehner.net/blog/stale-while-revalidate-data-fetching-composable-with-vue-3-composition-api/
## 출처
- [Data Fetching - vue-router](https://router.vuejs.org/guide/advanced/data-fetching.html