vue.js EventBus를 활용한 컴포넌트간 데이터 공유


프론트엔드 프레임워크를 사용하다보면 왠지 모르게 빡빡하게 짜여져 제공되는 것들 때문에 데이터의 흐름이나 여러 핸들링을 처리하기에 어려움을 겪기도 합니다. 제가 현재 작성하고 있는 Vue.js의 경우도 이러한 부분 때문에 클래식(?)스타일로 웹개발을 하시는 분들은 부담스러운 부분들도 있습니다. 데이터의 흐름을 쉽게 하기 위해 vuex라는 외부라이브러리가 있고, 메소드들을 서로 호출할 수 있도록 도와주는 EventBus라는 방법이 있습니다. 저는 이러한 것들 중에서 EventBus라는 것의 대해서 살펴보고 예제를 작성해보려 합니다.

이벤트를 사용하는 이유

일반적으로 메소드, 변수를 정의할 때 한 오브젝트나 컴포넌트 단위로 묶어서 사용되기 때문에 이벤트를 사용할 필요가 없이 현재위치에 포함된 메소드/변수를 호출하여 사용할 수 있습니다. 하지만 각각 분리되어 있는 개체에 전송하거나 알려줘야한다면 어떻게 해야할까요? 이럴때 공통으로 데이터들을 주고 받을 수 있는 공간을 만들고, 이를 통해서 서로 규격에 맞춰 데이터들을 주고 받으면 될 것 입니다. 과거 스마트폰이라는 개념이 나오기 전까지는 푸시라는 것이 생소하고 잘 사용하지도 않았으며, 이보다는 정기적으로 데이터를 긁어오는 폴링이라는 것이 더 사용했던 것 같습니다. 하지만 최근에는 푸시라는 용어와 함께 토픽, 구독, 발행등의 단어들을 사용하고 있는데 제 개인적으로는 이러한 것들이 이벤트와 비슷한 개념으로 받아들여도 되지 않을까라고 조심스럽게 의견을 내봅니다. 이벤트를 등록하고 받을 준비가 끝났다면 언제 어디서든지 데이터들을 주고 받고, 각 이벤트요청 상황에 따라 원하는 메소드들을 수행할 수 있을 것입니다.

vue.js의 EventBus

vue.js에서 이벤트를 쉽게 다루기 위해 EventBus라는 개념을 이용할 수 있으며, 누구나 쉽게 사용할 수 있습니다.

// 이벤트버스 생성
var EventBus = new Vue()
// 이벤트 발행
EventBus.$emit('message', 'hello world');
// 이벤트 구독
EventBus.$on('message', function(text) {
    console.log(text);
});

자, 이렇게 하여 vue.js에서 이벤트를 쉽게 활용할 수 있습니다. 위와 같이 구현해놓는다면 컴포넌트가 전혀 다르더라도 서로 쉽게 호출할 수 있습니다.

컴포넌트간 이벤트 주고받기

컴포넌트보다 한단계 위의 단계인 VueApp간의 이벤트 공유로 예제를 드리도록 하겠습니다. (제가 EventBus를 보면서 컴포넌트끼리 데이터주고 받는 것보다 극단적인 상황인 App단계에서의 이벤트공유가 가능여부가 더 궁금했었고, 이 글을 읽고 계신분들도 이 예제가 더 도움이 많이 될 것 같아 이렇게 진행했습니다.)

<div id="sender-app">
    <input v-model="text">
    <button @click="sender">sender</button>
    <div v-if="receiveText">#sender-app: I sent a message a </div>
</div>
<div id="receiver-app">
    <div v-if="text">#receiver-app: </div>
</div>
var EventBus = new Vue();

var SenderApp = new Vue({
    el: '#sender-app',
    data() {
    	return {
            text: '',
            receiveText: ''
        }
    },
    created() {
    	EventBus.$on('message', this.onReceive);
    },
    methods: {
    	sender() {
            EventBus.$emit('message', this.text);
            this.text = '';
        },
        onReceive(text) {
            this.receiveText = text;
        }
    }
});

var ReceiverApp = new Vue({
    el: '#receiver-app',
    data() {
    	return {
            text: ''
        }
    },
    created() {
    	EventBus.$on('message', this.onReceive);
    },
    methods: {
    	onReceive(text) {
            this.text = text;
        }
    }
});

위 예제에서 확인했듯이 SenderAppReceiverApp이 서로 다른 VueApp임에도 불구하고 EventBus를 통해 이벤트를 공유할 수 있습니다.

만약에 EventBus를 공용으로 사용하는 것이 아닌 Vue내에서만 사용하고 싶으시다면 아래와 같이 Vue내장함수로 사용할 수 있습니다.

(function() {

    var EventBus = Vue();

    Object.defineProperties(Vue.prototype, {
        $eventBus: {
            get: function () {
                return EventBus;
            }
        }
    }
})();

관련 예제는 Github을 통해 공유되어 있으며, 궁금한 내용있으시면 Github Issue를 통해 언제든지 알려주시면 감사하겠습니다.

참고자료



위 링크를 통해 후원을 받고 있습니다. 모든 후원금은 Vue.js 한국 커뮤니티 운영에 사용됩니다.