의존성 주입이란?
기존 컴포넌트 기반 아키텍처는 상위에서 하위로 데이터를 전달할 때(props), props를 사용하지 않는 컴포넌트에도 props를 선언하고 전달해야 하는 Props Drilling의 문제가 있었다.
이를 해소하기 위해 redux, recoil, vuex, pinia 등 다양한 상태 관리 라이브러리를 사용하여 props를 전역 변수로 관리하는 방법을 이용하기도 했다.
vue3부터는 vue 자체적으로 중간 컴포넌트를 지나지 않고도 상위에서 하위로 props를 전달할 수 있는 기능을 제공한다.
그것이 바로 의존성 주입(Provide Injection)이다.
즉, props drilling 없이 상위에서 하위로 의존성을 제공하는 것이다.
사용법
사용법 또한 굉장히 간단하다.
상위 컴포넌트에서는 하위로 전달할 데이터, 이벤트를 provide 안에 키-값의 형태로 정의한다.
상위 컴포넌트의 의존성을 주입할 하위 컴포넌트에서는 inject 함수를 사용해 상위의 의존성을 받는다. 이때 provide에 정의했던 키를 활용하여 어떤 의존성을 받을 것인지를 판단한다.
상위 컴포넌트
<template>
<div class="parents">
부모 컴포넌트
<ChildComp />
</div>
</template>
<script setup>
import ChildComp from "@/components/ChildComp.vue";
import { ref, provide } from "vue";
const count = ref(0);
const setCount = {
plus: () => {
count.value++;
},
minus: () => {
count.value--;
},
};
provide("count", { count, setCount });
</script>
<style>
.parents {
background-color: antiquewhite;
}
</style>
중간 컴포넌트
<template>
<div class="child">
<h4>자식 컴포넌트</h4>
<span>단순히 지나가는 용도</span>
<DeepChildComp />
</div>
</template>
<script setup>
import DeepChildComp from "@/components/DeepChildComp.vue";
</script>
<style>
.child {
background-color: coral;
}
</style>
하위 컴포넌트
<template>
<div class="under-child">
하위 자식 컴포넌트
<div>
<p>{{ count }}</p>
<button @click="setCount.plus">+</button>
<button @click="setCount.minus">-</button>
</div>
</div>
</template>
<script setup>
import { inject } from "vue";
const { count, setCount } = inject("count");
</script>
<style>
.under-child {
background-color: aqua;
}
</style>
결과
부모 컴포넌트에 정의한 count 변수를 최하단의 컴포넌트에서 사용 및 변경할 수 있다.
장점
1. Props Drilling으로부터 자유롭다.
2. vuex, pinia와 같은 상태 관리 라이브러리 없이도 전역 변수 관리가 가능하다.
app 수준에서도 provide/inject 를 사용할 수 있다. (=app에서 렌더링되는 모든 컴포넌트에서 사용 가능)
3. 렌더링 퍼포먼스를 개선할 수 있다.
상태 관리 라이브러리를 사용하는 것과 동일하게 props drilling이 발생하지 않기 때문에 불필요한 리렌더링이 감소한다.
4. 변수 및 함수 선언이 쉽다.
vue의 자체 기능이기 때문에 변수, 함수 선언도 vue 문법 그대로이다.
Key
일반적으로 문자열로 키를 사용하는 것이 가장 쉽고 간편하지만, 프로젝트의 규모가 클 경우에는 키의 중복이 발생할 위험이 있다.
그러므로 vue3에서는 provide의 키로 Symbol 데이터 타입을 사용할 것을 권장하고 있다.
- 심볼은 중복이 없는 데이터 타입이다.
[ 참고 자료 ]
'Vue' 카테고리의 다른 글
[ Vue ] defineProps로 정의한 props에 초기 값 설정하기 | withDefaults (0) | 2024.04.23 |
---|---|
[ Vue ] defineProps에 타입을 지정하는 2가지 방법 (0) | 2024.03.27 |
[ Vue ] Vue에서 컴포넌트간 데이터를 주고 받는 방법 | Props & Emit (0) | 2024.03.27 |
[ Vue ] v-slot이란? | v-slot으로 공통 컴포넌트 만들기 (0) | 2024.03.27 |
[ Vue ] v-html 사용을 지양해야 하는 이유 (0) | 2024.03.27 |