๋ค์ด๊ฐ๋ฉฐ
์๋ ํ์ธ์ ์ค๋๋ง์ ๊ธ์ด๋ค์. ์ต๊ทผ์ ์๋ก์ด ํ์ฌ๋ก ์ด์งํ๋ฉด์ ํฌ์คํ ์ค๋น ๊ธฐ๊ฐ์ด ๊ฝค ๊ธธ์ด์ง ๊ฒ ๊ฐ์ต๋๋ค. ๋ค๋ค ์ฝ๋ก๋๋ ์ ์ด๊ฒจ๋ด๊ณ ๊ณ์ ๊ฐ์? ํ๋ฃจ๋นจ๋ฆฌ ๋ง์ ํธํ ๋ฐ์ ๋๊ฐ ์ ์๋ ๋ ์ด ์์ผ๋ฉด ์ข๊ฒ ๋ค์.. ๐
์ค๋ ์ค๋นํ ๊ธ์ ๋ค๋ค ์ด๋ฏธ ๋ค์ผ์ จ์ Vue.js์ ์ ๊ท ๋ฒ์ ์ ๋ํ ํฌ์คํ ์ ๋๋ค. ๋ทฐ ๊ณต์ ์ฌ์ดํธ์์ ๋ทฐ 3 ๊ณต์ ๋ฌธ์๋ฅผ ํ์ธํ์ค ์ ์๋๋ฐ์. ์ด ์ฌ์ดํธ๋ฅผ ๋ชจ๋ ํ ๋ฒ์ ์ ๋ฆฌํ๊ธด ์์ด ๋๋ฌด ๋ฐฉ๋ํ์ฌ ์ด๋ฒ ๊ธ์์๋ ๊ธฐ์กด Vue.js์ ๋น๊ตํ์ฌ ์์๋๋ฉด ์ข์ ์ ๊ทธ๋ฆฌ๊ณ ์ ๊ท ๋ฌธ์์์ ๊ผญ ํ ๋ฒ์ฉ ์ดํด๋ณด๋ฉด ์ข์ ๋งํ ๋ด์ฉ ๋ฑ์ ์ ๋ฌํ๋ ค ํฉ๋๋ค.
์ค๋ ๊ฐ๋จํ Vue 3์ ๋ํด์ ๋ฑ์ฅ ๋ฐฐ๊ฒฝ๊ณผ ์๊ฐ ์ ๋๋ฅผ ์์๋ณด๊ณ ๋ค์์ ์ฐ์ฌ๋ 2๊ฐ์ง ์๋ฆฌ์ฆ์์ ์ข ๋ ๊น์ํ๊ฒ Vue 3๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค ๐
- Vue 3 ์ปดํฌ์ง์ API(์ฐ์ฌ ์์ ์ค)
- Vue 3 ๋ง์ด๊ทธ๋ ์ด์ ๊ฐ์ด๋(์ฐ์ฌ ์์ ์ค)
Vue 3์ ์ถ์ ์์ ์ผ? ํ์ฌ ๋จ๊ณ๋?
์๋ก์ด ๋ทฐ ๋ฒ์ ์ด ๊ณง ๋ฑ์ฅํฉ๋๋ค. ํ์ฌ ๋ฒ ํ(Beta) ๋ฒ์ ์ ์ง๋ ๋ฆด๋ฆฌ์ฆ ํ๋ณด(Release Candidate) ๋จ๊ณ์ ์์ต๋๋ค. ์ข ๋ ์ฝ๊ฒ ์๊ธฐํ๋ฉด ๊ณง ๊ณต์ ๋ฒ์ ์ผ๋ก ์ถ์๋๊ธฐ ์ง์ ์ด๋ผ๋ ๋ง์ด์ฃ ๐
์ ํฌ๊ฐ ์์ฃผ ์ฌ์ฉํ๋ ๋ทฐ ์ฝ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฟ๋ง ์๋๋ผ ์ฃผ๋ณ ์ํ๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(๋ทฐ์์ค, ๋ทฐ ๋ผ์ฐํฐ)๋ ๋ฒ ํ ๋จ๊ณ์ด๊ธฐ ๋๋ฌธ์ ์๋ง ์ฌํด๊ฐ ๊ฐ๊ธฐ ์ ์๋ ๊ณต์ ๋ฒ์ ์ผ๋ก ์ถ์๋ ํ๋ฅ ์ด ๋งค์ฐ ๋์์ก์ต๋๋ค.
๐ข Vue.js 3 One Piece๊ฐ ์ถ์ ๋์์ต๋๋ค - 9์ 19์ผ
Vue 3์ด๋ผ๋.. ์ฌํ๊น์ง ๋ฐฐ์ด๊ฒ ๋ค ์์ฉ ์๋๊ฑด๊ฐ์?
ํ์ด์ง ์คํฌ๋กค์ ๋ ๋ด๋ฆฌ๊ธฐ ์ ์ ํ๊ฐ์ง ์ง๊ณ ๋์ด๊ฐ ๋ถ๋ถ์ด ์์ต๋๋ค. ์๋ง ์๋ก์ด Vue.js ๋ฒ์ ์ ๋ง์ฃผํ๋ฉด์ ์๋์ ๊ฐ์ ์๊ฐ์ด ๋ค ์ ์์ต๋๋ค.
โ์ ์ด์ ๊ฒจ์ฐ ๋ทฐ์ ์
๋ฌธํ๋๋ฐ ์ ๊ท ๋ฒ์ ์ด๋ผ๋ ๋ค์ ๋ฐฐ์์ผ ํ๋๊ฑฐ ์๋๊ฐ์?โ
โ์ ํ๋ก์ ํธ ์์ํ๋๋ฐ ๊ทธ๋ผ ๋ทฐ 3์ด ๋์ฌ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ํด์ผ ํ๋์?โ
์ค์ ๋ก ๋ช ์ผ ์ ์ ์์ ์ ์ฌํ ์ง๋ฌธ์ ๋ฐ๊ธฐ๋ ํ๋๋ฐ์. ์ฌ๊ธฐ์ ๋ง์๋๋ฆฌ๊ณ ์ถ์ ์ ์ ํ ๊ฐ์ง์ ๋๋ค.
โVue 3์ ๊ธฐ์กด Vue 2์ ๋น๊ตํด์ ์ ์ฒด์ ์ธ ์ปจ์ ๊ณผ ๊ฐ๋ ์ด ํฌ๊ฒ ๋ฌ๋ผ์ง์ง ์์์ต๋๋ค. Composition API ๋ผ๋ ์ธ์คํด์ค ์ต์ ์์ฑ์ด ์๋ก ์ถ๊ฐ ๋์๊ธฐ๋ ํ์ง๋ง ์ด ์์ฑ์ ์ฐ์ง ์๊ณ ๋ ์ง๊ธ๊น์ง ๋ฐฐ์์จ ๋ด์ฉ๋ค๋ก ์ถฉ๋ถํ ๋ชจ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ์ ์์ต๋๋ค ๐โ
์ ๊ท ๋ฒ์ ์ด ์ค๋ ๊ธฐ๊ฐ ๋์ ์ค๋น๋์ด ์จ ๋งํผ ์ ๋ ๊ด๋ จ ์๋ฃ๋ค์ ํ์ธํ๊ณ ์๋น์ค๋ฅผ ๋ง๋ค์ด๋ณด๋ฉด์ Composition API์ ๋ํ ๋ช ๊ฐ์ง ๊ด์ ์ด ์๊ฒผ๋๋ฐ์. ์ถํ์ ๋ณ๋๋ก ์๊ธฐ๋ฅผ ํด๋ณด๋ ค ํฉ๋๋ค ๐
Vue 3์์ ํด๊ฒฐํ๋ ค๋ ๋ฌธ์ ์
๋ทฐ 3์ ์๋ 6์๊ฒฝ๋ถํฐ ๊ฝค ์ค๋ ์๊ฐ ๋์ ์ปค๋ฎค๋ํฐ์ ๋ฐฉํฅ์ฑ์ ๊ณต์ ํ๋ฉด์ ๋ค๋ฌ์ด ์์ต๋๋ค.
์ฒ์์๋ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ข ๋ ๋งค๋๋ฝ๊ฒ ํฌ์ฉํ๊ธฐ ์ํด ํด๋์ค(ES6 Class) ๊ธฐ๋ฐ ์ปดํฌ๋ํธ ์ฝ๋ ์์ฑ ๋ฐฉ์์ ๊ณ ๋ฏผํ๋ค๊ฐ ์ต์ข ์ ์ผ๋ก ํ์ฌ์ ๊ฐ์ฒด ์คํ์ผ ์ปดํฌ๋ํธ ์ต์ ์์ฑ ์ ์ ๋ฐฉ์์ ์ฑํํ์ฃ .
๋ทฐ 3์ด ์ถ๊ตฌํ๋ ๋ฐฉํฅ์ ํฌ๊ฒ 2๊ฐ์ง๋ก ์์ฝํด ๋ณผ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
- ์ปดํฌ๋ํธ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ ํฅ์
- ํ์ ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ ์ง์
๊ธฐ์กด ๋ทฐ ๋ฒ์ ์์ ํ๊ณ์ ์ผ๋ก ์ธ๊ธ๋๋ ์ด 2๊ฐ์ง๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ทฐ 3์ด ๋ฑ์ฅํ์ต๋๋ค.
Vue.js์ ๊ธฐ์กด ํ๊ณ์ - ์ปดํฌ๋ํธ ์ฝ๋ ์ฌ์ฌ์ฉ
๋ชจ๋ ํ๋ฐํธ์๋ ํ๋ ์์ํฌ๋ค์ ๋ชจ๋ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ UI ๊ฐ๋ฐ ๋ฐฉ์์ ์ถ๊ตฌํฉ๋๋ค. ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ํธํ๊ฒ ๋ง๋ค๋ฉด์ ์ถํ์ ๋๋ฒ๊น ๋ ์์ํ๊ฒ ํ ์ ์๊ธฐ ๋๋ฌธ์ด์ฃ . ๋ทฐ๋ ์ปดํฌ๋ํธ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด์ ๋ํ์ ์ผ๋ก ์๋ 3๊ฐ์ง ๋ฐฉ์์ ์ถ์ฒํ๊ณ ์๋๋ฐ์.
- ์ฌ๋กฏ(Slots & Scoped Slots)
- ๋ฏน์ค์ธ(Mixins)
- ํ์ด ์ค๋ ์ปดํฌ๋ํธ(High Order Components)
์ฌ๊ธฐ์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ฐ์ ํ๊ฒ ์ฐ๊ด๋ ๋ก์ง๋ค์ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๋ณดํต ๋ฏน์ค์ธ์ ๋ง์ด ์ฌ์ฉํ์ต๋๋ค. (๊ฐ์ธ์ ์ธ ์๊ฐ์ด์ง๋ง ํ์ด ์ค๋ ์ปดํฌ๋ํธ๋ณด๋ค ๋ฏน์ค์ธ์ด ๋๋ค์ ๊ฐ๋ฐ์๋ค์๊ฒ ์ ํธ๋๋ ์ด์ ๋ ๊ฐ๋ ๊ณผ ๋ฌธ๋ฒ์ด ๋ ์ฝ๊ธฐ ๋๋ฌธ์ธ ๊ฒ ๊ฐ์ต๋๋ค)
๋ฏน์ค์ธ์ ์ปจ๋ฒค์
์ด ๊ต์ฅํ ์ค์ํ ๋ฌธ๋ฒ์ธ๋ฐ์. ๋ฏน์ค์ธ์ data
, methods
์ ๊ฐ์ ์์ฑ์ ์ ์ํ ๋๋ ๋ฏน์ค์ธ์ ์ฃผ์
ํ๋ ์ปดํฌ๋ํธ์ ์ต์
์์ฑ๊ณผ ๋ฏน์ค์ธ ์์ฑ์ ๊ตฌ๋ถํ๊ธฐ ์ํด ์ ๋์ฌ๋ฅผ ๋ถ์ด๊ฑฐ๋ ํ ๋ด ์ปจ๋ฒค์
์ ์๊ฒฉํ๊ฒ ์ ์ํ๋ ๊ฒ ์ข์ต๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์๋์ ๊ฐ์ ์ํฉ์์ ๊ฝค ๊ณจ๋จธ๋ฆฌ๋ฅผ ์ฉํ๋๋ค.
<!-- App.vue -->
<template>
<main>
<h1>์ค๋์ ๋ ์ง {{ currentDate }}</h1>
<todo-item v-for="item in items" :item="item" :id="formatId(item.id)"></todo-item>
</main>
</template>
<script>
import ItemMixins from './mixins/ItemMixins.js'
import TodoMixins from './mixins/TodoMixins.js'
import MyMixins from './mixins/MyMixins.js'
export default {
mixins: [ItemMixins, TodoMixins, MyMixins]
data() {
return {
todoItems: ['์ด ๋ฐ์ดํฐ ์์ฑ์', '์ฐ์ผ ๊น์?', '์ ์ฐ์ผ๊น์?]
}
},
methods: {
formatCurrentDate(value) {
// ...
this.currentDate = this.formatDate(value);
}
},
// ...
}
</script>
๋ฏน์ค์ธ์ ํน์ ์ปดํฌ๋ํธ์ 2๊ฐ ์ด์ ์ฌ์ฉํ๋ ์๊ฐ ๋ก์ง์ ํ๋ฆ์ ๋ฐ๋ผ๊ฐ๊ธฐ๊ฐ ์ด๋ ต๊ณ , ์ค์ ํด๋น data
๋ methods
๊ฐ ์ด๋ ๋ฏน์ค์ธ์ ์ ์๋์ด ์๋์ง ํ์
ํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค. ์ด๋ ๊ธฐ ๋๋ฌธ์ ๋ฏน์ค์ธ์ ์๊ฒฉํ ๊ท์น์ผ๋ก ์ฌ์ฉ ๋ฒ์์ ๋ณ์ ๋ช
์ ์ ํํด์ผ ํฉ๋๋ค.
Vue.js์ ๊ธฐ์กด ํ๊ณ์ - ํ์ ์คํฌ๋ฆฝํธ ์ง์
๋ทฐ๋ ์ ๋ฌธ์๋ค์ด ์ฝ๊ฒ ํ๋ ์์ํฌ๋ฅผ ๋ฐฐ์ธ ์ ์๋๋ก ํด๋์ค ๊ธฐ๋ฐ์ ์ปดํฌ๋ํธ ์ฝ๋ ์ ์ ๋ฐฉ์์ด ์๋ ๊ฐ์ฒด ์คํ์ผ์ ์ปดํฌ๋ํธ ์ฝ๋ ์ ์ ๋ฐฉ์์ ์ฌ์ฉํ์ต๋๋ค. ๊ฐ๊ฐ์ ์ฝ๋ ์คํ์ผ์ด ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ํ๋ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
// ํด๋์ค ๊ธฐ๋ฐ ์ปดํฌ๋ํธ ์ฝ๋ ์์ฑ ๋ฐฉ์
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
num: 10
}
}
render() {
return (
<div>
<h1>Hello, {this.props.name}</h1>
<p>{ num }</p>
</div>
)
}
}
// ๊ฐ์ฒด ๊ธฐ๋ฐ ์ปดํฌ๋ํธ ์ฝ๋ ์์ฑ ๋ฐฉ์
new Vue({
props: ['name'],
data: {
num: 10,
},
template: `
<div>
<h1>Hello, {{ name }}</h1>
<p>{{ num }}</p>
</div>
`
})
์์ ๊ฐ์ด ๊ฐ์ฒด ๊ธฐ๋ฐ ์ฝ๋ ์์ฑ ๋ฐฉ์์ ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ ์ต์ํ์ง ์์ ์ ๋ฌธ์๋ ์์ ์น ๊ฐ๋ฐ ๋ฐฉ์์ ์ต์ํ ์ฌ๋๋ค์๊ฒ ํ์ต ๋ถ๋ด๊ฐ์ ๋์ด์ฃผ๊ณ ์ฝ๋ ๊ฐ๋ ์ฑ์ ๋์ฌ์ฃผ์์ต๋๋ค.
ํ์ง๋ง ์ ์๋น์ด ์ง์ ์ฅ๋ฒฝ์ ๋ฎ์ถ๊ธฐ ์ํด ๊ฐ์ฒด ์คํ์ผ์ ์ฌ์ฉํ๋ค ๋ณด๋ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ง์ํ๊ธฐ์๋ ์ข ๋ฒ๊ฑฐ์ด ๊ตฌ์กฐ๋ฅผ ๊ฐ๊ฒ ๋ฉ๋๋ค. ํ์ ์คํฌ๋ฆฝํธ์ ํ์ ์ถ๋ก ๋ฐฉ์์ ๊ฐ์ฒด ๊ตฌ์กฐ๋ณด๋ค ํจ์ ๊ตฌ์กฐ์์ ๋ ์ด์ ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋์ ๊ธฐ์กด ๋ทฐ ๋ฒ์ ์์๋ ์๋์ ๊ฐ์ ํด๋์ค ๋ฌธ๋ฒ๋ค๋ก ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ๊ฐ๋ฐํ๊ธฐ ์์ํฉ๋๋ค.
<!-- MyButton.vue -->
<template>
<button @click="sayHi">say hi</button>
</template>
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';
// ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ด์ฉํ ์ปดํฌ๋ํธ ์ ์
@Component
export default class App extends Vue {
// data ์์ฑ
message = 'hello';
// methods ์์ฑ
sayHi() {
console.log(this.message);
}
}
</script>
์ฌ๋ด์ผ๋ก ์ต๊ทค๋ฌ๋ฅผ ์ค๋ ์ฌ์ฉํ์ ์ง์ธ ๋ถ๊ป ์ด๊ฑฐ ์ต๊ทค๋ฌ ์๋๋ ๋ผ๋ ์๋ฆฌ๋ฅผ ๋ค์ ์ ์ด ์์ต๋๋ค๋ง.. ์ฌ์ค ์ ๋ ๋ฐ๋ฐํ๊ธฐ ์ด๋ ค์ด ๊ตฌ์กฐ์์ต๋๋ค. ํ์ง๋ง, ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ ๋ ๊ผญ ์์ ๊ฐ์ ํํ๋ก ๊ฐ๋ฐํ ํ์๋ ์์ต๋๋ค. ์๋์ ๊ฐ์ ๊ตฌ์กฐ๋ก๋ ์ถฉ๋ถํ ํ์ ์คํฌ๋ฆฝํธ์ ๊ธฐ๋ฅ์ ์ง์๋ฐ์ผ๋ฉฐ ์๋น์ค๋ฅผ ๊ฐ๋ฐํ ์ ์์ต๋๋ค ๐
<template>
<button @click="sayHi">say hi</button>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
data() {
return { message: 'hello' }
},
methods: {
sayHi() {
console.log(this.message);
}
}
});
</script>
ํ์ง๋ง ์ฌ์ ํ ์ฃผ๋ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ํ์ ์ง์์ด ๋ถ์คํ ๊ฑด ์ฌ์ค์ ๋๋ค. ์๋์ ๊ฐ์ ์ํฉ์์๋ ๋งค๋ฒ ๊ฐ๋ฐ์๊ฐ ์ผ์ผ์ด ํ์ ์ ์ ์ํด ์ค์ผ ํ์ฃ .
// routes.ts
new VueRouter({
routes: [
{
path: '/',
component: MainView
beforeEnter(to: object, from: object, next: Function) {
// to์ from์ ๋ํ ํ์
์ ์ฝ๊ฒ ์ํฌํธ ํ ์ ์์ด ์ฌ์ฉ์๊ฐ ์ง์ ํ์
์ ์ ์ํด์ค์ผ ํจ
}
}
]
})
Vue 3์์๋ ๋ฌด์์ด ๋ฌ๋ผ์ก๋๊ฐ?
๊ทธ๋์ ์์์ ์ดํด๋ณธ ํ๊ณ์ ๋ ๋ณด์ํ๊ณ ์ฌ์ฉ์๊ฐ ๋ ๋ค์ํ ๋ฌธ๋ฒ์ ์ฌ์ฉํ ์ ์๋๋ก ๋ฐ๋์์ต๋๋ค. ํฌ๊ฒ ์์ฝํ๋ฉด ์๋ 5๊ฐ์ง์ ๋๋ค.
- Teleport(Vue Portal๊ณผ ์ ์ฌํฉ๋๋ค)
- ํ ํ๋ฆฟ ํํ์ ๊ด๋ จ ์ถ๊ฐ ๋ฌธ๋ฒ ์ ๊ณต
- Suspense
- Reactivity ์ฃผ์ API
- ๊ทธ๋ฆฌ๊ณ Composition API
๊ฐ๊ฐ์ ํน์ง์ ์ถํ ๋ณ๋์ ํฌ์คํ ์์ ์์ธํ ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค. ์ค๋ ํ ๋ฒ์ ๋ค ๋ฐฐ์ฐ๊ธฐ์๋ ์์ด ๋๋ฌด ๋ง๊ณ ๋จธ๋ฆฌ๊ฐ ๋ณต์กํด์ง ์ ์์ผ๋๊น์ ๐
์ค๋์ ๊ธฐ์กด ๋ฌธ๋ฒ์์ ์ถ๊ฐ๋ ๋ด์ฉ๋ค๋ง ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค ๐
Teleport์ ๋ทฐ ํฌํ ์ฌ์ฉ๋ฒ์ ๊ฑฐ์ ๊ฐ์ต๋๋ค. ๊ฐ๋ ์ ์ธ ์ฐจ์ด๊ฐ ์๋๋ฐ ๊ทธ๊ฑด ์ถํ ๋ณ๋ ํฌ์คํ ์ผ๋ก ๋ค๋ฃจ๊ฒ ์ต๋๋ค ๐
Vue 3 ๊ณต์ ๋ฌธ์์ ๋ํ ์ฒซ ์ธ์
์ผ๋จ ์ ๊ณต์ ๋ฌธ์์ ๋ํ ์๊ธฐ๋ฅผ ์ ๊น ํ๊ฒ ์ต๋๋ค. ์๋ 2๊ฐ์ง๊ฐ ํฌ๊ฒ ๋ฌ๋ผ์ก๋ค์.
- ๋ทฐ ํ๋ ์ค(VuePress)๊ธฐ๋ฐ ์ฌ์ดํธ ์ ์
- ๋ฌธ์ํ ๋ด๋น์ ๋ณ๊ฒฝ
Vue 3 ๊ณต์ ๋ฌธ์๋ ์ด์ ๋ฒ์ ๊ณผ ๋ค๋ฅด๊ฒ ๋ทฐ ํ๋ ์ค๋ผ๋ Vue.js ๊ธฐ๋ฐ ๋ฌธ์ํ ๋๊ตฌ๋ฅผ ์ด์ฉํ์ฌ ์ ์๋์์ต๋๋ค. ๊ทธ๋์ ํน์ ์ฝ๋ ๋ผ์ธ์ ๊ฐ์กฐํ๋ ๊ธฐ๋ฅ์ด๋ ์ฑ์ ์ค์นํ ์ ์๋ ๊ธฐ๋ฅ(Progressive Web Apps)์ด ์ถ๊ฐ๋ก ์ ๊ณต๋ฉ๋๋ค.
๋ฌธ์ํ ๋ด๋น์๋ ๋ฏธ๊ตญ ์ปจ์คํดํธ์ด์ ๊ธฐ์กด ๋ด๋น์์ธ ํฌ๋ฆฌ์ค(Chris)๊ฐ ์๋๋ผ ๋์์ธ ํนํ ํ๋ฐํธ ๊ฐ๋ฐ์์ธ ์ฌ๋ผ(Sarah Drasner)๊ฐ ์ฃผ๋ํ ๊ฒ์ผ๋ก ๋ณด์ด๋ค์. ์ฌ๋ผ๋ ํ๋ฐํธ์๋ ๊ฐ๋ฐ ์ชฝ์์ ๊ฝค ์ธ์ง๋๊ฐ ๋์ CSS Trick์ ๊ธฐ๊ณ ์์ด์ ์ ๋ช ํ ์ฝ๋ ํ์ด๋ผ์ดํ ๋๊ตฌ์ธ Night Owl์ ๋ง๋ ์ฌ๋์ ๋๋ค. ํ์ฌ ๋ทฐ ์ฝ์ด ํ์ผ๋ก ํ๋ํ๊ณ ์์ฃ .
Vue 3 ํ์ด๋ณด๊ธฐ - ๊ธฐ๋ณธ ๋ฌธ๋ฒ ํธ
์ ๊ทธ๋ผ ๋ณธ๊ฒฉ์ ์ผ๋ก ๋ทฐ 3 ๊ณต์ ๋ฌธ์์ ์ฃผ์ ํฌ์ธํธ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๊ธฐ์กด Vue.js ์ง์์์ ํฌ๊ฒ ๋ฒ์ด๋์ง ์๋ ์ ์ผ๋ก ๊ธฐ๋ณธ ๋ฌธ๋ฒ๋ค์ ์ ๋ฆฌํ์ต๋๋ค. ํฌ๊ฒ ์๋ 2๊ฐ์ง ๊ด์ ์์ ์ ๋ฆฌํ์ผ๋ ์ฐธ๊ณ ํด ์ฃผ์ธ์ ๐
๐ก ์๋ ๋ด์ฉ์ Vue 3 ๊ณต์ ๋ฌธ์์ Essential ๋ฉ๋ด์ Component in-Depth ๋ฉ๋ด๋ฅผ ๋ณด๊ณ ์ ๋ฆฌํ ๊ฒ์ ๋๋ค.
Vue 3์์ ์๋กญ๊ฒ ์ถ๊ฐ๋๊ฑฐ๋ ๊ผญ ํ์ธํด์ผ ํ ๋ฌธ๋ฒ๋ค
1. ๋๋ ํฐ๋ธ ๋ฌธ๋ฒ์ ์ธ์(Arguments)
๋ทฐ 3์์ ๋์ ์ธ์(Dynamic Arguments)๋ผ๋ ๊ฐ๋
์ด ์ถ๊ฐ๋์์ต๋๋ค. ๋๋ ํฐ๋ธ์ ๋์(arguments)์ด ๋ทฐ ์ธ์คํด์ค ๋ฐ์ดํฐ์ ์ฐ๊ฒฐ๋ ์ ์๊ฒ ๋ฌธ๋ฒ์ด ์ง์๋ฉ๋๋ค. v-on:
๋๋ ํฐ๋ธ๋ v-bind:
๋๋ ํฐ๋ธ์ ๋์์ ์๋์ ๊ฐ์ด ๋ทฐ ๋ฐ์ดํฐ ์์ฑ์ผ๋ก ์ฐ๊ฒฐํ์ฌ ์ ์ธํ ์ ์์ต๋๋ค.
<!-- ๋ฌธ๋ฒ ์์ -->
<a v-bind:[attributeName]="url">...</a>
์์ ์์ ๋ฌธ๋ฒ์ ์ค์ ์ฝ๋๋ฅผ ์ ์ฉํ๋ฉด ์๋์ ๊ฐ์ ๋ชจ์ต์ ๋๋ค.
<a v-bind:[linkAttribute]="url">...</a>
data() {
return {
linkAttribute: 'href' // ์ `myAttribute`๊ฐ `href`๋ก ์ ์ธ๋จ
}
}
2. ์ถ์ฝ ๋ฌธ๋ฒ
๋๋ ํฐ๋ธ์ ๋์ ์ธ์๋ฅผ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์๋์ ๊ฐ์ ์ถ์ฝ ๋ฌธ๋ฒ๋ ์ง์๋ฉ๋๋ค.
<!-- ๊ธฐ๋ณธ ๋ฌธ๋ฒ -->
<a v-bind:href="imageUrl">
<a v-on:click="logText">
<a v-bind:[myAttribute]="imageUrl"> <!-- ์ถ๊ฐ๋ ๋ฌธ๋ฒ -->
<!-- ์ถ์ฝ ๋ฌธ๋ฒ -->
<a :href="imageUrl">
<a @click="logText">
<a :[myAttribute]="imageUrl"> <!-- ์ถ๊ฐ๋ ๋ฌธ๋ฒ(์ถ์ฝํ) -->
3. ๋ฉํฐ ์ด๋ฒคํธ ํธ๋ค๋ฌ
์ผ๋ฐ์ ์ผ๋ก ๊ธฐ์กด ๋ทฐ ๋ฌธ๋ฒ์์ DOM ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ์๋์ ๊ฐ์ด ํ๋๋ง ๋ถ์ฐฉํด์ ์ฌ์ฉํฉ๋๋ค.
<!-- ์์ -->
<button @click="logText">log</button>
methods: {
logText(event) {
if (event) {
event.preventDefault();
}
}
}
์ด์ ๋ ํ ํ๋ฆฟ ํํ์์์ ํน์ DOM์ ์ด๋ฒคํธ๋ฅผ ์ฌ๋ฌ ๋ฉ์๋๋ก ์ฒ๋ฆฌํ ์ ์๋ ๋ฌธ๋ฒ์ด ์ง์๋ฉ๋๋ค.
<!-- ์์ -->
<button @click="logText($event), sayHi($event)">log</button>
methods: {
logText(event) {
// ์ด๋ฒคํธ ์ฒ๋ฆฌ ๊ด๋ จ ์ฒซ ๋ฒ์งธ ๋ก์ง
},
sayHi(event) {
// ์ด๋ฒคํธ ์ฒ๋ฆฌ ๊ด๋ จ ๋ ๋ฒ์งธ ๋ก์ง
}
}
4. ํค๋ณด๋ ์ด๋ฒคํธ ์ ์ด ๋ฌธ๋ฒ ์ถ๊ฐ
๊ธฐ์กด ๋ฌธ๋ฒ์์๋ ์๋์ ๊ฐ์ด ํน์ ํค์ ์ ๋ ฅ์ ์ ์ดํ์ต๋๋ค.
<input @keyup.enter="addTodo">
enter
ํค ์ด์ธ์๋ ์๋ ํค ๋ชฉ๋ก์ ์ง์ํฉ๋๋ค.
# Key Modifier
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
์ด์ ๋ ๊ณต์ ๋ฌธ์์์ ์๋ด๋์ง ์๋ ํค ์ ๋ ฅ์ ๋ํด์๋ ์๋์ ๊ฐ์ ๊ท์น์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
<!-- "KeyboardEvent.key" ๊ฐ์ด PageDown์ธ ๊ฒฝ์ฐ ์๋์ ๊ฐ์ด ์ผ๋ฐฅ์ผ๋ก ๋ณํํ์ฌ ๋ถ์ผ ์ ์์ -->
<input @keyup.page-down="onPageDown" />
5. ์ปดํฌ๋ํธ ํต์ ๋ฐฉ๋ฒ - ์ด๋ฒคํธ ์๋ฐ ์ธ์ ์ ๋ฌ
์ปดํฌ๋ํธ ํต์ ๋ฐฉ๋ฒ ์ค ์ด๋ฒคํธ ์๋ฐ(event emit)์ ๋ํ ์ถ๊ฐ์ ์ธ ๋ฌธ๋ฒ์ด ์ง์๋ฉ๋๋ค. ์๋์ ๊ฐ์ ์ปดํฌ๋ํธ ๊ตฌ์กฐ๊ฐ ์์ ๋
App
โโTodoList
โโTodoItem
TodoItem
์ปดํฌ๋ํธ์์ ๋ฐ์ํ ์ด๋ฒคํธ์ ์ธ์๋ฅผ ๋ฃจํธ ์ปดํฌ๋ํธ์ธ App
์ ์ ๋ฌ ๋ฐ์ผ๋ ค๋ฉด ์ค๊ฐ์ ์๋ ์ปดํฌ๋ํธ์ธ TodoList
์ปดํฌ๋ํธ์์ ์๋์ ๊ฐ์ด ์ด๋ฒคํธ๋ฅผ ์ค๊ฐํด์ค์ผ ํ์ต๋๋ค.
<!-- TodoItem.vue -->
<template>
<li>
<button @click="$emit('remove', 10)">remove</button>
</li>
</template>
<!-- TodoList.vue -->
<template>
<ul>
<todo-item @remove="removeItem"></todo-item>
</ul>
</template>
<script>
export default {
methods: {
removeItem(num) {
this.$emit('remove', num);
}
}
}
</script>
<!-- App.vue -->
<template>
<div>
<todo-list @remove="removeTodo"></todo-list>
</div>
</template>
<script>
export default {
methods: {
removeTodo(num) {
axios.delete('/todo/' + num);
}
}
}
</script>
ํ์ง๋ง ์ด์ ๋ ์์ ๊ฐ์ด ์ด๋ฒคํธ๋ฅผ ์ค๊ฐํ๋ ๋ฉ์๋๋ฅผ ์์ฑํ ํ์ ์์ด ํ ํ๋ฆฟ ํํ์์์ ์ด๋ฒคํธ๋ฅผ ์ธ์์ ํจ๊ป ์์ ์ปดํฌ๋ํธ์ ์ ๋ฌํ ์ ์์ต๋๋ค.
<!-- TodoItem.vue -->
<template>
<li>
<button @click="$emit('remove', 10)">remove</button>
</li>
</template>
<!-- TodoList.vue -->
<template>
<ul>
<todo-item @remove="$emit('remove', $event)"></todo-item>
</ul>
</template>
<!-- App.vue -->
<template>
<div>
<todo-list @remove="removeTodo"></todo-list>
</div>
</template>
<script>
export default {
methods: {
removeTodo(num) {
axios.delete('/todo/' + num);
}
}
}
</script>
๐ฌ ์ฌ์ค ์ ๋ฌธ๋ฒ์ ๊ธฐ์กด Vue.js ๋ฒ์ ์์๋ ๋์ผํ๊ฒ ๋์ํ๋ ๋ถ๋ถ์ธ๋ฐ ๋ฏธ์ฒ ๋ชฐ๋๋ ๋ถ๋ถ์ด์๋ค์ ๐
6. ํ๋กญ์ค ์์ฑ
ํ๋กญ์ค ์์ฑ์ ์ผ๋ฐ ๋ฌธ์์ด์ ์ฐ๊ฒฐํ๋ ๊ฒ๊ณผ ๋ทฐ ์ธ์คํด์ค์ data
๋ฅผ ์ฐ๊ฒฐํ๋ ๊ฒ์ ์ฐจ์ด์ ์ ๋ณด์ฌ์ฃผ๋ ์ฝ๋์
๋๋ค.
<!-- ํ๋กญ์ค ์์ฑ์ ์ผ๋ฐ ๋ฌธ์์ด์ ์ฐ๊ฒฐํ๋ ๊ฒฝ์ฐ -->
<template>
<app-header title="News Tonight"></app-header>
</template>
<!-- ํ๋กญ์ค ์์ฑ์ ๋ทฐ ๋ฐ์ดํฐ๋ฅผ ์ฐ๊ฒฐํ๋ ๊ฒฝ์ฐ -->
<template>
<app-header :title="appTitle"></app-header>
</template>
<script>
export default {
data() {
return {
appTitle: 'News Tonight'
}
}
}
</script>
์ฌ๊ธฐ์ ์๋ก์ด ๋ฌธ๋ฒ์ ํ๋ ๋ ์ธ๊ธํ๊ณ ์๋๋ฐ ํ๋กญ์ค ์์ฑ์ ๊ฐ์ ์ฐ๊ฒฐํ์ง ์์ผ๋ฉด true
๊ฐ์ ๊ฐ์ต๋๋ค.
<template>
<todo-item is-completed></todo-item>
</template>
<script>
export default {
props: ['isCompleted'],
created() {
console.log(this.isCompleted); // true
}
}
</script>
7. ํ ํ๋ฆฟ ํํ์์์์ ํ๋กญ์ค ์์ฑ ์ ์ ์ถ์ฝ ๋ฌธ๋ฒ
์๋์ ๊ฐ์ด data
์์ฑ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ๋ชจ๋ ํ๋กญ์ค ์์ฑ์ผ๋ก ๊ฐ๊ฐ ์ฐ๊ฒฐํด์ฃผ๋ ์ถ์ฝ ๋ฌธ๋ฒ๋ ๋ฑ์ฅํ์์ต๋๋ค.
<script>
export default {
data() {
return {
appInfo: {
title: '์ ๋ชฉ',
version: '๋ฒ์ '
}
}
}
}
</script>
<!-- ์ถ์ฝ ๋ฌธ๋ฒ -->
<app-title v-bind="appInfo"></app-title>
<!-- ์ค์ ๋ก๋ ์๋์ ๊ฐ์ด ๋์ - ๊ธฐ์กด ๋ฌธ๋ฒ -->
<app-title v-bind:title="appInfo.title" v-bind:version="appInfo.version"></app-title>
8. ์ด๋ฒคํธ ์๋ฐ ๋ฌธ๋ฒ
์ธ์คํด์ค ์ต์
์์ฑ์ emits
์ต์
์์ฑ์ด ์ถ๊ฐ ๋์์ต๋๋ค.
export default {
// ์ธ์คํด์ค ์ต์
์์ฑ
components: { TodoItem },
emits: ['remove', 'add:todo']
}
์ปดํฌ๋ํธ ๊ฐ์ ์ด๋ค ๋ฐ์ดํฐ์ ์ด๋ฒคํธ๊ฐ ์ค๊ฐ๋์ง ์ข ๋ ๋ช ํํ๊ฒ ์ธํฐํ์ด์ค(์ฝ์)๋ฅผ ๋ฌธ์ํํ๋ ๊ด์ ์์ ์ถ๊ฐํ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๋์ ๊ฐ์ด ์ด๋ฒคํธ ์๋ฐ์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ(validation) ๋ฌธ๋ฒ๋ ์ ์ํ ์ ์์ต๋๋ค.
export default {
emits: {
remove: false,
'add:todo': ({ item }) => {
if (item) {
return true;
} else {
console.log('invalid event payload');
return false;
}
}
}
}
9. inheritAttrs
์ต์
์์ฑ
์๋น์ค๋ฅผ ๊ฐ๋ฐํ ๋ ์ฌ๋ฌ ๋ช ์ ํ๋ฐํธ์๋ ๊ฐ๋ฐ์๋ ํ์ ํ๋ ์ํฉ์์ ์ ์ฉํ ๊ฒ์ ๋ณด์ด๋ ์ต์ ์์ฑ์ด ์ถ๊ฐ๋์์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ์ ์ํ ๋ ์๋์ ๊ฐ์ด ํ๋กญ์ค ์์ฑ์ด ์๋ HTML ํ์ค ์์ฑ(Attributes)์ ์ ์ํ๋ฉด
<!-- App.vue - ์์ ์ปดํฌ๋ํธ -->
<template>
<div>
<todo-item class="warn"></todo-item>
</div>
</template>
<!-- TodoItem.vue - ํ์ ์ปดํฌ๋ํธ -->
<template>
<li>
<p>์์ดํ
1</p>
</li>
</template>
ํ์ ์ปดํฌ๋ํธ์ธ TodoItem
์ปดํฌ๋ํธ์ HTML ๋ฃจํธ ์๋ฆฌ๋จผํธ์ HTML ํ์ค ์์ฑ์ด ์ถ๊ฐ๋ฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ํ์ ์ปดํฌ๋ํธ์ ๋ด์ฉ์ ์๋์ ๊ฐ์ด ์ ์ํ ๊ฒ์ฒ๋ผ ๋์ํ๊ฒ๋์ฃ .
<!-- TodoItem.vue -->
<template>
<li class="warn">
<p>์์ดํ
1</p>
</li>
</template>
์ด๊ฑธ ์์ฑ ์์(attribute inheritance)์ด๋ผ๊ณ ํ๋๋ฐ ์๋์ ๊ฐ์ด inheritAttrs: false
๋ฅผ ์ฃผ์ด์ ์์์ ๋ง๋ ๋ฌธ๋ฒ์ด ์ถ๊ฐ๋์์ต๋๋ค.
export default {
inheritAttrs: false
}
ํ์ ์์ ๋ณดํต ๊ณตํต ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด๋๊ณ ๊ณต์ฉ์ผ๋ก ์ฐ๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ ์์ ๊ฐ์ ์ต์ ์ ํ์ฉํ๋ฉด ๊ณตํต ์ปดํฌ๋ํธ๊ฐ ์๋ชป๋ ๋ฐฉํฅ์ผ๋ก ์ฌ์ฉ๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ ๊ฒ ๊ฐ๋ค์.
10. v-model
๋ฌธ๋ฒ
์ฌ์ฉ์ ์
๋ ฅ์ ๋ฐ์ ๋ ์์ฃผ ์ฌ์ฉ๋๋ v-model
๋๋ ํฐ๋ธ๋ ์ปดํฌ๋ํธ ํ๊ทธ์ ์ฐ๊ฒฐํ์์ ๋ ์๋์ ๊ฐ์ด ์ ์ํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค. v-model ๋ด๋ถ ๋์ ์ค๋ช
ํ๋ ๊ธ ๋งํฌ
<div>
<my-input v-model="inputText"></my-input>
</div>
<template>
<input :value="value" @input="onInput">
</template>
<script>
// MyInput.vue
export default {
props: ['value'],
methods: {
onInput(event) {
this.$emit('input', event.target.value);
}
}
}
</script>
์ ๋ฌธ๋ฒ์ด ์๋์ ๊ฐ์ด ๋ฐ๋์์ต๋๋ค.
<!-- App.vue -->
<template>
<div>
<my-input v-model="inputText"></my-input>
</div>
</template>
<script>
export default {
data() {
return { inputText: '' }
}
}
</script>
<!-- MyInput.vue -->
<template>
<input :value="modelValue" @input="onInput">
</template>
<script>
export default {
props: ['modelValue'],
methods: {
onInput(event) {
this.$emit('update:modelValue', event.target.value);
}
}
}
</script>
ํ์ ์ปดํฌ๋ํธ์์ v-model
์ ๋์์ด ๋๋ ํ๋กญ์ค ์์ฑ ์ด๋ฆ์ด modelValue
๋ก ๋ฐ๋์๊ณ , ์์ ์ปดํฌ๋ํธ๋ก ์ฌ๋ฆด ๋์ ์ด๋ฒคํธ ๋ํ input
์ด ์๋๋ผ update:modelValue
๋ก ๋ฐ๋์์ต๋๋ค.
:value
->:modelValue
:input
->:update:modelValue
11. ์ปดํฌ๋ํธ ํ๊ทธ์์ v-model
์ฌ๋ฌ ๊ฐ ์ฌ์ฉ
์ปดํฌ๋ํธ ํ๊ทธ์ ์๋์ ๊ฐ์ด v-model
๋๋ ํฐ๋ธ๋ฅผ ์ฌ๋ฌ ๊ฐ ์ฐ๊ฒฐํ ์ ์๊ฒ ๋์์ต๋๋ค.
<!-- App.vue -->
<template>
<div>
<user-profile
v-model:firstName="firstName"
v-model:lastName="lastName"
></user-profile>
</div>
</template>
<script>
export default {
data() {
return {
firstName: '',
lastName: ''
}
}
}
</script>
<!-- UserProfile.vue -->
<template>
<input :value="firstName" @input="$emit('update:firstName', $event.target.value)">
<input :value="lastName" @input="$emit('update:lastName', $event.target.value)">
</template>
<script>
export default {
props: ['firstName', 'lastName'],
}
</script>
๊ณต์ ๋ฌธ์์์ ๊ผญ ์ดํด๋ณด๋ฉด ์ข์ ๋ด์ฉ๋ค
์ ๋ฌธ๋ฒ ์ด์ธ์๋ ์๋ ๋ด์ฉ๋ค์ ๊ผญ ๊ณต์ ๋ฌธ์์์ ํ๋ฒ์ฉ ์ฝ์ด๋ณด๋ ๊ฒ์ ์ถ์ฒ๋๋ฆฝ๋๋ค ๐
1. Computed Caching vs Methods
์ปดํจํฐ๋ ์์ฑ๊ณผ ๋ฉ์๋์ ์ฐจ์ด์ ์ ์ด์ ๊ณต์ ๋ฌธ์๋ณด๋ค ๋ ์ ์ ํ ์์ ๋ก ๋ช ์พํ๊ฒ ์ค๋ช ํ์์ต๋๋ค.
2. Watch
Watch ์์ ์ ์ค๋ช ์ ์ฌ์ ํ ํ๋ฒ์ ์๋ฟ์ง ์์ง๋ง ํ์ธํด๋ณผ๋ง ํฉ๋๋ค.
โThis is most useful when you want to perform asynchronous or expensive operations in response to changing data.โ
๊ฐ์ธ์ ์ธ ์๊ฐ์ผ๋ก๋ ์๋น์ค ๊ฐ๋ฐํ ๋ watch
๋ ์ต์๋ก ์ฌ์ฉํ์๋ ์ฃผ์์
๋๋ค. watch
๋ฅผ ์ ๊ฒ ์ฌ์ฉํ ์๋ก ๋ฐ์ดํฐ ๊ฐ์ ์์กด ๊ด๊ณ ๋ณต์ก๋๋ฅผ ๋ฎ์ถ๊ณ ์ฝ๋ ํ๋ฆ์ ๋ ์ฝ๊ฒ ํ์
ํ ์ ์์ผ๋ฉฐ ๋๋ฒ๊น
๋ ์ฉ์ดํ๊ธฐ ๋๋ฌธ์
๋๋ค.
3. ํด๋์ค ๋ฐ์ธ๋ฉ
๋ทฐ ๋ฐ์ดํฐ ๊ฐ์ ๋ฐ๋ผ ํด๋์ค๋ฅผ ๋์ ์ผ๋ก ๋ฐ์ธ๋ฉ ํ๋ ๋ถ๋ถ์ ์์๊ฐ ์ ๋์ ์์ต๋๋ค. ์ค์ ๋ก๋ ์ค๋ฌด์์ ํ ํ๋ฆฟ ํํ์์ ๊ฐ๊ฒฐํ๊ฒ ๋ง๋ค๊ธฐ ์ํด ๋งค์ฐ ์งํฅํ๊ณ ์๋ ์คํ์ผ์ด๊ธฐ ๋๋ฌธ์ ๊ผญ ํ์ธํด๋ณด์๋ ๊ฑธ ์ถ์ฒ๋๋ฆฝ๋๋ค.
<div :class="classObject"></div>
data() {
return {
isActive: true,
error: null
}
},
computed: {
classObject() {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
4. ์คํ์ผ ๋ฐ์ธ๋ฉ
์ธ๋ผ์ธ ์คํ์ผ์ ํ ์ค๋ก ๋์ฌ๋๋ ๊ฒ๋ณด๋ค ์๋์ ๊ฐ์ด ๊ฐ์ฒด ํํ๋ก ์์ ํ๋ฉด ์ฝ๋๊ฐ ๊ฐ๊ฒฐํด์ง๋๋ค. ์ค๋ฌด์์ ๋ง์ด๋ค ๋์น๋ ๋ถ๋ถ์ธ ๊ฑฐ ๊ฐ์๋ฐ ์ ์ง์ด์ฃผ์๋ค์.
<div :style="styleObject"></div>
data() {
return {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
}
5. v-if
์ v-show
์ ์ฐจ์ด์
์๋น์ค ๊ฐ๋ฐํ ๋ ๋ง์ด ์ฌ์ฉํ๋ v-if
๋๋ ํฐ๋ธ์ v-show
๋๋ ํฐ๋ธ์ ์ฐจ์ด์ ์ ์ด๊ธฐ ๋ ๋๋ง ๋น์ฉ๊ณผ ๋ณ๊ฒฝ์ ๋ ๋๋ง ๋น์ฉ์ผ๋ก ๋๋์ด ์ ๋น๊ตํ์์ต๋๋ค.
6. ๋ชฉ๋ก ํํฐ๋ง & ์ค๋๋ง ํ
ํน์ ๋ชฉ๋ก์ ํํฐ๋ง ๋ฐ ์ค๋๋ง ํด์ผ ํ ๋ computed
์ methods
๋ฅผ ์ด๋ป๊ฒ ๊ตฌ๋ถํด์ ์จ์ผ ํ๋ ์ง ์ ๊ธฐ์ ๋์ด ์์ต๋๋ค.
7. v-on
๋๋ ํฐ๋ธ์ ์ด๋ฒคํธ ์ ์ด์(event modifiers)์ ๋ํ ์ ์ ํ ์์์ ์ค๋ช
prevent
, stop
, capture
, self
๋ฑ ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ฐฉ์์ ๋ํ ์์ ์ ์ฃผ์์ด ๊ธฐ์กด ๋ฌธ์๋ณด๋ค ๋ ์๋ฟ๋๋ก ์์ธํ๊ฒ ๊ธฐ์ ๋์ด ์์ต๋๋ค.
8. ํ ํ๋ฆฟ ํํ์์ ์ด๋ฒคํธ ์ ์ด์๋ฅผ ์ ์ฉํ์ ๋์ ์ฅ์ ์ค๋ช
HTML ์ฝ๋์ ์ด๋ฒคํธ ์ ์ด ๋ก์ง์ด ์๋์ ๊ฐ์ด ๋ถ์ด ์๋๊ฒ ์ ์ฅ์ ์ธ์ง ์ฝ๋ ๊ฐ๋ ์ฑ, ํ ์คํ , ๋ฆฌํฉํ ๋ง ๊ด์ ์์ ์ ์ค๋ช ํด์ฃผ๊ณ ์์ต๋๋ค.
<button @click.prevent="doSomething">click me</button>
9. ์ปดํฌ๋ํธ ๋ฑ๋ก ๋ฐฉ์์ ๋น๊ต
๋ทฐ 3 ๋ฌธ์ ๋๋ถ๋ถ์ ์ปดํฌ๋ํธ ๊ด๋ จ ์ฝ๋๋ ์ ์ญ ์ปดํฌ๋ํธ ์ฝ๋๋ก ์์๋ฅผ ๋ค๊ณ ์์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ์ค์ ๋ก ์๋น์ค๋ฅผ ๊ตฌํํ ๋๋ ์ฃผ๋ก ๋ก์ปฌ ์ปดํฌ๋ํธ ๋ฐฉ์์ด ์ฌ์ฉ๋๋๋ฐ ์ด์ ๋ํ ์ฐจ์ด์ ์ ์๋์ ๊ฐ์ด ์ ์ค๋ช ํ๊ณ ์์ต๋๋ค.
โ์ ์ญ์ผ๋ก ๋ทฐ ์ธ์คํด์ค์ ๋ฑ๋กํ ๊ฒฝ์ฐ ์ฌ์ฉํ์ง ์๋๋ผ๋ ์ต์ข ๋น๋์ ํด๋น ์์์ด ํฌํจ๋๋ค. ๋ฐ๋ผ์ ์ฌ์ฉ์๊ฐ ๋ถํ์ํ ๋ฆฌ์์ค๋ฅผ ๋ค์ด๋ก๋ ๋ฐ์์ผ ํ๋ ๋จ์ ์ด ์๊ธด๋ค.โ
10. ์ฌ๋กฏ์ ๋ ๋๋ง ์ ํจ ๋ฒ์
์ฌ๋กฏ์ ํ์ฉํ ๋ ๋ฐ์ดํฐ์ ์ ํจ ๋ฒ์๊ฐ ์์ ์ปดํฌ๋ํธ์ ํ์ ์ปดํฌ๋ํธ ์ค ์ด๋ ๊ณณ์ ์ฐ๊ด๋ ๊ฑด์ง ๊ทธ๋ฆผ์ผ๋ก ์ ํ์ด ๋์์ต๋๋ค.
11. ๋ฏน์ค์ธ
๋ฏน์ค์ธ์ ๋จ์ 2๊ฐ์ง๋ฅผ ์ง์ผ๋ฉด์ ์ Composition API๋ฅผ ์ฐ๋ฉด ์ข์์ง์ ๋ํด ์ ๋ํ๊ณ ์์ต๋๋ค. ๋ฏน์ค์ธ์ ๊ธฐ์กด ๋ทฐ ๋ฌธ๋ฒ์ด๋ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋นํด ๋ฌ๋ผ์ง ์ ์ด ์์ผ๋ ์ฐธ๊ณ ํ์๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค ๐
12. ๋ทฐ ํ ํ๋ฆฟ ์ต์คํ๋ก๋ฌ
์๋ฐ ์ ๊ฐ ์คํ๋ผ์ธ ์์ ๋ ์ฌ์ฉํ๋ Vue Template Explorer๋ฅผ ์ด์ ๋ ๊ณต์ ๋ฌธ์์์๋ ์๋ดํ๊ณ ์์ต๋๋ค.
13. ๋ทฐ ๋ฐ์์ฑ(Reactivity) ์ค๋ช
๋ทฐ์ ๊ฐ์ ์ธ ๋ฐ์์ฑ ์ฒด๊ณ(Reactivity System)๋ฅผ ์์ ์ ๋น์ ํ๋ฉด์ โ๋ฐ์ดํฐ๊ฐ ๋ฐ๋๋ฉด ํ๋ฉด์ด ๊ฐฑ์ ๋๋คโ ๋ผ๋ ๊ฑธ๋ก ์ ์ค๋ช ํ๊ณ ์๋ค์ ๐
๋ง๋ฌด๋ฆฌ
์ง๊ธ๊น์ง Vue 3์์ ๊ธฐ์กด ๋ฒ์ ๊ณผ ๋น๊ตํ์ฌ ๋ฌ๋ผ์ง ์ ๊ณผ ์ถ๊ฐ์ ์ผ๋ก ์ ๊ณต๋๋ ๋ฌธ๋ฒ๋ค์ ๋ํด์ ๊ฐ๋ตํ ์ดํด๋ดค์ต๋๋ค. ๊ธฐ์กด ํ๊ณ์ ์ ๊ทน๋ณตํ๋ ค๋ ๋ ธ๋ ฅ๋ฟ๋ง ์๋๋ผ ์ค๋ฌด์์ ๋ง์ด ์ฌ์ฉ๋๊ณ ์๋ ๋ฌธ๋ฒ์ ๋ํด์ ๋ค์ํ ์ ํ์ง๋ฅผ ์ ๊ณตํด ์ค ๊ฒ์ด ๋์ ๋๋ค์.
๋ฌด์๋ณด๋ค๋ ๊ธฐ์ ์ ์ข ์๋์ด ์์ง ์์ 100% ์ปค๋ฎค๋ํฐ ์คํ์์ค๋ต๊ฒ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ๋ฐ์ดํธ ๋ฐฉํฅ์ฑ์ ์ฌ์ฉ์๋ค๊ณผ ๊ต๊ฐํ๋ฉฐ ๋ฐ์ ์์ผ ์๋ค๋ ๊ฒ ๊ฐ์ฅ ์ธ์์ ์ด๋ค์. ์์ผ๋ก๋ ๋ ๋ง์ ๋ถ๋ค์ด Vue.js ์คํ ์์ค ๊ฐ๋ฐ์ ์ฐธ์ฌํด์ ๋ ์ข์ ๋๊ตฌ๋ฅผ ํจ๊ป ๋ง๋ค์ด ๋๊ฐ ์ ์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.
Vue 3์ ๋ํด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ํํค์ณ ๋ณผ ๋ค์ ๊ธ๋ค๋ ๊ธฐ๋ํด ์ฃผ์ธ์. ๊ธด ๊ธ ์ฝ์ด ์ฃผ์ ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค ๐
Vue 3 ํ์ต ๋ก๋๋งต



๊ธ๋ณด๋ค ๋ ์ฝ๊ฒ ๋ฐฐ์ฐ๋ ์จ๋ผ์ธ ๊ฐ์
์ข ๋ ์น์ ํ๊ณ ์์ธํ ์ค๋ช ์ ์ํ์ ๋ค๋ฉด ์๋ ๊ฐ์ข๋ฅผ ์ด์ฉํด๋ณด์๋ ๊ฒ๋ ์ข์ ๊ฒ ๊ฐ์์ ๐









ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ๋ ์ํ ์ ์๋ ๋ฐฉ๋ฒ
์บกํดํ๊ต์ ๋์ถ๋ ํ์ ์คํฌ๋ฆฝํธ ์ง์๊ณผ ๋ ธํ์ฐ๋ฅผ ์๊ณ ์ถ๋ค๋ฉด ์๋ ๋์๋ฅผ ์ฝ์ด๋ณด์ธ์ :)
