티스토리 뷰

 

안녕하세요~ 최근 Vue.js 2의 공식 지원 종료 소식과 함께 많은 프론트엔드 개발자분들이 Vue.js 3로의 마이그레이션을 고민하고 계실 거라 생각합니다.

지난 에서는 Vue.js 2 종료와 관련된 고민들을 언급했었는데요, 이제 본격적으로 마이그레이션 과정을 살펴보며, 구체적인 변경 사항들에 대해 알아보려고합니다.

 

Vue.js 3는 여러 면에서 기존 버전을 크게 개선합니다. 가장 두드러진 변화 중 하나는 성능 향상입니다. Vue 3는 가상 DOM의 재작성, 최적화된 리렌더링, 그리고 업데이트 사이즈 감소를 통해 더 빠른 렌더링 속도와 낮은 메모리 사용량을 제공합니다. 이러한 성능 개선은 특히 대규모 애플리케이션에서 눈에 띄게 나타납니다.

Composition API

코드를 기능별로 재사용하고 조합하기 쉽게 만들어 주어, 컴포넌트 로직을 보다 유연하고 조직적으로 관리할 수 있게 해줍니다.

Vue.js 3에서는 새로 도입된 Composition API를 통해 컴포넌트 로직을 더 유연하게 구성할 수 있습니다. 이는 코드의 재사용성을 높이며, 대규모 애플리케이션에서 가독성과 유지보수성을 크게 향상시킵니다.

  • 재사용성 향상: 로직을 재사용 가능한 함수로 분리하므로, 코드의 중복을 줄일 수 있습니다.
  • 가독성 개선: 관련된 기능들을 함께 묶어 관리하므로, 코드의 가독성을 높일 수 있습니다.
  • 유지보수 용이: 컴포넌트 간의 결합도를 낮추어 기능을 독립적으로 유지보수할 있습니다Composition API는 다음과 같은 이점을 제공합니다:

Vue.js 2

Options API (Vue 2): 데이터와 메서드가 별도의 옵션으로 구성됩니다. 컴포넌트의 다양한 옵션(data, methods, computed 등)을 기능별로 나누어 정의했습니다.이는 간단한 애플리케이션에 적합할 수 있으나, 컴포넌트가 복잡해질수록 관련 로직이 흩어질 수 있습니다.

<template>
  <div>
    <input v-model="name" placeholder="Enter your name">
    <button @click="greet">Greet</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: ''
    };
  },
  methods: {
    greet() {
      alert(`Hello, ${this.name}!`);
    }
  }
};
</script>

 

Vue.js 3

setup 함수를 통해 관련된 기능을 논리적으로 묶을 수 있습니다. 이는 코드의 재사용성과 유지보수성을 향상시키는 데 유리합니다.

<template>
  <div>
    <input v-model="name" placeholder="Enter your name">
    <button @click="greet">Greet</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const name = ref('');
    const greet = () => {
      alert(`Hello, ${name.value}!`);
    };

    return { name, greet };
  }
};
</script>

Reactivity System

Reactivity System은 프레임워크의 반응형 데이터 바인딩 메커니즘을 구현합니다. 이 시스템은 데이터의 변경을 자동으로 감지하고, 이에 따라 사용자 인터페이스를 업데이트합니다.

Vue.js 3의 Proxy 객체는 데이터 변화를 효율적으로 감지합니다. 이는 더 나은 성능과 더 넓은 사용 가능성을 제공합니다.

  • 자동적인 반응성 추적: Vue 3에서는 reactive 또는 ref를 사용하여 모든 객체 속성의 반응성이 자동으로 추적됩니다. 
  • 동적 속성의 반응성: Vue 3에서는 객체에 새로운 속성을 추가하거나 삭제해도, 반응형으로 관리됩니다.

Vue.js 2

data 함수 내에서 반응형 데이터 count를 정의합니다. count 속성의 변경을 감지하기 위해 $watch API를 사용합니다.

export default {
  data() {
    return {
      count: 0
    };
  },
  created() {
    this.$watch('count', (newValue) => {
      // count 속성이 변경될 때 실행될 로직
    });
  }
};

 

Vue.js 3

reactive 함수는 Proxy를 사용하여 state 객체를 반응형으로 만듭니다. count 속성이 변경될 때마다 Vue는 이를 감지하고 관련된 UI를 자동으로 업데이트합니다.

import { reactive } from 'vue';

const state = reactive({
  count: 0
});

// state 객체의 count 속성이 변경될 때 Vue가 자동으로 감지
state.count++;​

reactivity system

