Vue3 Provide와 Inject를 활용하여 Prop Drilling를 해결하기

Provide와 Inject

🗿 Prop Drilling

prop drilling이란 일반적으로 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 때 props 를 사용하는데,

규모가 큰 컴포넌트 트리가 있다면 자손 컴포넌트와 연관된 모든 자식들에게 props를 전달해야하는 것을 말함.

(드릴로 뚫고 내려가는 것 같아서)

 

이러한 문제를 해결하는게 vue3의 provideinject

provide와 inject를 사용하면 부모의 데이터는 계층 구조 상관없이 전달 가능하다.

 

 

🗿 Provide

export default {
    setup() {
    	provide('message', 'hello!');
    },
};

상위 컴포넌트의 setup 함수 내부에서 provide 함수를 사용해서 전달한다.

첫번째 파라미터는 주입할 key, 두번째는 주입할 value

 

 

🗿 Inject

const defaultMessage = inject('defaultMessage', 'default');

하위 컴포넌트의 setup 함수 내부에서 inject 함수를 통해 상위 컴포넌트에서 제공한 데이터를 삽입한다.

반응성 연결도 유지 가능! 두번째 인자를 통해 기본값 설정(default)도 가능하다.

 

 

🗿 Provide & Inject

const message = ref('Hello World!');
const updateMessage = () => {
	message.value = 'world!';
};
provide('message', { message, updateMessage });

provide, inject를 반응성 데이터로 제공할 때 가능하면 모든 변경은 provide 내부에서 하는게 좋다. (유지관리를 위해!)

데이터 변경은 provide쪽에서 변경 메서드를 제공하는게 좋다.

 

provide('count', readonly(count));

데이터 변경을 아예 막고 싶으면 provide로 제공할 때 readonly로 막아버릴 수 있다.

대규모 애플리케이션에서 다른 개발자와 함게 작업할 때 잠재적 충돌을 피하기 위해 Symbol 주입 키를 사용하는 게 좋다.

 

 

🗿 App-level Provide

// main.js
const app = createApp(App);

// App-level Provide
app.provide('msg', '글로벌 프로퍼티');

app.mount('#app');
setup() {
    // App-level Provide global property
    const msg = inject('msg');
    console.log(msg);
    return { };
},

이러한 Provide와 Inject를 통해 App-level Provide를 설정하여 전역으로 사용할 수 있다. (플러그인 작성에 유용)

 

// main.js
const app = createApp(App);

// Vue2방식의 global property (setup에서는 접근할 수 없음..)
app.config.globalProperties.msg = '글로벌 프로퍼티';

app.mount('#app');

vue2에서는 app.config.globalProperties 를 활용했지만 이는 vue3의 setup함수 내부에서는 사용이 불가.

대신 vue3에서는 main.js에서의 provide, inject를 통해 가능하다