ABOUT ME

์—ด์‹ฌํžˆ ์‚ด์•„์•ผ ๋จน๊ณ ์‚ด์ง€๐Ÿ˜‰

Today
Yesterday
Total
  • [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๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ ์ถœ๋ ฅ

    ์˜ ๊ณผ์ •์„ ๊ฑฐ์น˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

     

    ๊ฒฐ๊ณผ๋ฌผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ์„ค๋ช…๋งŒ ํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑ์„ ํ•˜์˜€๋Š”๋ฐ, ์ค‘๊ฐ„์ค‘๊ฐ„ ํ•„์š”ํ•  ๊ฒƒ ๊ฐ™์€ ๋ถ€๋ถ„์ด ์ ์  ์ถ”๊ฐ€๋˜๋ฉด์„œ

    ๊ธ€์ด ๋‚œ์žกํ•ด์ง€๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค..๐Ÿ˜…

     

    ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์บ์น˜ํ•˜์…”์„œ ๋ณด์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค!

Designed by Tistory.