plugins

Nuxt는 Vue 애플리케이션이 생성될 때 Vue 플러그인 등을 사용하기 위한 플러그인 시스템을 제공합니다.

Nuxt는 app/plugins/ 디렉터리의 파일을 자동으로 읽고 Vue 애플리케이션이 생성될 때 로드합니다.

안의 모든 플러그인은 자동으로 등록되며, nuxt.config에 따로 추가할 필요가 없습니다.
파일 이름에 .server 또는 .client 접미사를 사용하여 플러그인을 서버 또는 클라이언트 측에서만 로드할 수 있습니다.

Registered Plugins

디렉터리의 최상위에 있는 파일(또는 하위 디렉터리 내의 index 파일)만 플러그인으로 자동 등록됩니다.

Directory structure
-| plugins/
---| foo.ts      // scanned
---| bar/
-----| baz.ts    // not scanned
-----| foz.vue   // not scanned
-----| index.ts  // currently scanned but deprecated

foo.tsbar/index.ts만 등록됩니다.

하위 디렉터리에 있는 플러그인을 추가하려면, nuxt.config.tsapp/plugins 옵션을 사용할 수 있습니다:

nuxt.config.ts
export default defineNuxtConfig({
  plugins: [
    '~/plugins/bar/baz',
    '~/plugins/bar/foz',
  ],
})

Creating Plugins

플러그인에 전달되는 유일한 인자는 nuxtApp입니다.

plugins/hello.ts
export default defineNuxtPlugin((nuxtApp) => {
  // nuxtApp으로 무언가를 수행
})

Object Syntax Plugins

더 고급 사용 사례를 위해 객체 문법을 사용하여 플러그인을 정의하는 것도 가능합니다. 예를 들어:

plugins/hello.ts
export default defineNuxtPlugin({
  name: 'my-plugin',
  enforce: 'pre', // 또는 'post'
  async setup (nuxtApp) {
    // 이것은 일반 함수형 플러그인과 동일합니다
  },
  hooks: {
    // 여기에서 Nuxt 앱 런타임 훅을 직접 등록할 수 있습니다
    'app:created' () {
      const nuxtApp = useNuxtApp()
      // 훅에서 무언가를 수행
    },
  },
  env: {
    // 서버 전용 또는 아일랜드 컴포넌트를 렌더링할 때 플러그인이 실행되지 않도록 하려면 이 값을 `false`로 설정하세요.
    islands: true,
  },
})
객체 문법을 사용하는 경우, 속성은 더 최적화된 빌드를 생성하기 위해 정적으로 분석됩니다. 따라서 런타임에 이를 정의해서는 안 됩니다.
예를 들어, enforce: import.meta.server ? 'pre' : 'post'와 같이 설정하면 Nuxt가 플러그인에 대해 수행할 수 있는 향후 최적화를 무력화하게 됩니다. Nuxt는 객체 문법을 사용할 때 모든 훅 리스너를 정적으로 사전 로드하므로, 플러그인 등록 순서를 걱정하지 않고도 훅을 정의할 수 있습니다.

Registration Order

파일 이름에 '알파벳' 번호 접두사를 붙여 플러그인이 등록되는 순서를 제어할 수 있습니다.

Directory structure
plugins/
 | - 01.myPlugin.ts
 | - 02.myOtherPlugin.ts

이 예시에서 02.myOtherPlugin.ts01.myPlugin.ts에 의해 주입된 모든 것에 접근할 수 있습니다.

이는 한 플러그인이 다른 플러그인에 의존하는 상황에서 유용합니다.

'알파벳' 번호 매기기가 처음이라면, 파일 이름은 숫자 값이 아니라 문자열로 정렬된다는 점을 기억하세요. 예를 들어, 10.myPlugin.ts2.myOtherPlugin.ts보다 먼저 옵니다. 이 때문에 예시에서는 한 자리 숫자 앞에 0을 붙입니다.

Loading Strategy

Parallel Plugins

기본적으로 Nuxt는 플러그인을 순차적으로 로드합니다. 플러그인을 parallel로 정의하면 Nuxt는 다음 플러그인을 로드하기 전에 해당 플러그인의 실행이 끝날 때까지 기다리지 않습니다.

plugins/my-plugin.ts
export default defineNuxtPlugin({
  name: 'my-plugin',
  parallel: true,
  async setup (nuxtApp) {
    // 다음 플러그인은 즉시 실행됩니다
  },
})

Plugins With Dependencies

플러그인이 실행되기 전에 다른 플러그인을 기다려야 하는 경우, dependsOn 배열에 해당 플러그인의 이름을 추가할 수 있습니다.

