# Nuxt์ ๋น๋๊ธฐ ๋ฐ์ดํฐ ํธ์ถ ๋ฐฉ๋ฒ
๋์คํธ๋ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง ํ๋ ์์ํฌ์ด๊ธฐ ๋๋ฌธ์ ๋ทฐ ์ฑ๊ธ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ REST API๋ฅผ ํธ์ถํ๋ ๋ฐฉ์์ ๋ค๋ฅด๊ฒ ์ ๊ทผํด์ผ ํฉ๋๋ค. ์ด ๊ธ์์๋ ๊ธฐ์กด ๋ฐฉ์๊ณผ์ ์ฐจ์ด์ ๊ณผ ์ฃผ์ํด์ผ ํ ์ ์ ๋ํด์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
# ์ฑ๊ธ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ๋ค๋ฅธ ์
ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง์ธ ๋ทฐ ์ฑ๊ธ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ ์์์ ๋ฐ์ดํฐ ํธ์ถ ๋ฐฉ์์ ์๋์ ๊ฐ์ต๋๋ค.
<!-- UserProfile.vue -->
<template>
<div>
<p>{{ user }}</p>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
user: {},
}
},
methods: {
async fetchUser() {
const response = await axios.get('/users/1');
this.user = response.data;
}
},
created() {
this.fetchUser();
},
}
</script>
created()
๋ผ์ดํ์ฌ์ดํด ํ
์ ์ด์ฉํด์ ์ปดํฌ๋ํธ๊ฐ ์์ฑ๋์๋ง์ ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํด ๋ฐ์์จ ๊ฐ์ ํ๋ฉด์ ํ์ํ๋ ์ฝ๋์
๋๋ค. ์ด๋ ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๋ ์์ ์ ๋ธ๋ผ์ฐ์ ์์ Vue.js ์ฝ๋๊ฐ ํ๋ฉด์ DOM์ ๊ตฌ์ฑํ๊ณ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ ์์ ์
๋๋ค. ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง๊ณผ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง ์ฐจ์ด์ ์ ๊ทธ๋ฆผ์์๋ ๋ณผ ์ ์์ง๋ง ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง์ ๋น ํ๋ฉด์ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ฐ์ ํ๋ฉด์ ๋ฟ๋ฆด ์์์ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์์ ๊ตฌ์ฑํ๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ ์ฝ๋๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
ํ์ง๋ง, ๋์คํธ๋ ์๋ฒ์์ ํ์ด์ง์ ๋ด์ฉ์ ๋ชจ๋ ๊ทธ๋ ค์ ๋ธ๋ผ์ฐ์ ๋ก ๊ฐ์ ธ๊ฐ์ผ ํฉ๋๋ค. ๊ทธ๋ผ ์ด๋ป๊ฒ ํด์ผ ํ ๊น์?
# ๋์คํธ์ REST API ํธ์ถ ๋ฐฉ์
์์์ ์ดํด๋ณธ ๊ฒ์ฒ๋ผ ์ฑ๊ธ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ ์์ ํ์ด์ง์ ๋ฐ์ดํฐ๋ฅผ ํ์ํ๊ธฐ ์ํด์๋ ๋ทฐ ๋ผ์ดํ์ฌ์ดํด ํ ์ ์ฌ์ฉํ์ต๋๋ค. ๋์คํธ์์๋ ์๋์ 2๊ฐ์ง ์ธ์คํด์ค ์ต์ ์์ฑ์ด ๋ณ๋๋ก ์ ๊ณต๋ฉ๋๋ค.
asyncData
fetch
# asyncData
asyncData
๋ ํ์ด์ง ์ปดํฌ๋ํธ(pages ํด๋ ์๋์ ์์นํ๋ ์ปดํฌ๋ํธ)์๋ง ์ ๊ณต๋๋ ์์ฑ์
๋๋ค. asyncData
๋ก ์๋์ ๊ฐ์ด ์๋ฒ ๋ฐ์ดํฐ๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
<!-- pages/user.vue -->
<template>
<div>
<p>{{ user }}</p>
</div>
</template>
<script>
import axios from 'axios';
export default {
// params์ id๊ฐ 1์ด๋ผ๊ณ ๊ฐ์
async asyncData({ params, $http }) {
const response = await axios.get(`/users/${params.id}`);
const user = response.data;
return { user }
}
}
</script>
์ ์ฝ๋๋ URL /user
๋ก ์ ๊ทผํ ๋ user.vue
์ปดํฌ๋ํธ๋ฅผ ํ๋ฉด์ ๊ทธ๋ฆฌ๊ธฐ ์ ์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๋ ์ฝ๋์
๋๋ค. ๋ฐ์ดํฐ๋ฅผ ๋ค ๋ฐ์์์ผ์ง๋ง ๋ฐ์ดํฐ๋ฅผ ๋ค๊ณ <template></template>
์์ญ์ ์ฝ๋๋ฅผ ํ๋ฉด์ ํ์ํฉ๋๋ค. ๋ง์น ์ฑ๊ธ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์
์ ๋ทฐ ๋ผ์ฐํฐ์์ ๋ค๋น๊ฒ์ด์
๊ฐ๋์์ ๋ฐ์ดํฐ๋ฅผ ํธ์ถํ๊ณ ๋ฐ์์์ ๋ ํ์ด์ง๋ฅผ ์ง์
ํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
TIP
๋ผ์ฐํฐ ๋ค๋น๊ฒ์ด์
๊ฐ๋์ ๋ฐ์ดํฐ ํธ์ถ ๋ฐฉ๋ฒ์ ์๋ ์์์ ์ฐธ๊ณ ํ์ธ์ ๐
Vue.js ์๋ฒฝ ๊ฐ์ด๋ - ๋ผ์ฐํฐ ๋ค๋น๊ฒ์ด์
๋ฐ์ดํฐ ํธ์ถ ๋ฐฉ๋ฒ (opens new window)
# asyncData์ ํ๋ผ๋ฏธํฐ
asyncData ์์ฑ์ ํ๋ผ๋ฏธํฐ๋ context
์์ฑ์
๋๋ค. ์ปจํ
์คํธ ์์ฑ์ ๋์คํธ ํ๋ ์์ํฌ ์ ๋ฐ์ ๊ฑธ์ณ ๊ณต์ฉ์ผ๋ก ์ฌ์ฉ๋๋ ์์ฑ์ผ๋ก์จ ํ๋ฌ๊ทธ์ธ, ๋ฏธ๋ค์จ์ด ๋ฑ์ ์์ฑ์์๋ ์ ๊ทผํ ์ ์์ต๋๋ค. ์ปจํ
์คํธ์๋ ์คํ ์ด, ๋ผ์ฐํฐ ๊ด๋ จ ์ ๋ณด๋ฟ๋ง ์๋๋ผ ์๋ฒ ์ฌ์ด๋์์ ์์ฒญ, ์๋ต ๊ด๋ จ๋ ์์ฑ๋ ์ ๊ทผํ ์ ์์ต๋๋ค.
function (context) { // asyncData, plugins, middleware, ...
// Always available
const {
app,
store,
route,
params,
query,
env,
isDev,
isHMR,
redirect,
error,
$config
} = context
// Only available on the Server-side
if (process.server) {
const { req, res, beforeNuxtRender } = context
}
// Only available on the Client-side
if (process.client) {
const { from, nuxtState } = context
}
}
# asyncData์ ์๋ฌ ํธ๋ค๋ง
aysncData ์์ฑ์์ API ํธ์ถ ์๋ฌ๊ฐ ๋ฐ์ํ์ ๋๋ ์๋์ ๊ฐ์ด ์๋ฌ ํ์ด์ง๋ก ์ด๋์ํฌ ์ ์์ต๋๋ค.
export default {
async asyncData({ params, $http, error }) {
try {
const response = await axios.get(`/users/${params.id}`);
const user = response.data;
return { user }
} catch(e) {
error({ statusCode: 503, message: 'API ์์ฒญ์ด ์คํจํ์ต๋๋ค ๋ค์ ์๋ํด ์ฃผ์ธ์' })
}
}
}
# fetch
fetch
๋ ํ์ด์ง ์ปดํฌ๋ํธ ๋ฟ๋ง ์๋๋ผ ์ผ๋ฐ ๋ทฐ ์ปดํฌ๋ํธ์์๋ ์ฌ์ฉํ ์ ์๋ ๋ฐ์ดํฐ ํธ์ถ ์์ฑ์
๋๋ค. ๋ค์ 2๊ฐ์ง ์ํฉ์์ ํธ์ถ๋ฉ๋๋ค.
- ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง์ ์ํด ์๋ฒ์์ ํ๋ฉด์ ๊ตฌ์ฑํ ๋ ์ปดํฌ๋ํธ๊ฐ ์์ฑ๋๊ณ ๋์ ์คํ๋จ
- ๋ธ๋ผ์ฐ์ ์์ URL ์ฃผ์๋ฅผ ๋ณ๊ฒฝํด์ ํ์ด์ง๋ฅผ ์ด๋ํ ๋
๊ฐ๋จํ ์์ ์ฝ๋๋ฅผ ๋ณด๊ฒ ์ต๋๋ค.
<!-- components/UserProfile.vue -->
<template>
<div>{{ user }}</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
user: {},
}
},
async fetch() {
const res = await axios.get('https://jsonplaceholder.typicode.com/users/1');
this.user = res.data;
},
}
</script>
๋ง์ฝ ์ ์ปดํฌ๋ํธ๊ฐ ์๋์ ๊ฐ์ด main.vue
์ปดํฌ๋ํธ์ ๋ฑ๋ก๋์ด ์๊ณ URL ์ฃผ์๊ฐ /
์์ /main
์ผ๋ก ๋ณ๊ฒฝ๋๋ฉด ์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์ ๋ถ์ฐฉ๋๊ณ ๋์(mounted) fetch
์์ ๋ฐ์ดํฐ ํธ์ถ ๋ก์ง์ด ์คํ๋ฉ๋๋ค.
<!-- pages/main.vue -->
<template>
<div>
<h1>๋ฉ์ธ ํ์ด์ง</h1>
<UserProfile></UserProfile>
</div>
</template>
<script>
import UserProfile from '@/components/UserProfile.vue'
export default {
components: {
UserProfile,
},
}
</script>
์์ ๋์์์ ๋ณผ ์ ์๋ฏ์ด ์ต์ด์ /
๋ก ์ ๊ทผํ๊ณ /main
์ผ๋ก ์ด๋ํ๊ธฐ ๋๋ฌธ์ ์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์ ๋จผ์ ๋ฟ๋ ค์ง๊ณ ๋์ fetch
ํธ์ถ์ด ์คํ๋ฉ๋๋ค. ๋ฐ๋ผ์, /main
์ผ๋ก ์ด๋ํ๊ณ ๋๋ฉด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ๋์ user
์์ฑ์ ๊ธฐ๋ณธ ๊ฐ์ธ {}
๊ฐ ๋จผ์ ํ๋ฉด์ ๋ณด์ด๊ณ ์ ์ ํ์ ๋ฐ์์จ ๋ฐ์ดํฐ๊ฐ ํ๋ฉด์ ๊ทธ๋ ค์ง๋ ๊ฑธ ๋ณผ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์ ๋ง์ฝ ์ต์ด๋ก ์น ์๋น์ค๋ฅผ /main
์ผ๋ก ์ ๊ทผํ๊ฒ ๋๋ฉด ์๋ฒ์์ ํ๋ฉด์ ๊ตฌ์ฑํ ๋ ํธ์ถ๋ฉ๋๋ค. ๋ฐ๋ผ์, ํ๋ฉด์ ๋ฐ์ดํฐ๊ฐ ํธ์ถ๋ ์ํ๋ก ํ์ด์ง๊ฐ ํ์๋ฉ๋๋ค.
# fetch ํน์ง
fetch
๋ asyncData
์ ๋ค๋ฅด๊ฒ ์๋์ ๊ฐ์ ์์ฑ๋ค์ ์ ๊ณตํฉ๋๋ค.
$fetchState
: ๋ฐ์ดํฐ ํธ์ถ ์ํ๋ฅผ ๋ํ๋ด๋ ์์ฑ์ด๋ฉฐ ์ธ์คํด์ค๋ก ์ ๊ทผํ ์ ์์ต๋๋ค. ํธ์ถ ์ํ์ ๋ฐ๋ผpending
,error
,timestamp
๋ฅผ ์ ๊ณตํฉ๋๋ค.$fetch
:fetch
๋ก์ง์ ๋ค์ ์คํ์ํฌ ์ ์๋ ํจ์์ ๋๋ค.fetchOnServer
: ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง ์์ ์๋ฒ์์fetch
๋ฅผ ์คํํ ์ง ๋ง์ง ๊ฒฐ์ ํ๋ ์์ฑ์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ์true
์ ๋๋ค.
์ ์์ฑ์ ์ฝ๋๋ก ์ดํด๋ณด๊ฒ ์ต๋๋ค.
<template>
<div>
<article>
<p v-if="$fetchState.pending">์ฌ์ฉ์ API ํธ์ถ ์ค</p>
<p v-else-if="$fetchState.error">์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค</p>
<div v-else>{{ user }}</div>
</article>
<button @click="fetchUser">๋ค์ ํธ์ถํ๊ธฐ</button>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
user: {},
}
},
methods: {
fetchUser() {
// fetch ์์ฑ์ ๋ก์ง์ ์คํํฉ๋๋ค.
this.$fetch();
}
},
async fetch() {
const res = await axios.get('https://jsonplaceholder.typicode.com/users/1');
this.user = res.data;
},
// ์๋ ์์ฑ์ 'false'๋ก ๋ฐ๊พธ๋ฉด ์๋ฒ์์ ํ๋ฉด์ ๊ตฌ์ฑํ ๋ `fetch` ์์ฑ์ ๋ก์ง์ด ์คํ๋์ง ์์ต๋๋ค.
fetchOnServer: false
}
</script>