플러그인 작성
플러그인은 Vue 앱에 전역 수준의 기능을 추가하는 방법입니다. 앱 전체에서 사용하는 컴포넌트, 디렉티브, provide/inject를 한 번에 등록할 수 있습니다.
면접에서 "Vue 플러그인을 만들어본 적이 있나요?"라는 질문에, install 함수의 구조와 앱 인스턴스 API를 설명할 수 있으면 좋습니다.
플러그인 구조
// plugins/myPlugin.ts
import type { App, Plugin } from 'vue'
// 방법 1: install 메서드가 있는 객체
export const myPlugin: Plugin = {
install(app: App, options?: { greeting?: string }) {
// 1. 전역 컴포넌트 등록
app.component('GlobalAlert', {
template: '<div class="alert"><slot /></div>'
})
// 2. 전역 디렉티브 등록
app.directive('highlight', {
mounted(el: HTMLElement, binding) {
el.style.backgroundColor = binding.value || 'yellow'
}
})
// 3. provide — 모든 컴포넌트에서 inject 가능
app.provide('greeting', options?.greeting || '안녕하세요')
// 4. 전역 속성 추가 (Options API에서 this로 접근)
app.config.globalProperties.$format = (date: Date) => {
return date.toLocaleDateString('ko-KR')
}
}
}
// 방법 2: install 함수 자체를 플러그인으로
export function createLogger(): Plugin {
return {
install(app: App, options?: { level?: string }) {
const logger = {
log: (...args: any[]) => console.log('[LOG]', ...args),
warn: (...args: any[]) => console.warn('[WARN]', ...args),
error: (...args: any[]) => console.error('[ERROR]', ...args)
}
app.provide('logger', logger)
}
}
}
// main.ts
import { createApp } from 'vue'
import { myPlugin, createLogger } from './plugins/myPlugin'
const app = createApp(App)
app.use(myPlugin, { greeting: '환영합니다!' })
app.use(createLogger())
app.mount('#app')
실전 플러그인 — 국제화(i18n) 간이 버전
// plugins/i18n.ts
import type { App, Plugin, InjectionKey } from 'vue'
interface I18nMessages {
[locale: string]: Record<string, string>
}
interface I18n {
t: (key: string) => string
locale: string
setLocale: (locale: string) => void
}
export const I18nKey: InjectionKey<I18n> = Symbol('i18n')
export function createI18n(messages: I18nMessages): Plugin {
return {
install(app: App) {
let currentLocale = 'ko'
const i18n: I18n = {
t(key: string) {
return messages[currentLocale]?.[key] || key
},
get locale() {
return currentLocale
},
setLocale(locale: string) {
currentLocale = locale
}
}
app.provide(I18nKey, i18n)
// 전역 속성으로도 제공 (Options API 호환)
app.config.globalProperties.$t = i18n.t
}
}
}
// main.ts
import { createI18n } from './plugins/i18n'
app.use(createI18n({
ko: {
'greeting': '안녕하세요',
'button.submit': '제출',
'button.cancel': '취소'
},
en: {
'greeting': 'Hello',
'button.submit': 'Submit',
'button.cancel': 'Cancel'
}
}))
<script setup lang="ts">
import { inject } from 'vue'
import { I18nKey } from '@/plugins/i18n'
const i18n = inject(I18nKey)!
</script>
<template>
<p>{{ i18n.t('greeting') }}</p>
<button>{{ i18n.t('button.submit') }}</button>
</template>
전역 속성의 TypeScript 타입 확장
// types/vue-global.d.ts
declare module 'vue' {
interface ComponentCustomProperties {
$format: (date: Date) => string
$t: (key: string) => string
}
}
export {}
플러그인 vs Composable
| 항목 | 플러그인 | Composable |
|---|---|---|
| 범위 | 앱 전역 | 컴포넌트 단위 |
| 등록 | app.use() | import + 호출 |
| 용도 | 전역 설정, 인프라 | 특정 기능 로직 |
| 예시 | 라우터, 상태 관리, i18n | useMouse, useFetch |
면접 팁
- Vue Router, Pinia 같은 공식 라이브러리도 플러그인 구조(
app.use())를 따릅니다 - 플러그인은 앱 초기화 시 한 번 실행되는 설정 이라는 점에서 Composable과 다릅니다
app.config.globalProperties는 Options API 호환용이며, Composition API에서는 provide/inject가 권장됩니다
요약
Vue 플러그인은 install 메서드를 통해 전역 컴포넌트, 디렉티브, provide/inject, 전역 속성을 한 번에 등록합니다. 앱 인프라 수준의 기능(i18n, 로깅, 분석)에 적합하며, 특정 기능 로직은 Composable을 사용하는 것이 더 적합합니다.
댓글 로딩 중...