[Vue] Provide / Inject vs Props

Seungil Kim·2021년 9월 6일
0

Vue

목록 보기
3/3
post-thumbnail

Provide / Inject vs Props

부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 방법은 두 가지가 있다. 첫 번째 방법은 Props를 이용해 자식 컴포넌트에게 데이터를 전달하는 것이고 두 번째 방법은 Provide와 Inject를 이용해 데이터를 전달하는 것이다. 지금부터 두 방법의 차이점과 장단점을 알아보자.

Props

부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 일반적인 방법이다. 부모 컴포넌트와 자식 컴포넌트는 아래로 단방향 바인딩(one-way-down binding) 을 형성한다. 즉, 부모 컴포넌트에서의 데이터가 업데이트되면, 자식 컴포넌트의 prop들이 새로고침되는 방식이고, 자식 컴포넌트에서 prop를 변경하려 해서는 안 된다는 뜻이다.
일반적으로 다음과 같이 사용한다.

const App = {
  data() {
    return {
      posts: [
        { id: 1, title: 'My journey with Vue' },
        { id: 2, title: 'Blogging with Vue' },
        { id: 3, title: 'Why Vue is so fun' }
      ]
    }
  }
}

const app = Vue.createApp(App)

app.component('blog-post', {
  props: ['title'],
  template: `<h4>{{ title }}</h4>`
})

app.mount('#blog-posts-demo')
<div id="blog-posts-demo">
  <blog-post
    v-for="post in posts"
    :key="post.id"
    :title="post.title"
  ></blog-post>
</div>

부모 컴포넌트의 data에서 사용하고 싶은 것을 자식 컴포넌트의 props에서 선언한다. v-bind로 props를 동적으로 사용할 수 있다.

Provide / Inject

일반적으로는 props를 사용해 데이터를 전달하지만 이게 매우 불편한 상황이 있다. 컴포넌트가 중첩되어 멀리 있는 컴포넌트한테 데이터를 전달해야 하는 상황이다.

다음과 같이 컴포넌트가 구성되어 있을 때, 루트 컴포넌트에서 Grid로 데이터를 전달하고 싶으면 어떻게 해야 할까?

첫 번째 방법은 props를 두번 사용하는 것이다. Root -> Base -> Grid 순서로 전달하면 Grid에서 루트 컴포넌트의 데이터를 사용할 수 있다.

하지만 프로젝트 규모가 커지고 더 많은 컴포넌트가 필요해지면 목적지까지 가는 중간에 껴있는 수많은 컴포넌트의 props에 불필요한 데이터가 전달된다.

두 번째 방법은 provide, inject를 사용하는 것이다.

루트 컴포넌트

<div>
  <active-element
    :topic-title="activeTopic && activeTopic.title"
    :text="activeTopic && activeTopic.fullText"
  ></active-element>
  <knowledge-base
    :topics="topics"
  ></knowledge-base>
</div>
export default {
  data() {
    return {
      topics: [
        {
          id: 'basics',
          title: 'The Basics',
          description: 'Core Vue basics you have to know',
          fullText:
            'Vue is a great framework and it has a couple of key concepts: Data binding, events, components and reactivity - that should tell you something!',
        },
        {
          id: 'components',
          title: 'Components',
          description:
            'Components are a core concept for building Vue UIs and apps',
          fullText:
            'With components, you can split logic (and markup) into separate building blocks and then combine those building blocks (and re-use them) to build powerful user interfaces.',
        },
      ],
      activeTopic: null,
    };
  },
  provide() {
    return {
      topics: this.topics,
    };
  },
};

Grid 컴포넌트 (중첩된 컴포넌트)

<ul>
  <knowledge-element
    v-for="topic in topics"
    :key="topic.id"
    :id="topic.id"
    :topic-name="topic.title"
    :description="topic.description"
  ></knowledge-element>
</ul>
inject: ['topics']

상위 컴포넌트에 provide에 전달하고싶은 데이터를 선언하고, 하위 컴포넌트에서 inject로 받아서 사용한다. 약간 장거리 props 느낌.. 어라? 그러면 그냥 props 안쓰고 provide/inject만 쓰면 되는거 아닐까?

provide, inject의 두 가지 중요한 특징이 있다.

  1. 부모 컴포넌트는 어떤 하위 컴포넌트가 provide된 속성을 사용하는지 알 필요가 없다.
  2. 자식 컴포넌트는 inject된 속성이 어디서 왔는지 알 필요가 없다.

이 특징이 props를 사용해야 할 때와 provide/inject를 사용해야 할 때를 구분해준다고 생각한다.

provide, inject만 사용하면 데이터가 어디에서 어디로 가는지 알 수 없다.
props만 사용하면 멀리 떨어진 컴포넌트에게 데이터를 전달하는게 매우 불편하다.

따라서 두 가지 경우를 적절하게 사용해야 한다!
나중에 Vue 디자인 패턴에 대해 더 공부해봐야겠다.

출처: v3.ko.vuejs.org/guide

profile
블로그 옮겼어용 https://ks1ksi.io/

2개의 댓글

comment-user-thumbnail
2021년 9월 6일

복학하면 저 제자로 받아주세요 ¡¡¡( •̀ ᴗ •́ )و!!!

1개의 답글