• Vue.js Slot: 슬롯은 왜 필요한가? :: 마이구미
    Vue.js 2017. 12. 2. 22:45
    반응형

    이 글은 Vue.js 에서 제공하는 <slot> 요소에 대해 다룬다.

    크게 Slots, Named Slots, Scoped Slot 기능을 위한 예제를 통해 진행한다.

    관련 문서 - https://kr.vuejs.org/v2/guide/components.html#슬롯을-사용한-컨텐츠-배포

    참고 링크 - https://skyronic.com/blog/vue-slots-example

    최종 예제 - https://codesandbox.io/s/y0z5ql6911

    2019/4/22 업데이트 수정


    • Slots
    • Named Slots
    • Scoped Slot


    뷰를 접했다면 아마 슬롯에 대한 문서를 이미 읽었을 것이다.

    본인은 문서를 통해 슬롯을 이해했을 때, 어렵지 않게 이해할 수 있다.

    하지만 왜 쓰는거지? 확 와닿지 않았다.


    다음 의미를 이해한다면 슬롯을 이해했다고 보면 된다.


    Vue.js는 현재 웹 컴포넌트 사양 초안을 모델로 한 콘텐츠 배포 API를 구현하며 원본 콘텐츠의 배포판 역할을하기 위해 특수한 <slot> 엘리먼트를 사용합니다.


    결론적으로 슬롯은 컴포넌트 자체의 재사용성을 높이는 데 사용된다.

    슬롯이 무엇인지 예제를 통해 알아본다.


    레이아웃에 관련된 예제를 살펴보자.

    모든 페이지의 레이아웃에는 팝업을 사용하는 영역이 항상 존재한다고 가정한다.

    그렇다면, 다음과 같이 작성할 수 있을 것이다.


    => Layout.vue
    <div id="container">
        <div class="popup">{{ popupTitle }}</div> 
    </div>


    그리고 우리는 이 컴포넌트를 레이아웃이 필요로하는 곳에서 항상 사용하고 싶다.


    첫 페이지에 대한 레이아웃을 만들어달라는 요청이 왔다고 가정한다.

    요청 사항은 다음과 같다.


    • 크게 Header, Body, Footer 로 구성된다.


    Layout 컴포넌트를 사용하면서, 이를 처리하기 위해서는 Vue 에서 제공하는 슬롯 기능을 사용할 수 있다.

    기본적인 슬롯인 단일 슬롯을 통해 구현하면 다음과 같다.


    => Home.vue

    <app-layout> <div id="header"> <h1>Header Area</h1> </div> <div id="body"> <h1>Body Area</h1> </div> <div id="footer"> <h1>Footer Area</h1> </div> </app-layout>


    => Layout.vue

    <div id="container"> <slot></slot> <div class="popup">{{ popupTitle }}</div> </div>


    슬롯은 컴포넌트 태그 내부에 작성된다.

    위와 같이 Layout 컴포넌트를 사용하는 곳(부모)에서 추가적인 코드를 작성하고, Layout 컴포넌트 수정없이 그대로 사용할 수 있는 모습을 볼 수 있다.


    다른 페이지의 레이아웃을 만들어보자.


    • 크게 Header, Body, Footer, Sidebar 로 구성된다.


    => About.vue

    <app-layout>

    <div id="sidebar">

    <h3>Sidebar Area</h3> </div>

    <div id="header"> <h1>Header Area</h1> </div> <div id="body"> <h1>Body Area</h1> </div> <div id="footer"> <h1>Footer Area</h1> </div> </app-layout>


    여기서 만약 영역이 계속 추가되면 어떻게 될까?

    점점 많아질수록, 우리는 어떤 영역이 슬롯으로 넘어오는 지 어느 정도 추측은 해야할 것이다.


    하지만 슬롯 기능은 부모에서 작성되기 때문에 Layout 컴포넌트는 무언가를 전달받지만, 무엇인지는 알 수 없다.


    하지만 추측할 수 있다면, 컴포넌트 작성에 있어 훨씬 도움이 될 것이다.

    이를 위해 우리는 제공되는 Named-slots 기능을 사용할 수 있다.


    See the Pen Name slot in vue.js by leejunghyun (@mygumi) on CodePen.


    위와 같이 슬롯에 대해 이름을 정의해서 사용할 수 있게 된다.


    결론적으로 컴포넌트는 스스로가 아닌 외부에서 제공하는 것과 함께 컴포넌트가 결정되는 것을 확인할 수 있다.

    이러한 흐름을 통해 슬롯은 원본은 유지하면서 원하는 콘텐츠를 배포하는 역할을 할 수 있다.




    위에서 다룬 Named Slots 기능은 굉장히 유용해보인다.

    또한 슬롯에는 다른 목적을 가진 유용한 기능이 Scoped Slot 존재한다.


    지금까지는 이해를 돕기 위한 예제로, 다소 와닿지않을 수 있다.

    이번에는 실제로 활용할 수 있는 예제를 통해 Slot, Named Slots, Scoped Slot 을 접해보자.


    예제의 시나리오는 다음과 같다.

    현재 볼륨을 제어하는 로직이 존재한다.



    추가적으로, 볼륨에 대한 상태를 나타내는 진행바를 추가하길 원한다.



    여기서 이미 볼륨 컴포넌트는 존재하고, 여러군데에서 재사용하고 있는 진행바에 대한 컴포넌트도 존재한다.

    볼륨에 관한 데이터는 볼륨 컴포넌트가 가지고 있다고 가정한다.


    <progressbar
        :show=""
        :now=""
        :end=""
    />


    그렇다면, 사실상 볼륨 컴포넌트의 자식으로 진행바 컴포넌트를 배치하면 다루기가 편하다.

    진행바 컴포넌트는 볼륨 컴포넌트의 데이터를 그대로 props 형태로 전달해주기만 하기 때문이다.


    Volume.vue


    <div class="volume-container">

        <progressbar
            :show="aliveEvent"
            :now="volume"
            :end="100"
        />

    </div>


    하지만 볼륨 컴포넌트에 선언할 경우, 다소 재사용성이 떨어지게 된다.

    우리는 이것은 슬롯을 통해 문제를 해결할 수 있다.


    <volume>

        <progressbar/>

    </volume>


    이를 통해 볼륨 컴포넌트에 영향을 끼치지 않았지만, 다른 문제점이 존재한다.

    볼륨 컴포넌트에 배치했을 때는 볼륨 데이터를 쉽게 props 으로 전달할 수 있었다.

    하지만 위처럼 슬롯을 이용할 경우, ProgressBar 에 볼륨 데이터를 전달하기에, 다소 매끄럽지 않게 된다.


    일반적인 슬롯의 장점은 컴포넌트의 템플릿의 재사용성에 가깝다.

    그렇기에, 데이터 관점에서는 위와 같은 문제점이 있다.


    그렇다면 어떻게 해결할 수 있을까? 

    이를 위해 제공되는 것이 Scoped Slot 이다.


    슬롯이 템플릿의 재사용성이라면, Scoped Slot 는 데이터의 재사용성이라고 볼 수 있다.

    Scoped Slot 은 하위 컴포넌트의 값을 상위 컴포넌트에서 접근할 수 있게 해준다.


    <volume>

        <progressbar 

            slot-scoped="slotProps" 

            :show="slotProps[볼륨 컴포넌트 데이터 변수명]"

            :now="slotProps[볼륨 컴포넌트 데이터 변수명]"

            :end="slotProps[볼륨 컴포넌트 데이터 변수명]"

        />

    </volume>


    결과적으로, 슬롯을 통해서도 볼륨 컴포넌트의 데이터에 접근해서 사용할 수 있게 된다.

    보다시피, 굉장히 유용하게 사용할 수 있다.

    슬롯의 대한 기능은 이외에도 많고, 현재에도 계속해서 추가적인 기능이 업데이트되고 있다.


    마지막으로 예제에 대한 전체적인 코드를 참고하길 바란다.

    예제를 글로 설명하기에는 다소 부족한 면이 있기에, 예제를 통해 이해하면 훨씬 좋을 것이다.



    반응형

    댓글

Designed by Tistory.