πŸ“— Vue.js

[Vue.js] μ»΄ν¬λ„ŒνŠΈ κ°œλ… 및 μ‚¬μš©λ²•

JaeBBang 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개의 μ»΄ν¬λ„ŒνŠΈ 좜λ ₯

의 과정을 거치게 λ©λ‹ˆλ‹€.

 

결과물은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

μ»΄ν¬λ„ŒνŠΈμ— λŒ€ν•œ μ„€λͺ…λ§Œ ν•˜κΈ° μœ„ν•΄ μž‘μ„±μ„ ν•˜μ˜€λŠ”λ°, 쀑간쀑간 ν•„μš”ν•  것 같은 뢀뢄이 점점 μΆ”κ°€λ˜λ©΄μ„œ

글이 λ‚œμž‘ν•΄μ§€κΈ° μ‹œμž‘ν–ˆμŠ΅λ‹ˆλ‹€..πŸ˜…

 

ν•„μš”ν•œ λΆ€λΆ„λ§Œ μΊμΉ˜ν•˜μ…”μ„œ λ³΄μ‹œκΈΈ λ°”λžλ‹ˆλ‹€!