Reactivity System은 Vue.js의 반응형 프로그래밍 모델의 핵심입니다. 이 시스템은 애플리케이션의 상태(데이터)가 변경될 때 자동으로 화면을 업데이트합니다. 사용자 인터페이스는 선언적으로 작성되며, 데이터가 변경되면 Vue.js는 이를 감지하고 DOM을 자동으로 업데이트합니다.

  • 자동적인 속성 추적: Vue 3에서는 객체에 새로운 속성을 추가하거나 삭제해도 Vue가 자동으로 반응형으로 관리합니다. 
  • 더 넓은 반응성 범위: Proxy는 배열의 변경과 같은 복잡한 작업을 더 효과적으로 감지합니다.

Vue.js 2

Vue.js 2에서는 Object.defineProperty()를 사용하여 객체의 속성에 접근자(getter/setter)를 정의함으로써 데이터의 반응성을 구현합니다. 이 방식은 객체의 모든 속성에 대해 명시적으로 반응형을 설정해야 하는 제약이 있었습니다.

Vue 2에서는 data 함수를 통해 count 속성을 정의하고, 이 속성의 변경을 자동으로 감지합니다. 그러나 이 방식은 추가된 새로운 속성이나 배열의 변경을 반응형으로 감지하는 데 한계가 있었습니다.

export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment() {
      this.count++;
    }
  }
};


Vue.js 3

Vue.js 3에서는 JavaScript의 Proxy 객체를 활용해 데이터의 반응성을 관리합니다. Proxy는 객체에 대한 작업을 가로채어, 그 작업을 수정하거나 새로운 기능을 추가할 수 있게 합니다. 이는 데이터 변화를 효율적으로 감지하고, 더 빠른 반응 속도를 제공합니다.

reactive 함수는 객체를 반응형으로 만들어줍니다. state.count가 변경될 때마다 Vue는 자동으로 이를 감지하고 관련된 UI를 업데이트합니다.

import { reactive } from 'vue';

const state = reactive({
  count: 0
});

// state.count의 변경을 Vue가 자동으로 감지
state.count++;

Lifecycle Hooks

Composition API는 기능별 코드 조각을 재사용하고 조합하기 쉽게 만들어 주어, 컴포넌트 로직을 보다 유연하고 조직적으로 관리할 수 있게 해줍니다. 이는 특히 대규모 애플리케이션 또는 복잡한 컴포넌트에서 가독성과 유지보수성을 크게 향상시킵니다.

Vue.js 3에서는 몇몇 Lifecycle Hooks의 이름이 변경되었습니다. 이는 Vue 3의 Composition API와의 일관성을 높이고, 이해하기 쉽게 만들기 위한 조치입니다. 

  • beforeDestroy -> before
  • Unmount destroyed -> unmounted 

이러한 이름 변경은 기존의 기능을 그대로 유지하면서, 더 명확한 의미 전달을 위해 이루어졌습니다.

 

vue.js 2

Vue.js 2에서는 beforeDestroy와 destroyed Hooks를 사용합니다.

export default {
  data() {
    return {
      // 데이터 정의
    };
  },
  beforeDestroy() {
    // 컴포넌트가 파괴되기 전에 실행될 로직
  },
  destroyed() {
    // 컴포넌트가 파괴된 후에 실행될 로직
  }
};

vue.js 3

Vue.js 3에서는 beforeUnmount와 unmounted Hooks로 변경되었습니다.

Vue.js 3에서는 Composition API의 setup 함수 내에서 onBeforeUnmount와 onUnmounted 함수를 사용하여 같은 기능을 구현합니다.

import { onBeforeUnmount, onUnmounted } from 'vue';

export default {
  setup() {
    // Composition API 로직

    onBeforeUnmount(() => {
      // 컴포넌트가 언마운트되기 전에 실행될 로직
    });

    onUnmounted(() => {
      // 컴포넌트가 언마운트된 후에 실행될 로직
    });
  }
};

v-model

v-model은 Vue.js에서 폼 입력과 애플리케이션 데이터를 양방향으로 바인딩하는 데 사용됩니다. 일반적으로 v-model은 입력 요소(예: <input>, <select>, <textarea>)에 적용되어 사용자의 입력을 데이터 모델과 실시간으로 동기화합니다.

vue 2

v-model을 사용하여 단일 데이터 속성에 대한 양방향 바인딩을 구현합니다.

CustomInput 컴포넌트에 message 데이터를 v-model을 통해 바인딩합니다. 자식 컴포넌트는 props를 통해 값을 받고, input 이벤트를 통해 부모 컴포넌트에 변경 사항을 전달합니다.

<!-- 부모 컴포넌트 -->
<template>
  <custom-input v-model="message"></custom-input>
</template>

<script>
import CustomInput from './CustomInput.vue';

export default {
  components: {
    CustomInput
  },
  data() {
    return {
      message: 'Hello Vue 2!'
    };
  }
};
</script>

<!-- 자식 컴포넌트 (CustomInput.vue) -->
<template>
  <input :value="value" @input="$emit('input', $event.target.value)">
