[Vue3] 멀리 있는 컴포넌트간 데이터전송할 땐 mitt

gminnimk·2025년 3월 21일

Vue3

목록 보기
27/39

mitt는 아주 가벼운 이벤트 버스 라이브러리로, Vue3 프로젝트에서 컴포넌트 간의 커뮤니케이션을 보다 간편하게 만들어줍니다.

https://velog.io/@gminnimk/Vue3-provide-inject (provide, inject 개념)


1️⃣ mitt 설정 및 전역 등록

main.js

import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import mitt from 'mitt'

const app = createApp(App)
const emitter = mitt()

// 전역 속성으로 등록하면 Options API에서도 this.$emitter로 접근 가능
app.config.globalProperties.axios = axios
app.config.globalProperties.emitter = emitter

// Vue3의 provide/inject API를 이용하여 자손 컴포넌트에 emitter 제공
app.provide('emitter', emitter)

app.mount('#app')
  • mitt 인스턴스 생성const emitter = mitt()를 통해 mitt 인스턴스를 생성합니다.
  • 전역 등록
    • app.config.globalProperties.emitter에 할당하여 Options API에서도 사용 가능하게 합니다.
    • app.provide('emitter', emitter)를 통해 Vue3의 provide/inject 기능으로 모든 자손 컴포넌트에서 쉽게 접근할 수 있도록 합니다.

2️⃣ 컴포넌트에서 mitt 사용하기

mitt를 사용하는 두 가지 주요 방식은 이벤트 발생(emitting)이벤트 수신(listening).

2.1 이벤트 수신 (Listening)

예시: App.vue

<script setup>
import { ref, onMounted, onUnmounted, inject } from 'vue'
import postData from './assets/postData'
import ContainerBox from "@/components/ContainerBox.vue"
import axios from 'axios'

const step = ref(0)
const post = ref(postData)
const imgUrl = ref('')
const write = ref('')
const selectedFilter = ref('')

// provide로 등록한 emitter를 inject하여 사용
const emitter = inject('emitter')

// 이벤트 핸들러: 필터가 선택되면 실행됨
const handleFilterSelect = (filter) => {
  selectedFilter.value = filter
  console.log("선택된 필터: ", filter)
}

// 컴포넌트가 마운트되면 'filterSelect' 이벤트 구독
onMounted(() => {
  emitter.on('filterSelect', handleFilterSelect)
})

// 컴포넌트가 언마운트되면 이벤트 구독 해제
onUnmounted(() => {
  emitter.off('filterSelect', handleFilterSelect)
})

// ... (더 많은 로직)
</script>
  • inject('emitter')를 통해 main.js에서 제공한 mitt 인스턴스를 받아옵니다.
  • onMounted에서 emitter.on('filterSelect', handleFilterSelect)로 'filterSelect' 이벤트를 구독합니다.
  • onUnmounted에서 emitter.off('filterSelect', handleFilterSelect)로 메모리 누수를 방지하기 위해 이벤트 구독을 해제합니다.

2.2 이벤트 발생 (Emitting)

예시: FilterBox.vue

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

const props = defineProps({
  imgUrl: { type: String },
  filter: { type: String }
})

// inject로 mitt 인스턴스를 받아옴
const emitter = inject('emitter')

// 필터 아이템 클릭 시 emitter.emit을 사용해 이벤트 발생
const selectFilter = () => {
  emitter.emit('filterSelect', props.filter)
}
</script>

<template>
  <div
    @click="selectFilter"
    :class="filter"
    :style="{ backgroundImage: `url(${props.imgUrl})` }"
    class="filter-item"
  >
    {{ filter }}
  </div>
</template>
  • emit() 메서드를 사용하여 'filterSelect' 이벤트를 발생시키며, 인자로 선택된 필터 값을 전달합니다.
  • 이 이벤트는 위의 App.vue에서 구독되어 해당 핸들러가 실행됩니다.

3️⃣ mitt 사용의 장점

  • 경량화: mitt는 매우 가볍고 빠르며, 복잡한 상태 관리 라이브러리 없이 간단한 이벤트 버스를 구현할 수 있습니다.
  • 컴포넌트 간의 독립성 강화: 부모-자식 관계에 제한되지 않고, 깊은 컴포넌트 트리에서도 쉽게 커뮤니케이션이 가능하므로 prop drilling을 피할 수 있습니다.
  • 간편한 등록/해제: onMounted와 onUnmounted 훅을 이용하여 이벤트 구독과 해제를 쉽게 관리할 수 있습니다.

📌 정리

  • mitt 인스턴스 생성 및 전역 등록: main.js에서 mitt 인스턴스를 생성하고 provide와 globalProperties에 등록합니다.
  • 이벤트 구독 (listener): 컴포넌트에서 inject('emitter')를 통해 mitt 인스턴스를 받아 emitter.on()으로 이벤트를 구독합니다.
  • 이벤트 발생 (emitter): 필요한 컴포넌트(예: FilterBox.vue)에서 emitter.emit()을 통해 이벤트를 발생시킵니다.
  • 메모리 관리: 컴포넌트 언마운트 시 emitter.off()로 이벤트 핸들러를 제거하여 메모리 누수를 방지합니다.

0개의 댓글