FrontEnd/Vue

[Vue3] Composition API

Grace 2023. 4. 2. 23:18

Vue3에서 발표한 Composition API에는 크게 반응형 API(Reactivity API), 라이프 사이클 훅(Lifecycle Hooks), 종속성 주입이 있습니다.

API(Reactivity API)

ref(), reactive()와 같은 API를 사용하여 reactive state(반응 상태), computed state(계산된 상태), watcher(감시자)와 같은 것들을 만들 수 있습니다.

<template>
	<div>
		<h2>반응형</h2>
		<p>{{ reactiveMessage }}</p>
		<button v-on:click="addReactiveMesssage">Add message</button>
		<h2>일반</h2>
		<p>{{ normalMessage }}</p>
		<button v-on:click="addNormalMesssage">Add message</button>
	</div>
</template>

<script setup>
import { isRef, onUpdated, ref } from 'vue';

// 반응형 상태 선언
const reactiveMessage = ref('Reactive Message');
// 일반 변수 선언
let normalMessage = 'Normal Message';

console.log('isRef(reactiveMessage): ', isRef(reactiveMessage)); // true
console.log('isRef(normalMessage): ', isRef(normalMessage)); // false

const addReactiveMesssage = () => {
	reactiveMessage.value = reactiveMessage.value + '!';
};
const addNormalMesssage = () => {
	normalMessage = normalMessage + '!';
};

onUpdated(() => {
	console.log('update component');
});
</script>

<style lang="scss" scoped></style>

Vue 인스턴스는 크게 생성(create)되고 DOM에 부착(mount)되고, 업데이터(update)되며, 없어지는(destroy) 4가지 과정을 거치게 됩니다.

종속성 주입

provide(), inject() 는 Reactivity API를 사용하는 동안 Vue의 의존성 주입 시스템을 활용할 수 있게 해줍니다.

parent에 있는 users를 child2에 전달하기 위해 child1에 users를 props로 전달해주어야 하는 의미없는 props 전달이 일어나고, 이런 경우 자식 컴포넌트가 깊을수록 부모에서 자식까지 계속에서 props가 들어가야하는 props drilling 이슈가 발생할 수 있습니다.
이런 경우에 provide와 inject를 이용해서 해결할 수 있습니다.
provide에 의해 생긴 파이프라인을 통해 data를 주고 받을 수 있게 되어, child1을 거치지 않고 child2에서 inject를 통해 users를 받을 수 있게 된다.

// Parent
<template>
  <child1></child1>
</template>

<script setup>
import { provide } from 'vue'

const users = [
      	 { name: "김병훈", age: 29 },
         { name: "김친구", age: 30 }
      ]

provide(users);
</script>

// Child2
<template>
  <div>
    <h3>이름: {{ users.name }}</h3>
    <h4>나이: {{ users.age }} 살</h4>
    <child3></child3>
  </div>
</template>

<script setup>
import { inject } from 'vue'

const users = inject(users)
</script>
💡 모든 props를 provide, inject로 대체해도 되나요?
만약 모든 props를 의존성 주입으로 대체하게 된다면, 어플리케이션 안의 컴포넌트들을 현재의 구조로 묶게되며, 이렇게 되면 리팩토링이 어려워집니다. 전달된 속성들 또한 반응형이 아니게 됩니다. 어플리케이션의 크기가 커지게 될 경우 해당 패턴을 확장하기 쉽지 않기 때문에 디자인적으로 의존성 주입을 중앙 집중형 데이터 저장소로 사용하는 것은 좋지 않습니다.
공유하고자 하는 속성이 일반적이지 않고 앱에 특정되어 있거나, 조상 요소로부터 제공된 데이터를 수정할 필요가 있다면 Vuex(혹은 Pinia)와 같은 상태 관리 라이브러리를 사용하는 것이 좋습니다.