</template>

<script>
export default {
  props: ['value']
};
</script>

 

vue.js 3

하나의 컴포넌트에 여러 v-model을 사용할 수 있습니다. 이를 통해 다양한 데이터 속성을 독립적으로 바인딩할 수 있습니다.

CustomInput 컴포넌트에 bookTitle과 bookAuthor를 각각 다른 v-model을 사용하여 바인딩합니다. 자식 컴포넌트는 각 입력 필드에 대해 독립적인 props를 받고, 해당 입력 필드의 변경 사항을 emit을 통해 부모 컴포넌트에 전달합니다.

<!-- 부모 컴포넌트 -->
<template>
  <custom-input
    v-model:title="bookTitle"
    v-model:author="bookAuthor"
  ></custom-input>
</template>

<script>
import CustomInput from './CustomInput.vue';

export default {
  components: {
    CustomInput
  },
  data() {
    return {
      bookTitle: 'Vue.js Guide',
      bookAuthor: 'Vue Team'
    };
  }
};
</script>

<!-- 자식 컴포넌트 (CustomInput.vue) -->
<template>
  <input :value="title" @input="$emit('update:title', $event.target.value)">
  <input :value="author" @input="$emit('update:author', $event.target.value)">
</template>

<script>
export default {
  props: ['title', 'author']
};
</script>

Fragments

Fragments는 React에서 처음 도입된 개념으로, Vue.js에서도 Vue3부터 이를 지원하게 되었습니다. Fragment는 여러 개의 루트 노드를 가진 컴포넌트를 가능하게 하는 기능입니다.

vue.js 2

단일 루트 노드만을 가진 컴포넌트를 작성해야 했습니다. 모든 요소는 단일 루트 노드인 <div> 내부에 위치해야 합니다.

<template>
  <div>
    <header>
      <h1>Welcome to my blog.</h1>
    </header>
    <main>
      <article>
        <h2>My first post</h2>
        <p>This is the content of my first post.</p>
      </article>
    </main>
  </div>
</template>


vue.js 3

Fragments 지원으로 인해 다음과 같이 여러 루트 노드를 가진 컴포넌트를 작성할 수 있게 되었습니다. <div>와 같은 불필요한 루트 노드 없이, 여러 개의 루트 노드를 가진 컴포넌트를 작성할 수 있습니다. 이로 인해 DOM 구조가 더욱 단순하고 직관적으로 되며, 불필요한 렌더링을 줄일 수 있습니다.

<template>
  <header>
    <h1>Welcome to my blog.</h1>
  </header>
  <main>
    <article>
      <h2>My first post</h2>
      <p>This is the content of my first post.</p>
    </article>
  </main>
</template>

Slots

슬롯은 Vue.js에서 컴포넌트의 재사용성을 높이기 위해 사용하는 기능입니다. Vue 2에서는 <slot> 태그를 통해 슬롯을 정의했고, slot-scope 속성을 통해 슬롯에 데이터를 전달했습니다.

vue.js 2

<template>
  <div>
    <slot name="header" :data="data"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: 'Hello, World!'
    }
  }
}
</script>
<template>
  <my-component>
    <template slot="header" slot-scope="{ data }">
      <h1>{{ data }}</h1>
    </template>
  </my-component>
</template>

 

vue.js 3

Vue 3에서는 슬롯을 사용하는 방법이 변경되었습니다. 이제는 v-slot 디렉티브를 사용하여 슬롯을 정의하고, 슬롯 props를 통해 슬롯에 데이터를 전달합니다. 이로 인해 슬롯 사용법이 더욱 간단하고 직관적이게 되었습니다.

<template>
  <div>
    <slot name="header" :data="data"></slot>
  </div>
</template>

<script>
export default {
  setup() {
    return {
      data: 'Hello, World!'
    }
  }
}
</script>
<template>
  <my-component>
    <template v-slot:header="{ data }">
      <h1>{{ data }}</h1>
    </template>
  </my-component>
</template>

 

Vue.js 3로의 마이그레이션은 단순히 기술 스택을 업데이트하는 것 이상으로 더 나은 사용자 경험을 제공하고, 더 효율적으로 프로젝트를 관리할 수 있는 기회라고 생각됩니다. 비록 처음에는 새로운 개념과 패턴에 익숙해지는 데 어려움을 겪을 수도 있지만, 결국에는 더 좋은 서비스를 만들 수 있는 토대가 됩니다.

여러분이 Vue.js 3로의 전환을 고려하고 있다면, 글이 유용한 가이드가 되었기를 바랍니다. 변화는 언제나 도전적이지만, 과정에서 배우고 성장하는 것이 우리를 나은 개발자로 만들어 주는 것 같습니다.

감사합니다!

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함