plugins/depending-on-my-plugin.ts
export default defineNuxtPlugin({
  name: 'depends-on-my-plugin',
  dependsOn: ['my-plugin'],
  async setup (nuxtApp) {
    // 이 플러그인은 실행되기 전에 `my-plugin`의 실행이 끝날 때까지 기다립니다
  },
})

Using Composables

Nuxt 플러그인 내에서 composablesutils를 사용할 수 있습니다:

app/plugins/hello.ts
export default defineNuxtPlugin((nuxtApp) => {
  const foo = useFoo()
})

하지만 몇 가지 제한 사항과 차이점이 있다는 점을 기억하세요:

컴포저블이 나중에 등록된 다른 플러그인에 의존하는 경우, 제대로 동작하지 않을 수 있습니다.
플러그인은 순서대로, 그리고 다른 모든 것보다 먼저 호출됩니다. 아직 호출되지 않은 다른 플러그인에 의존하는 컴포저블을 사용할 수 있습니다.
컴포저블이 Vue.js 라이프사이클에 의존하는 경우, 동작하지 않습니다.
일반적으로 Vue.js 컴포저블은 현재 컴포넌트 인스턴스에 바인딩되지만, 플러그인은 nuxtApp 인스턴스에만 바인딩됩니다.

Providing Helpers

NuxtApp 인스턴스에 헬퍼를 제공하고 싶다면, 플러그인에서 provide 키 아래에 반환하면 됩니다.

export default defineNuxtPlugin(() => {
  return {
    provide: {
      hello: (msg: string) => `Hello ${msg}!`,
    },
  }
})

그런 다음 컴포넌트에서 이 헬퍼를 사용할 수 있습니다:

app/components/Hello.vue
<script setup lang="ts">
// 또는 여기에서 사용할 수도 있습니다
const { $hello } = useNuxtApp()
</script>

<template>
  <div>
    {{ $hello('world') }}
  </div>
</template>
전역 네임스페이스 오염을 피하고 메인 번들 엔트리를 작게 유지하기 위해, 헬퍼를 제공하는 대신 composables를 사용할 것을 강력히 권장합니다.
플러그인이 ref 또는 computed를 제공하는 경우, 컴포넌트 <template>에서 언래핑되지 않습니다.
이는 Vue가 템플릿의 최상위가 아닌 ref를 처리하는 방식 때문입니다. 이에 대한 자세한 내용은 Vue 문서에서 확인할 수 있습니다.

Typing Plugins

플러그인에서 헬퍼를 반환하면 자동으로 타입이 지정되며, useNuxtApp()의 반환값과 템플릿 내에서 타입 정보를 확인할 수 있습니다.

다른 플러그인 내부 에서 제공된 헬퍼를 사용해야 하는 경우, useNuxtApp()을 호출하여 타입이 지정된 버전을 가져올 수 있습니다. 하지만 일반적으로 플러그인의 순서를 확실히 알고 있는 경우가 아니라면 이는 피하는 것이 좋습니다.

고급 사용 사례의 경우, 주입된 속성의 타입을 다음과 같이 선언할 수 있습니다:

index.d.ts
declare module '#app' {
  interface NuxtApp {
    $hello (msg: string): string
  }
}

declare module 'vue' {
  interface ComponentCustomProperties {
    $hello (msg: string): string
  }
}

export {}

Vue Plugins

vue-gtag처럼 Google Analytics 태그를 추가하기 위한 Vue 플러그인을 사용하려면, Nuxt 플러그인을 통해 이를 사용할 수 있습니다.

먼저 Vue 플러그인 의존성을 설치합니다:

npm install --save-dev vue-gtag-next

그런 다음 플러그인 파일을 생성합니다:

app/plugins/vue-gtag.client.ts
import VueGtag, { trackRouter } from 'vue-gtag-next'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(VueGtag, {
    property: {
      id: 'GA_MEASUREMENT_ID',
    },
  })
  trackRouter(useRouter())
})

Vue Directives

마찬가지로, 플러그인에서 커스텀 Vue 디렉티브를 등록할 수 있습니다.

plugins/my-directive.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.directive('focus', {
    mounted (el) {
      el.focus()
    },
    getSSRProps (binding, vnode) {
      // 여기에서 SSR 전용 props를 제공할 수 있습니다
      return {}
    },
  })
})
Vue 디렉티브를 등록하는 경우, 한쪽에서만 렌더링할 때 사용하는 것이 아니라면 클라이언트와 서버 양쪽에 반드시 등록해야 합니다. 디렉티브가 클라이언트 측에서만 의미가 있다면, ~/plugins/my-directive.client.ts로 옮기고 서버용으로는 ~/plugins/my-directive.server.ts에 'stub' 디렉티브를 제공할 수 있습니다.
Read more in Vue 문서의 Custom Directives.