cover

Vue3에서 플러그인이란 속성, 함수, 라이브러리 등 자주 사용될만한 기능들을 묶어놓은 것을 말합니다. Vue router나 Vuex, Pinia 등 라이브러리 등이 이미 플러그인 형태로 사용되고 있습니다. 어떻게 만들고 사용하는 것인지 알아볼까요?


Plugins

플러그인을 딱 어떻게 사용하라고 정한 건 아니지만 보통 다음과 같은 용도로 사용할 수 있습니다.

글로벌 컴포넌트 등록 (app.component())
글로벌 디렉티브 등록 (app.directive())
앱의 provide 생성 (app.provide())
글로벌 인스턴스 속성 추가 (app.config.globalProperties)
위 항목들을 이용해 라이브러리와 연계 (vue-router, vuex 등)

이 글에서는 라이브러리와 연계하는 것 빼고 한 번씩 간략히 다뤄보겠습니다.

플러그인 파일 만들기

보통은 plugin을 위한 별개의 파일을 만들어서 export하는 식으로 합니다. 여기서는 src/plugins/myInput.js 이란 이름으로 파일을 만들겠습니다. 그리고 install이란 함수를 가진 객체 export하면 됩니다.

javascript
src/plugins/myInput.js
      export default {
	install(app, options) {
		// ...
	}
}
    

아니면 함수를 반환해도 됩니다.

javascript
src/plugins/myInput.js
      export default function (app, options) {
	// ...
}
    

플러그인 사용하기

만약 플러그인을 만들었다면 main.js 파일에서 app의 use 함수를 사용합니다.

javascript
main.js
      import { createApp } from "vue";
import App from "./App.vue";

import MyPlugin from "./plugins/myplugin";

const app = createApp(App);

// use 사용!
app.use(MyPlugin);

app.mount("#app");
    

만약에 플러그인에 전달하고자하는 값이 있다면 두 번째 매개변수로 전달할 수 있습니다.

javascript
      const options = {
	placeholder: 'name',
};
app.use(MyPlugin, options);
    

글로벌 컴포넌트 등록하기

app.component 함수를 이용하면 글로벌 컴포넌트를 등록할 수 있습니다. 만일 install 함수 내에서 이를 사용하면, 플러그인을 사용할 때 컴포넌트가 등록이 됩니다.

우선 임의로 컴포넌트를 만들어보겠습니다.

vue
src/components/MyInput.vue
      <template>
  <input type="text" placeholder="Email" />
</template>
    

그리고 이 컴포넌트를 플러그인에서 글로벌로 등록합니다.

javascript
      import MyInput from "@/components/MyInput.vue";

export default {
  install(app, options) {
    app.component("MyInput", MyInput);
  },
};
    

이미 플러그인을 사용하고 있으니 MyInput 컴포넌트가 글로벌로 등록되었겠죠? 그럼 App.vue에서 사용할 수 있습니다.

vue
App.vue
      <template>
  <MyInput />
</template>
    
loading

글로벌 디렉티브 등록하기

디렉티브는 app.directive()를 이용해서 등록할 수 있습니다. 예를 들어 알파벳을 대문자로 만들어주는 디렉티브 uppercase를 만든다고 해볼게요.

javascript
src/plugins/myplugin.js
      import MyInput from "@/components/MyInput.vue";

export default {
  install(app, options) {
    app.component("MyInput", MyInput);
		
		// 디렉티브 등록!
    app.directive("uppercase", (el) => {
      el.style.textTransform = "uppercase";
    });
  },
};
    

그럼 이 디렉티브를 MyInput에서 사용하면 알파벳이 대문자가 됩니다.

vue
App.vue
      <template>
  <MyInput v-uppercase />
</template>
    
loading

provide 생성

만약 plugin을 등록했을 때 하위 컴포넌트들에 전달하고 싶은 값이 있을 수 있습니다. app.provide 를 이용하면 provide를 생성할 수 있습니다. 예를 들어 플러그인을 사용할 때 options을 전달할 수 있다고 했습니다.

javascript
      const options = {
	placeholder: 'name',
};
app.use(MyPlugin, options);
    

이 값을 provide로 전달해보겠습니다.

javascript
src/plugins/myplugin.js
      import MyInput from "@/components/MyInput.vue";

export default {
  install(app, options) {
    app.component("MyInput", MyInput);

    app.directive("uppercase", (el) => {
      el.style.textTransform = "uppercase";
    });
		// Provide 생성!
    app.provide("myInputOption", options);
  },
};
    

이제 이 값은 하위 컴포넌트 어딘가에서 inject로 가져와 사용할 수 있습니다. MyInput 컴포넌트에서 가져와볼까요?

vue
src/components/MyInput.vue
      <template>
  <input type="text" ref="input" placeholder="Email" />
</template>

<script setup>
import { ref, inject, onMounted } from "vue";

const input = ref(null);

// inject로 option 값을 가져옴
const options = inject("myInputOption");

onMounted(() => {
  input.value.placeholder = options.placeholder;
});
</script>
    

그러면 EMAIL이 NAME으로 바뀐 것을 볼 수 있습니다!

loading

글로벌 인스턴스 속성 추가

app.config.globalProperties 을 이용하면 모든 컴포넌트에서 사용할 수 있는 속성(변수 또는 함수 등)을 만들 수 있습니다.

javascript
      export default {
  install(app, options) {
    app.config.globalProperties.$sayHello = () => {
			console.log("Hello");
    };
  },
};
    

$sayHello 값은 모든 컴포넌트의 속성처럼 들어가기 때문에 편하게 사용하면 됩니다.

javascript
      export default {
	created() {
		this.$sayHello();		
	}
}
    

갑자기 Options API를 사용하는 이유는 Composition API에서는 this를 접근할 수 없기 때문에 $sayHello 함수를 사용할 수가 없습니다. 굳이 사용하려면 provide를 통해 전달하면 됩니다.

javascript
      app.provide('sayHello', app.config.globalProperties.$sayHello);
    

그런데 이렇게 할거면 그냥 함수를 여기다가 넣…