-
[Vue.js] ์ปดํฌ๋ํธ ๊ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ๐ Vue.js 2024. 10. 16. 13:44
1. ์ปดํฌ๋ํธ๋?
Vue์์ ์ปดํฌ๋ํธ๋ UI์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋จ์์ ๋๋ค.
์ฃผ๋ก Vue์์ ํ๋ฉด์ ์์ญ์ ๊ตฌ๋ถํ์ฌ ๊ฐ๋ฐํ๋๋ฐ ์ฌ์ฉํฉ๋๋ค.
๊ทธ๋ผ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋?๐คทโโ๏ธ
- ์ฝ๋์ ๊ฐ๋ ์ฑ์ ๋์ธ๋ค.
- ์ ์ง๋ณด์๊ฐ ์ฉ์ดํ๋ค.
- ์ฝ๋์ ์ค๋ณต์ ์ค์ผ ์ ์๋ค.
Vue์์๋ ๊ฐ ์ปดํฌ๋ํธ๋ ๊ณ ์ ์ ๋ฐ์ดํฐ, ๋ฉ์๋, ํ ํ๋ฆฟ์ ๊ฐ์ง๊ณ ๋์ํฉ๋๋ค.
ํ์ด์ง์์ ์ฃผ๋ก Header, Body, Footer์ ๊ฐ์ UI ์์๋ฅผ ์ปดํฌ๋ํธ๋ก ๋ง๋ค๊ณ ,
๋ค๋ฅธ ๊ณณ์์๋ ์ฌ์ฌ์ฉํ ์ ์์ด ๊ด๋ฆฌ๊ฐ ํธํฉ๋๋ค.
์ปดํฌ๋ํธ๋ฅผ ์ค๋ช ํ๋ฉด์ ์ถ๊ฐ๋ก ๋ง์๋๋ฆฌ๋ฉด,
์ด์ ๊น์ง์ Vue2์์์ ์ปดํฌ๋ํธ๋ options API๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋์์ต๋๋ค.
ํ์ง๋ง Vue3์์๋ Composition API๊ฐ ๋์ ๋์๊ณ ,
๊ทธ ์ค์์๋ <script setup> ๋ฌธ๋ฒ์ ๋ ์ง๊ด์ ์ด๊ณ ๊ฐ๊ฒฐํ ๋ฐฉ์์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ ์ ์๋๋ก ๋์์ค๋๋ค.
Options API ์ Composition API ์ ํน์ง
ํน์ง Options API Composition API ์ฝ๋ ๊ตฌ์กฐ ์ต์ ๊ฐ์ฒด๋ก ๊ธฐ๋ฅ์ ๋ถ๋ฆฌ (data, methods ๋ฑ) ๊ด๋ จ๋ ๋ก์ง์ ํ ๊ณณ์ ๋ชจ์์ ์ ์ (ref, computed ๋ฑ) ์ ์ฐ์ฑ ๊ณ ์ ๋ ๊ตฌ์กฐ, ์ฌ์ฌ์ฉ ์ด๋ ค์ ๋ก์ง ์ฌ์ฌ์ฉ ๊ฐ๋ฅ, ๋ ์ ์ฐํ ์ฝ๋ ์์ฑ ๊ฐ๋ฅ ๊ฐ๋ ์ฑ ์์ ์ปดํฌ๋ํธ์ ์ ํฉ ํฐ ์ปดํฌ๋ํธ์ ์ ํฉ, ๋ก์ง์ด ๋ชจ๋ํ๋จ ์ํ ๊ด๋ฆฌ ๊ฐ ์์ฑ์ด ๋๋ ์ ธ ์์ ์ํ์ ๋ฉ์๋๊ฐ ํจ๊ป ๋ฌถ์ฌ ๊ด๋ฆฌ๋จ ์ปดํฌ๋ํธ ๊ท๋ชจ ์์ ๊ท๋ชจ ์ปดํฌ๋ํธ์ ์ ํฉ ํฐ ๊ท๋ชจ์ ๋ณต์กํ ์ปดํฌ๋ํธ์ ์ ํฉ Options API ์์
<script> export default { data() { return { count: 0 }; }, computed: { doubleCount() { return this.count * 2; } }, methods: { increment() { this.count++; } }, mounted() { console.log('Component mounted!'); } }; </script> <template> <div> <p>{{ doubleCount }}</p> <button @click="increment">Increment</button> </div> </template>
Vue2์์ ์์ฃผ ์ฌ์ฉํ๋ Optinos API๋
์ฃผ๋ก data(), methods, computed, mounted ๋ฑ ๊ฐ ์์ฑ์ ๊ฐ์ฒด๋ก ๋๋์ด ์ ์ํ๋ ํน์ง์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
Composition API ์์
<script setup> import { ref, computed, onMounted } from 'vue'; const count = ref(0); const doubleCount = computed(() => count.value * 2); function increment() { count.value++; } onMounted(() => { console.log('Component mounted!'); }); </script> <template> <div> <p>{{ doubleCount }}</p> <button @click="increment">Increment</button> </div> </template>
Vue3์์ ์ฃผ๋ก ์ฌ์ฉํ๋ Compositions API๋
์ฃผ๋ก ref(), computed(), onMounted() ๋ฑ Vue์ ๊ธฐ๋ฅ์ ํจ์๋ก ์ฌ์ฉํ์ฌ ์์ฑํ๋ ํน์ง์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
Vue3์์๋ Composition API๋ฟ๋ง ์๋๋ผ Options API๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ฏ๋ก ์ํฉ์ ๋ง๊ฒ ์ ์ ํ ์ฌ์ฉํ์๋ฉด ๋ฉ๋๋ค.
2. <script setup>์ด๋?
<script setup>์ Vue 3์์ ์ ๊ณตํ๋ ์๋ก์ด ๋ฌธ๋ฒ์ผ๋ก, Composition API์ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ต๋ํ ๊ฐ๋จํ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋์์ค๋๋ค. ๊ธฐ์กด์ setup() ํจ์ ๋ด๋ถ์ ์์ฑํ๋ ๋ก์ง์ ๋ ๊น๋ํ๊ฒ ์ฒ๋ฆฌํ ์ ์์ผ๋ฉฐ, ํนํ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ ๋ ๋งค์ฐ ์ ์ฉํฉ๋๋ค.
<script setup>์ ์ฌ์ฉํ๋ฉด ?
- setup() ํจ์๋ฅผ ์ง์ ์ ์ํ์ง ์๊ณ , ๊ทธ ์์ ๋ฃ์ ๋ด์ฉ์ ๋ฐ๋ก ์์ฑํ ์ ์์ต๋๋ค.
- defineProps(), defineEmits() ๊ฐ์ API๋ ๋ณ๋์ ์ํฌํธ ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ๋ ๊ฐ๊ฒฐํ ์ฝ๋ ์์ฑ์ด ๊ฐ๋ฅํฉ๋๋ค.
<script setup> ์์
<script setup> import ChildComponent from './ChildComponent.vue' const message = 'Hello from Parent!' </script> <template> <div> <ChildComponent :msg="message" /> </div> </template>
3. ์ปดํฌ๋ํธ ์ฌ์ฉ๋ฒ
<script setup>์์ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ ๋งค์ฐ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค.
๋ค๋ฅธ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ ธ์ ํ ํ๋ฆฟ์์ ์ฌ์ฉํ์๋ฉด ๋ฉ๋๋ค.
์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ ธ์ฌ ๋๋ ES ๋ชจ๋ ๋ฐฉ์์ ์ฌ์ฉํ๊ณ ,
์์๋ก ์๋์ ๊ฐ์ด ์ปดํฌ๋ํธ๋ฅผ ์ํฌํธํ๊ณ ํ ํ๋ฆฟ์ ์ ์ธํ๋ฉด ๋ฉ๋๋ค.
<template> <div> <Main></Main> </div> </template> <script setup> import Main from './views/Main.vue' </script> <style scoped></style>
์ ์ฝ๋๋ฅผ ๋น๊ตํด์ ์ค๋ช ๋๋ฆฌ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฐ์ ์ ๋ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํ์์ต๋๋ค.
App.vue
์ด์ ์ ์์๋๋ฉด ์ข์ ๊ฒ์ ๋จผ์ ์ค๋ช ๋๋ฆฌ์๋ฉด, ๋์ ์คํ์ ์์ด์
์ฒซ๋ฒ์งธ๋ก๋ main.js์์ ์์์ ํ๊ฒ ๋ฉ๋๋ค.
Main.js
// Vue ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ createApp ํจ์ ๊ฐ์ ธ์ค๊ธฐ import { createApp } from 'vue' // ์ํ ๊ด๋ฆฌ๋ฅผ ์ํด Pinia ๊ฐ์ ธ์ค๊ธฐ import { createPinia } from 'pinia' // App.vue ํ์ผ์์ App ์ปดํฌ๋ํธ ๊ฐ์ ธ์ค๊ธฐ import App from './App.vue' // ๋ผ์ฐํฐ ์ค์ ๊ฐ์ ธ์ค๊ธฐ import router from './router' // App ์ปดํฌ๋ํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Vue ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฑ const app = createApp(App) // ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Pinia๋ฅผ ์ฌ์ฉํ๋๋ก ๋ฑ๋ก app.use(createPinia()) // Vue Router๋ฅผ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฑ๋ก app.use(router) // #app์ด๋ผ๋ ID๋ฅผ ๊ฐ์ง DOM ์์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง์ดํธ app.mount('#app')
Vue๋ฅผ ๋๋๋งํ๊ธฐ๊น์ง์ ๊ณผ์ ์ ์๋์ ๊ฐ์ต๋๋ค.
3-1. ์ ํ๋ฆฌ์ผ์ด์ ์์ฑ
- main.js์์ createApp(App)์ ํธ์ถํ์ฌ Vue ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฑํฉ๋๋ค.
- App.vue์์ ์ ์๋ App ์ปดํฌ๋ํธ๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ต์์ ์ปดํฌ๋ํธ๋ก ์ค์ ๋ฉ๋๋ค.
3-2. ํ๋ฌ๊ทธ์ธ ๋ฑ๋ก
- createPinia()๋ฅผ ์ฌ์ฉํด Pinia ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฑ๋กํ์ฌ๊ธ, ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ ์ํ๋ฅผ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
- app.use(router)๋ฅผ ํตํด Vue Router๋ฅผ ๋ฑ๋กํ์ฌ SPA(Single Page Application) ๊ธฐ๋ฅ์ ์ถ๊ฐํฉ๋๋ค.
3-3. DOM์ ๋ง์ดํธ
- app.mount('#app')๋ฅผ ํธ์ถํ์ฌ HTML ํ์ผ์์ id="app"์ธ ์์์ Vue ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง์ดํธํฉ๋๋ค. ์ด ๊ณผ์ ์์ Vue๋ App.vue์ ์ ์๋ ๋ด์ฉ์ ๊ธฐ๋ฐ์ผ๋ก UI๋ฅผ ๋ ๋๋งํฉ๋๋ค.
3-4. App.vue ๋ ๋๋ง
- App.vue์ <template> ๋ถ๋ถ์ด DOM์ ๋ ๋๋ง๋๊ณ , ๊ทธ ์์์ ์ ๊ฐ ์ค์ ํ <Main></Main> ์ปดํฌ๋ํธ๊ฐ ํธ์ถ๋ฉ๋๋ค.
- <script setup> ๋ด์ import Main from './views/Main.vue'๋ฅผ ํตํด Main.vue๋ฅผ ๊ฐ์ ธ์ค๊ณ , ์ด๋ฅผ <Main> ํ๊ทธ๋ก ์ฌ์ฉํ์ฌ Main ์ปดํฌ๋ํธ๋ฅผ UI์ ์ถ๊ฐํฉ๋๋ค.
์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ ๋์๊ฐ์ ์ค๋ช ์ ๋๋ฆฌ๋ฉด,
App.vue๋ ์ต์์ ์ปดํฌ๋ํธ๋ก, ์ด๊ณณ์์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ฅผ ํฌํจํ๊ฑฐ๋ ๋ผ์ฐํฐ๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
์ฐ์ ์ ๋ views๋ผ๋ ํด๋์ Main.vue๋ผ๋ vueํ์ผ์ ๋ง๋ค๊ณ ๋์์ ์ ์ธ์ ํ์์ต๋๋ค.
Main.vue
Main.vue ์๋ ๋ง์ฐฌ๊ฐ์ง๋ก Header.vue, Body.vue , Footer.vue ๋ฅผ div ํ๊ทธ ์์ ์ ์ธ์ ํ์์ต๋๋ค.
์ด๋ ๊ฒ ๋๋ฉด App.vue์์๋ ์ฒ์์ ๋๋๋ง์ด ๋ ๋ Main.vue๋ฅผ ์ถ๋ ฅํ๊ฒ ๋๋๋ฐ,
์์ ๊ฐ์ด Main.vue๋ Header, Body, Footer ๋ฅผ ์ ์ธํ๊ณ ์์ผ๋ฏ๋ก ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ์ถ๋ ฅํ๊ฒ ๋ฉ๋๋ค.
Header.vue
Body.vue
Footer.vue
๊ฒฐ๊ตญ App.vue ๋ Main.vue๋ฅผ ์ถ๋ ฅ -> Main.vue๋ Header, Body, Footer ์ถ๋ ฅ -> ์ด 3๊ฐ์ ์ปดํฌ๋ํธ ์ถ๋ ฅ
์ ๊ณผ์ ์ ๊ฑฐ์น๊ฒ ๋ฉ๋๋ค.
๊ฒฐ๊ณผ๋ฌผ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ปดํฌ๋ํธ์ ๋ํ ์ค๋ช ๋ง ํ๊ธฐ ์ํด ์์ฑ์ ํ์๋๋ฐ, ์ค๊ฐ์ค๊ฐ ํ์ํ ๊ฒ ๊ฐ์ ๋ถ๋ถ์ด ์ ์ ์ถ๊ฐ๋๋ฉด์
๊ธ์ด ๋์กํด์ง๊ธฐ ์์ํ์ต๋๋ค..๐
ํ์ํ ๋ถ๋ถ๋ง ์บ์นํ์ ์ ๋ณด์๊ธธ ๋ฐ๋๋๋ค!
'๐ Vue.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Vue.js] Props์ Emits (1) 2024.12.05 [Vue.js] ๋ฐ์์ฑ(Reactivity) ์์คํ (0) 2024.12.04 [Vue.js] ํ ํ๋ฆฟ ๋ฌธ๋ฒ ๋ฐ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ (4) 2024.12.02 [Vue.js] Vue ํ๋ก์ ํธ ๊ตฌ์กฐ ์ดํดํ๊ธฐ (2) 2024.09.24 [Vue.js] Vue3 ์์ํ๊ธฐ (0) 2024.08.27