안녕하세요, Nuxt.js 학습 시리즈의 11번째 시간입니다! 지난 시간에는 SEO 최적화와 메타 데이터 관리에 대해 알아보았는데요. 이번 시간에는 Nuxt.js에서 애플리케이션의 기능을 확장하고 코드를 효율적으로 관리할 수 있게 해주는 플러그인(Plugins)과 유틸리티(Utils)에 대해 자세히 알아보겠습니다.

1. Nuxt.js 플러그인(Plugins)이란?
플러그인은 Vue 애플리케이션이 생성되기 전에 실행되는 JavaScript 모듈로, 전역 구성 요소 등록, 외부 라이브러리 통합, 함수나 상수 주입 등 애플리케이션의 기능을 확장하는 데 사용됩니다. Nuxt 3에서는 plugins/ 디렉토리에 있는 파일들을 자동으로 플러그인으로 인식하고 로드합니다.
플러그인의 주요 사용 사례:
- 전역 컴포넌트 등록
- 외부 라이브러리 통합 (axios, vue-i18n 등)
- 전역 함수 및 속성 제공
- Vue 인스턴스 확장
2. 플러그인 생성 및 사용하기
기본 플러그인 생성
Nuxt 3에서 플러그인을 생성하려면 plugins/ 디렉토리에 파일을 추가하기만 하면 됩니다. 다음은 간단한 플러그인 예시입니다:
// plugins/my-plugin.js
export default defineNuxtPlugin(nuxtApp => {
// 여기서 nuxtApp은 Nuxt 앱 인스턴스입니다
// 전역 속성 추가
nuxtApp.provide('hello', (name) => `Hello, ${name}!`)
// 콘솔에 메시지 출력
console.log('플러그인이 로드되었습니다!')
})
이제 애플리케이션의 어디에서나 $hello 메서드를 사용할 수 있습니다:
// 컴포넌트에서 사용
const { $hello } = useNuxtApp()
console.log($hello('World')) // 출력: Hello, World!
플러그인 실행 순서 제어하기
파일 이름에 숫자 접두사를 사용하여 플러그인의 실행 순서를 제어할 수 있습니다:
plugins/
1.first-plugin.js
2.second-plugin.js
3.third-plugin.js
조건부 플러그인 등록
특정 조건에서만 플러그인을 로드하려면 파일 이름에 .client 또는 .server 접미사를 사용할 수 있습니다:
plugins/
analytics.client.js // 클라이언트 측에서만 실행
database.server.js // 서버 측에서만 실행
both-sides.js // 클라이언트와 서버 모두에서 실행
3. 외부 라이브러리 통합하기
외부 라이브러리를 Nuxt 애플리케이션에 통합하는 것은 플러그인의 가장 일반적인 사용 사례 중 하나입니다. 예를 들어, Axios를 통합해 보겠습니다:
// plugins/axios.js
import axios from 'axios'
export default defineNuxtPlugin(() => {
const axiosInstance = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
})
// 요청 인터셉터 추가
axiosInstance.interceptors.request.use(config => {
// 요청 전에 수행할 작업
return config
})
// 응답 인터셉터 추가
axiosInstance.interceptors.response.use(
response => response,
error => {
// 오류 처리
return Promise.reject(error)
}
)
return {
provide: {
axios: axiosInstance
}
}
})
이제 컴포넌트에서 다음과 같이 사용할 수 있습니다:
// 컴포넌트에서 사용
const { $axios } = useNuxtApp()
// API 호출
const fetchData = async () => {
try {
const response = await $axios.get('/users')
return response.data
} catch (error) {
console.error('API 호출 오류:', error)
}
}
4. 전역 컴포넌트 등록하기
자주 사용하는 컴포넌트를 전역으로 등록하여 모든 페이지에서 쉽게 사용할 수 있습니다:
// plugins/global-components.js
import BaseButton from '~/components/BaseButton.vue'
import BaseCard from '~/components/BaseCard.vue'
import BaseInput from '~/components/BaseInput.vue'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component('BaseButton', BaseButton)
nuxtApp.vueApp.component('BaseCard', BaseCard)
nuxtApp.vueApp.component('BaseInput', BaseInput)
})
이제 모든 페이지나 컴포넌트에서 import 없이 바로 사용할 수 있습니다:
<template>
<div>
<basecard>
<baseinput v-model="username" placeholder="사용자 이름">
<basebutton @click="login">로그인</basebutton>
</baseinput></basecard>
</div>
</template>
5. 유틸리티(Utils) 함수 관리하기
Nuxt 3에서는 utils/ 디렉토리를 사용하여 애플리케이션 전체에서 재사용 가능한 유틸리티 함수를 관리할 수 있습니다. 이 디렉토리는 자동으로 자동 임포트(auto-import) 기능을 지원합니다.
유틸리티 함수 생성하기
// utils/format.js
export function formatDate(date, locale = 'ko-KR') {
return new Date(date).toLocaleDateString(locale)
}
export function formatCurrency(amount, currency = 'KRW') {
return new Intl.NumberFormat('ko-KR', {
style: 'currency',
currency
}).format(amount)
}
// utils/validation.js
export function isValidEmail(email) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return regex.test(email)
}
export function isValidPassword(password) {
// 최소 8자, 대문자, 소문자, 숫자, 특수문자 포함
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
return regex.test(password)
}
유틸리티 함수 사용하기
Nuxt 3의 자동 임포트 기능 덕분에 별도의 import 문 없이 바로 사용할 수 있습니다:
<template>
<div>
<p>가격: {{ formatCurrency(product.price) }}</p>
<p>출시일: {{ formatDate(product.releaseDate) }}</p>
<form @submit.prevent="register">
<input v-model="email" type="email" placeholder="이메일">
<p v-if="email && !isValidEmail(email)" class="error">
유효한 이메일 주소를 입력해주세요.
</p>
<input v-model="password" type="password" placeholder="비밀번호">
<p v-if="password && !isValidPassword(password)" class="error">
비밀번호는 최소 8자 이상이며, 대문자, 소문자, 숫자, 특수문자를 포함해야 합니다.
</p>
<button type="submit">등록</button>
</form>
</div>
</template>
<script setup="">
const email = ref('')
const password = ref('')
const register = () => {
if (isValidEmail(email.value) && isValidPassword(password.value)) {
// 등록 로직 실행
}
}
</script>
6. 복잡한 유틸리티 모듈 구성하기
더 복잡한 유틸리티 모듈을 구성할 수도 있습니다. 예를 들어, 로컬 스토리지를 관리하는 유틸리티를 만들어 보겠습니다:
// utils/storage.js
export const useStorage = () => {
const setItem = (key, value) => {
if (process.client) {
localStorage.setItem(key, JSON.stringify(value))
}
}
const getItem = (key) => {
if (process.client) {
const value = localStorage.getItem(key)
return value ? JSON.parse(value) : null
}
return null
}
const removeItem = (key) => {
if (process.client) {
localStorage.removeItem(key)
}
}
const clear = () => {
if (process.client) {
localStorage.clear()
}
}
return {
setItem,
getItem,
removeItem,
clear
}
}
사용 예시:
<script setup="">
const { setItem, getItem } = useStorage()
// 사용자 설정 저장
const saveUserPreferences = (preferences) => {
setItem('userPreferences', preferences)
}
// 저장된 설정 불러오기
const userPreferences = ref(getItem('userPreferences') || {
theme: 'light',
fontSize: 'medium'
})
</script>
7. 플러그인과 유틸리티의 실제 활용 사례
인증 시스템 구현하기
플러그인과 유틸리티를 결합하여 인증 시스템을 구현해 보겠습니다:
// utils/auth.js
export const useAuth = () => {
const token = useCookie('auth_token')
const user = useState('auth_user', () => null)
const setUser = (newUser) => {
user.value = newUser
}
const setToken = (newToken) => {
token.value = newToken
}
const login = async (credentials) => {
// API 호출 로직
// 성공 시:
setToken('your-auth-token')
setUser({ id: 1, name: '홍길동' })
return true
}
const logout = () => {
setToken(null)
setUser(null)
}
const isLoggedIn = computed(() => !!token.value)
return {
user,
token,
login,
logout,
isLoggedIn
}
}
// plugins/auth.js
export default defineNuxtPlugin(() => {
const { token, user } = useAuth()
// 토큰이 있으면 사용자 정보 가져오기
const initAuth = async () => {
if (token.value) {
try {
// API에서 사용자 정보 가져오기
// const userData = await $fetch('/api/me')
// user.value = userData
} catch (error) {
// 오류 시 로그아웃
const { logout } = useAuth()
logout()
}
}
}
// 앱 초기화 시 인증 상태 확인
initAuth()
return {
provide: {
isAuthenticated: () => !!token.value
}
}
})
다국어 지원 플러그인
간단한 다국어 지원 플러그인을 구현해 보겠습니다:
// utils/i18n/translations.js
export const translations = {
ko: {
welcome: '환영합니다',
login: '로그인',
register: '회원가입',
home: '홈',
about: '소개',
contact: '연락처'
},
en: {
welcome: 'Welcome',
login: 'Login',
register: 'Register',
home: 'Home',
about: 'About',
contact: 'Contact'
}
}
// plugins/i18n.js
import { translations } from '~/utils/i18n/translations'
export default defineNuxtPlugin(() => {
const locale = useState('locale', () => 'ko')
const t = (key) => {
const currentTranslations = translations[locale.value] || translations.ko
return currentTranslations[key] || key
}
const setLocale = (newLocale) => {
if (translations[newLocale]) {
locale.value = newLocale
}
}
return {
provide: {
t,
setLocale,
locale: readonly(locale)
}
}
})
사용 예시:
<template>
<div>
<h1>{{ $t('welcome') }}</h1>
<button @click="$setLocale('ko')">한국어</button>
<button @click="$setLocale('en')">English</button>
<nav>
<a href="/">{{ $t('home') }}</a>
<a href="/about">{{ $t('about') }}</a>
<a href="/contact">{{ $t('contact') }}</a>
</nav>
</div>
</template>
<script setup="">
const { $t, $locale } = useNuxtApp()
</script>
8. 플러그인과 유틸리티 관련 모범 사례
모범 사례
- 명확한 책임 분리: 플러그인은 앱 초기화와 전역 기능에, 유틸리티는 순수 함수에 집중하세요.
- 타입 안전성: TypeScript를 사용하여 플러그인과 유틸리티 함수의 타입을 명확히 정의하세요.
- 적절한 이름 지정: 기능을 명확히 나타내는 이름을 사용하세요.
- 문서화: 복잡한 플러그인이나 유틸리티는 주석을 통해 사용 방법을 문서화하세요.
- 테스트: 유틸리티 함수는 단위 테스트를 작성하여 안정성을 보장하세요.
피해야 할 사항
- 과도한 전역 상태: 모든 것을 플러그인으로 만들지 마세요. 필요한 경우에만 사용하세요.
- 불필요한 의존성: 플러그인에 너무 많은 외부 라이브러리를 포함하면 앱 크기가 커집니다.
- 서버/클라이언트 혼합: 플러그인이 서버와 클라이언트 모두에서 실행될 때는
process.client체크를 잊지 마세요.
9. 정리 및 다음 단계
이번 포스트에서는 Nuxt.js의 플러그인과 유틸리티에 대해 알아보았습니다. 플러그인을 통해 애플리케이션에 전역 기능을 추가하고, 유틸리티를 통해 재사용 가능한 함수를 관리하는 방법을 배웠습니다. 이러한 기능들은 코드의 재사용성과 유지보수성을 크게 향상시키며, 대규모 애플리케이션 개발에 필수적입니다.
다음 포스트에서는 미들웨어(Middleware)와 라우트 가드에 대해 알아볼 예정입니다. 페이지 이동 전/후에 특정 로직을 수행하는 미들웨어를 구현하고, 인증 기반 페이지 접근 제어 및 특정 레이아웃 동적 할당 방법을 배우게 됩니다. 이를 통해 더 안전하고 유연한 웹 애플리케이션을 구축할 수 있을 것입니다.
다음 회차 미리보기: 미들웨어(Middleware)와 라우트 가드
- 전역 미들웨어와 라우트 미들웨어의 차이점
- 인증 및 권한 기반 페이지 접근 제어 구현
- 동적 레이아웃 할당을 위한 미들웨어 활용
- 미들웨어를 활용한 실전 패턴






답글 남기기