여전히 좋은 선택이지만, props가...
Vue같은 SPA 프레임워크에서의 데이터는 부모에서 자식으로 이동하는 것을 원칙으로 합니다.
그러다 보니 프로젝트를 진행하다 보면 컴포넌트들 간에 계층 구조가 생기기 마련입니다.
이러한 계층 구조에서 컴포넌트 간에 정보를 주고 받을 때, 보통 부모 컴포넌트에서 자식 컴포넌트로 props를 내려주는 방식을 사용합니다.
Props
property의 약자로, 부모이게서 받은 데이터를 말합니다. props에 있는 데이터들은 수정이 불가능하며 오직 안에 있는 값을 꺼내서 사용할수만 있습니다.
그러나 이러한 계층 구조가 깊어지는 경우 반복해서 props를 사용해 데이터를 전달해야 하므로 번거로움이 발생하게 된다. 이런 경우 provide와 inject를 사용해 중간 컴포넌트들을 건너뛰고 원하는 컴포넌트에서 바로 데이터를 전달받을 수 있습니다.
provide는 상위 컴포넌트에서 전달하고자 하는 값을, inject에서는 상위 컴포넌트에서 받고자 하는 값을 정의하면 됩니다.
간단한 예시와 함께 알아보자
프로젝트 구조는 다음과 같습니다.
prop1 은 props 를 통해 Child 로, 다시 Child 에서 Inject 로 이동합니다.
Child 는 Inject 컴포넌트를 호출하며 props 로 prop2 데이터를 넘깁니다.
결과적으로 Provide.vue 에서 Inject.vue 로 prop1 이라는 값을 전달하기 위해 두 단계를 거쳐야 하는 것이다. 이런식으로 props 를 통해 데이터들을 전달한다면 컴포넌트 하나를 거칠 때마다 전달할 데이터들이 쌓이게 될 것입니다.
하위 컴포넌트에서 전달받은 값들을 변경하기 위해 emit 을 사용해야 하는 일이라도 발생한다면 상당히 골치 아파질 수 있다. 그 emit 또한 모든 중간 과정에 있는 component 들에 선언되어야 할 테니 말이다. 이런 상황에서 provide 와 inject 의 필요성이 빛을 발합니다.
우선 provide 를 통해 prov1 변수에 provide1 이라는 Key 값을 등록한다. 변수에 등록된 이 Key 값을 inject 함수의 인자로 받게 되면 변수 간에 의존성이 생기게 된다. 즉, 변수 prov1 의 값이 inject1 변수로 전달되는 것입니다.
그럼 이제 다음과 같은 계층 구조가 완성되었습니다.
provide 는 props 와 마찬가지로 데이터를 여러 가지 형태로 전달할 수 있다. 단순히 값 하나를 전달할 수도 있는 반면, 컴포넌트 자체를 전달할 수도 있습니다.
먼저, provide 를 통해 전달할 간단한 컴포넌트를 만듭니다.
위의 컴포넌트는 slot 으로 값을 받아서 화면에 띄우도록 구성되어 있습니다. 그럼 이제 Provide.vue 와 Inject.vue 를 아래와 같이 수정해 봅시다.
prov2 변수에 TestComponent 컴포넌트를 할당합니다. 이때, {{ }} 사이에 있는 객체는 TestComponent 에 전달되는 속성을 설정합니다. 이렇게 prov2 변수에 할당된 값은 Inject.vue 에 있는 inject2 에 전달됩니다.
주목해야 할 점은, inject2에 할당된 값을 inject1이나 inject3 처럼 template에서 변수 형태 그대로 사용하면 안 된다는 것입니다. Vue 에서는 컴포넌트를 데이터로 바인딩 할 때 문자열로 인식하기 때문에 {{inject2}} 와 같은 형태로 사용하게 되면 무슨 뜻인지 모를 이상한 문자들을 볼 수 있습니다. 그러므로 위와 같이 동적 컴포넌트를 사용해 데이터로 넘어온 컴포넌트를 처리해야 합니다.
마지막으로 Provide.vue 에 prov3 변수의 값을 증가시키는 button 을 추가했습니다. prov3 변수의 값이 증가함에 따라 inject3 변수의 값도 증가할 것이며, 반대로 inject3 의 값이 변함에 따라 prov3 의 값 또한 영향을 받을 것입니다.
props 로 전달된 값들 뿐만 아니라, TestComponent 에 전달된 값과 prov3 가 증가함에 따라 변화된 값 모두 잘 전달된 것을 볼 수 있습니다.
마치며
언뜻 보기에 provide / inject 를 사용하는 것이 props 로 데이터를 전달하는 방식보다 간편하게 느껴질 수 있습니다. props 와는 다르게 명시적으로 선언되는 것들이 적기 때문에 그렇습니다. 하지만 그렇기 때문에 프로젝트의 규모가 커지게 되면 컴포넌트들 간의 계층 구조를 파악하고 데이터들을 추적하기 어려워집니다. 이것은 생각보다 큰 문제를 야기할 수 있습니다.
그럼에도 불구하고 반드시 최상위 컴포넌트에만 존재해야 하는 요소가 있어 의존성을 받을 컴포넌트와의 계층 구조 상 깊이 차이가 크게 날 수 밖에 없는 등의 특수한 상황에서는 provide / inject 가 여전히 좋은 선택지가 될 수 있습니다.
하지만 위와 같이 특수한 상황은 매우 적기 때문에, 웬만하면 얌전히 props 를 사용하는 것을 추천하는 바 입니다.
©2023 thecompass. All rights reserved