Provide(제공)/Inject(주입)에 대하여

감나무·2025년 4월 21일

vue

목록 보기
3/4
post-thumbnail

들어가기

vue에서 props 를 통해 부모 -> 자식으로 데이터를 전달하는 건 익숙한 방법이다.
하지만 컴포넌트가 구조적 깊어지고 또 중간 컴포넌트가 해당 데이터를 저혀 사용하지 않을 경우 props 드릴링 이라는 문제가 발생이 된다. 하지만 vue에서는 이러한 상황에서 실용적으로 사용 할 수 있는 provide/inject API가 존재한다.

📌props 드릴링(prop drilling) 이란?
부모 컴포넌트의 데이터를 깊게 중첩된 자식 컴포넌트에 전달하기 위해 중간 컴포넌트들을 거쳐 계속 props로 전달해야 하는 상황을 말한다.
문제점

  • 중간 컴포넌트들이 그 데이터를 직접 사용하지 않는데도 props를 계속 받아야 함
  • 컴포넌트 구조가 복잡해질수록 유지보수 어렵고, 버그가 생기기 쉬움
  • prop 구조 변경 시 전체 체인이 영향을 받음

그럼 이 문제 provideinject로 props 드릴링을 해결할 수 있습니다. 부모 컴포넌트는 모든 자식 컴포넌트에 대한 의존성 제공자 역할을 할 수 있습니다. 하위 트리의 모든 컴포넌트는 깊이에 관계없이 상위 체인의 컴포넌트에서 제공(provide)하는 의존성을 주입(inject)할 수 있습니다.

Provide

컴포넌트의 하위 항목에 데이터를 제공하려면 Provide() 함수를 사용해야한다.

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

provide(/* 키 */ 'message', /* 값 */ '안녕!')
</script>

// 또는

<script>
import { provide } from 'vue'

export default {
  setup() {
    provide(/* 키 */ 'message', /* 값 */ '안녕!')
  }
}
</script>

Provide() 함수는 두 개의 인자를 허용한다. 첫 번째는 인자는 주입 키, 두 번째 인자는 제공되는 값을 의미한다.

앱 수준의 provide

<script>
import { createApp } from 'vue'
const app = createApp({})
app.provide(/* 키 */ 'message', /* 값 */ '안녕!')
</script>

또한, 앱 수준에서 제공할 수도 있다. 앱 수준 제공은 앱에서 랜더링 되는 모든 컴포넌트에서 사용이 가능하다 . 이는 플러그인은 일반적으로 컴포넌트를 사용하여 값을 제공할 수 없기 때문에 플러그인을 작성할 때 특히 유용한다.

Inject

부모 컴포넌트에서 제공하는 데이터를 주입하려면 inject()함수를 사용해야한다.

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

const message = inject('message')
</script>

사용 시 ref를 주입받으면 그대로 전달되며, 자동으로 .value 해제되지 않음 이는 사용할때

자식에서 ref.value로 직접 접근해야 함

이 덕분에 provide와의 반응형 연결이 유지된다.

Inject 기본값 설정

<script setup>
// 값이 제공되지 않았을 경우 fallback
const value = inject('key', '기본값')

// 팩토리 함수로 생성 
const value = inject('key', () => new HeavyClass(), true)
</script>

key에 해당하는 값이 provide되지 않았다면 → "기본값"이 그대로 사용됨
key 없으면 new Obj() 실행해서 그걸 기본값으로 사용

반응형 값 공유도 가능

// 제공자
<script setup>
const count = ref(0)
provide('count', count)
</script>

// 주입자
<script setup>
const count = inject('count')
</script>

이는 ref를 전달하면 양방향 반응성이 유지가되며, 자식 컴포넌트에서 .value를 통해 상태를 읽거나 갱신이 가능하다.

📌 만약 provide로 전달한 값이 자식 컴포넌트에서 변경되면 안 되도록 하고 싶다면 readonly()로 감싸서 읽기 전용으로 만들 수 있다.

Symbol을 키로 사용하는 이유

대규모 앱 또는 라이브러리에서 key 충돌을 방지하려면 문자열이 아닌 Symbol을 쓰는 것이 좋다. 이유는

  • symbol은 충돌 가능성이 없고, 명시적인 import로 의존성이 명확해진다.
  • 실무에서는 컴포넌트마다 keys.ts 등을 따로 두고 관리하는 방식이 흔하다.

참고자료
https://ko.vuejs.org/guide/components/provide-inject.html

profile
여기저기

0개의 댓글