Nuxt.config.ts 구조 정리
이 글에서 다루는 내용
Nuxt 프로젝트 설정에 사용되는 nuxt.config.ts 파일의 구조를 정리했습니다.
nuxt.config.ts
Nuxt 프로젝트의 모든 설정은 루트 디렉토리의 nuxt.config.ts 파일 하나에서 관리됩니다. 렌더링 방식, 환경변수, 모듈, 빌드 최적화까지 프로젝트의 동작 전반을 제어하는 핵심 파일입니다.
기본 구조
// nuxt.config.ts
export default defineNuxtConfig({
// 설정 옵션들...
})
defineNuxtConfig는 타입 자동완성을 제공하는 헬퍼 함수로, 별도 import 없이 전역에서 사용할 수 있습니다.
app — HTML head 및 전환 설정
페이지의 <head> 태그 안에 들어갈 메타 정보와 페이지 전환 애니메이션을 설정합니다.
app: {
head: {
title: 'My App',
titleTemplate: '%s | My App', // 페이지별 title 뒤에 suffix 붙이기
meta: [
{ name: 'description', content: 'My Nuxt App' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ property: 'og:title', content: 'My App' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' }
],
script: [
{ src: 'https://cdn.example.com/analytics.js', defer: true }
]
},
baseURL: '/', // 앱의 루트 경로 (서브 경로 배포 시 변경)
buildAssetsDir: '/_nuxt/', // 빌드 에셋이 위치할 경로
layoutTransition: { name: 'layout', mode: 'out-in' }, // 레이아웃 전환 애니메이션
pageTransition: { name: 'page', mode: 'out-in' } // 페이지 전환 애니메이션
}
titleTemplate을 활용하면 각 페이지에서 useHead({ title: '홈' })만 설정해도 자동으로 "홈 | My App" 형태로 렌더링됩니다.
pageTransition과 layoutTransition은 Vue의 <Transition> 컴포넌트를 기반으로 동작하므로, CSS에서 .page-enter-active, .page-leave-active 등의 클래스를 정의해 애니메이션을 구현합니다.
ssr — 렌더링 모드
ssr: true // 기본값. false로 설정하면 전체 앱이 SPA 모드로 동작
ssr 옵션을 명시하지 않으면 기본값은 true 입니다.
| 값 | 동작 방식 | 사용 케이스 |
|---|---|---|
true (기본값) |
서버에서 HTML을 생성해 응답 | SEO가 필요한 공개 페이지 |
false |
클라이언트에서만 렌더링 (SPA) | 인증 필요 대시보드, 관리자 페이지 |
전체를 SPA로 전환하지 않고 특정 경로만 SPA로 동작시키려면 아래의 routeRules를 활용합니다.
runtimeConfig — 환경변수 관리
.env 파일의 환경변수를 앱 내부에서 타입 안전하게 사용할 수 있도록 연결하는 설정입니다. 서버 전용 비밀값과 클라이언트에 노출 가능한 값을 분리해서 관리할 수 있습니다.
runtimeConfig: {
// 서버(Node.js)에서만 접근 가능 — 절대 클라이언트에 노출되지 않음
apiSecret: process.env.API_SECRET,
db: {
host: process.env.DB_HOST,
password: process.env.DB_PASSWORD
},
// public 안의 값은 클라이언트에서도 접근 가능
public: {
apiBase: process.env.NUXT_PUBLIC_API_BASE ?? '/api',
appEnv: process.env.NODE_ENV
}
}
컴포넌트나 composable에서는 useRuntimeConfig()로 접근합니다.
const config = useRuntimeConfig()
// 서버에서만 접근 가능
console.log(config.apiSecret)
// 클라이언트에서도 접근 가능
console.log(config.public.apiBase)
.env 파일의 변수명에 NUXT_ 접두사를 붙이면 runtimeConfig에 자동으로 매핑됩니다. 예를 들어 NUXT_PUBLIC_API_BASE는 config.public.apiBase로 연결됩니다.
alias — 디렉토리 별칭
긴 상대 경로(../../components/...) 대신 짧고 명확한 별칭으로 import할 수 있게 해줍니다.
alias: {
'@components': '~/components',
'@utils': '~/utils',
'@stores': '~/stores',
'@types': '~/types',
}
Nuxt는 기본적으로 ~, @를 프로젝트 루트로 매핑하므로 ~/components처럼 사용할 수 있습니다. 추가로 팀 컨벤션에 맞는 별칭을 직접 정의할 때 유용합니다.
imports — 자동 import 설정
Nuxt는 composables/, utils/ 디렉토리의 파일을 자동으로 import합니다. 이 설정으로 스캔 범위를 확장할 수 있습니다.
imports: {
dirs: [
'composables/**', // 하위 디렉토리까지 모두 스캔
'utils/**',
'stores/**'
]
}
자동 import 덕분에 import { useMyComposable } from '~/composables/useMyComposable' 같은 코드를 매번 작성하지 않아도 됩니다. 단, 너무 넓은 범위로 설정하면 빌드 타임이 늘어날 수 있으므로 주의합니다.
components — 컴포넌트 자동 import
components/ 디렉토리의 컴포넌트를 자동으로 등록합니다.
components: [
{
path: '~/components',
pathPrefix: false // true면 폴더명이 컴포넌트 이름 앞에 붙음
},
{
path: '~/components/global',
global: true // 모든 페이지에서 명시적 import 없이 사용 가능
}
]
pathPrefix: true로 설정하면 components/Form/Input.vue가 <FormInput>으로 등록되고, false면 <Input>으로 등록됩니다. 컴포넌트명 충돌이 우려될 때는 true를 권장합니다.
css — 전역 스타일
앱 전체에 적용할 CSS/SCSS 파일을 등록합니다.
css: [
'~/assets/css/main.css',
'~/assets/scss/global.scss'
]
여기에 등록된 파일은 모든 페이지에 자동으로 포함됩니다. 특정 페이지나 컴포넌트에서만 필요한 스타일은 <style scoped>를 사용하는 것이 좋습니다.
modules — 모듈 등록
Nuxt 생태계의 공식/커뮤니티 모듈을 등록합니다. 모듈은 단순한 플러그인보다 강력하며, Nuxt의 빌드 파이프라인 자체에 개입해 기능을 확장합니다.
modules: [
'@nuxtjs/tailwindcss', // Tailwind CSS
'@pinia/nuxt', // 상태관리
'@nuxt/image', // 이미지 최적화
'@nuxtjs/i18n', // 다국어
'@vueuse/nuxt', // VueUse composables 자동 import
'nuxt-icon' // 아이콘
]
모듈 등록 후에는 각 모듈 이름과 동일한 키로 설정을 추가할 수 있습니다.
i18n: {
locales: ['ko', 'en'],
defaultLocale: 'ko'
},
pinia: {
autoImports: ['defineStore', 'storeToRefs']
}
router — 라우터 설정
Vue Router의 동작 방식을 커스터마이징합니다.
router: {
options: {
hashMode: false, // true면 URL이 /#/path 형태로 변경
scrollBehaviorType: 'smooth' // 페이지 이동 시 스크롤 동작
}
}
hashMode: true는 서버 설정 없이 정적 호스팅(GitHub Pages 등)에서 SPA를 배포할 때 유용합니다.
build — 빌드 설정
build: {
transpile: ['gsap', 'vue-toastification']
}
기본적으로 Nuxt는 node_modules 내부 패키지를 트랜스파일하지 않습니다. ESM만 지원하거나 최신 문법을 사용하는 패키지가 구형 환경에서 오류를 일으킬 경우 transpile 배열에 추가합니다. 라이브러리를 추가했는데 빌드 후 Cannot use import statement 같은 오류가 발생한다면 이 옵션을 먼저 확인합니다.
vite — 번들러 설정
Nuxt의 기본 번들러는 Vite입니다. Vite의 설정을 그대로 확장할 수 있습니다.
vite: {
plugins: [], // Vite 플러그인 추가
css: {
preprocessorOptions: {
scss: {
// 모든 SCSS 파일에 자동으로 변수/믹스인 파일을 주입
additionalData: '@use "~/assets/scss/_variables.scss" as *;'
}
}
},
resolve: {
alias: { '@': '/src' }
},
server: {
// 개발 서버에서 API 요청을 다른 서버로 프록시
proxy: {
'/api': { target: 'http://localhost:3001', changeOrigin: true }
}
},
optimizeDeps: {
include: ['vue', 'pinia'] // 사전 번들링 대상 명시
}
}
additionalData는 매우 자주 쓰이는 옵션으로, SCSS 변수나 믹스인을 모든 컴포넌트에서 @use 없이 바로 사용하고 싶을 때 활용합니다.
nitro — 서버 엔진 설정
Nuxt의 서버 엔진인 Nitro를 설정합니다. 배포 환경(preset), 서버 스토리지, 라우트별 캐시 정책 등을 제어합니다.
nitro: {
// 배포 플랫폼에 맞는 preset 지정
preset: 'node-server', // vercel / cloudflare-pages / aws-lambda 등
routeRules: {
'/api/**': { cors: true },
'/blog/**': { swr: 3600 } // 1시간 캐시 후 백그라운드 갱신
},
// 서버 스토리지 (Redis, FS 등)
storage: {
redis: { driver: 'redis', url: process.env.REDIS_URL }
},
// 특정 패키지를 서버 번들에 인라인 포함
externals: {
inline: ['my-local-package']
}
}
swr(Stale-While-Revalidate)은 캐시된 응답을 즉시 반환하면서 백그라운드에서 데이터를 갱신하는 전략으로, 정적 생성(SSG)과 SSR의 중간 지점에 해당합니다.
routeRules — Hybrid Rendering
Nuxt의 강력한 기능 중 하나로, 라우트별로 렌더링 전략을 다르게 설정할 수 있습니다. 이를 Hybrid Rendering이라고 합니다.
routeRules: {
'/': { prerender: true }, // 빌드 시 정적 HTML로 생성 (SSG)
'/blog/**': { swr: 3600 }, // ISR — 1시간마다 백그라운드 재생성
'/admin/**': { ssr: false }, // SPA — 클라이언트에서만 렌더링
'/api/**': { cors: true }, // API 라우트 CORS 허용
'/dashboard/**': {
ssr: false,
headers: { 'X-Frame-Options': 'DENY' } // 보안 헤더 추가
},
'/old-path': { redirect: '/new-path' } // 리다이렉트
}
| 옵션 | 설명 |
|---|---|
prerender: true |
빌드 시 정적 HTML 생성 (SSG) |
swr: N |
N초 캐시 후 백그라운드 재생성 (ISR) |
ssr: false |
해당 경로만 SPA로 동작 |
redirect |
다른 경로로 리다이렉트 |
headers |
응답 헤더 추가 |
cors: true |
CORS 허용 |
/admin/**처럼 인증이 필요한 대시보드 영역은 SEO가 필요 없으므로 ssr: false로 SPA처럼 동작시키고, 공개 페이지는 SSR/SSG를 유지하는 패턴이 실무에서 자주 활용됩니다. 이 분기 처리는 Nitro가 담당합니다.
typescript — 타입스크립트 설정
typescript: {
strict: true, // 엄격한 타입 체크 활성화
typeCheck: true, // 빌드 시 타입 검사 수행 (vue-tsc 사용)
tsConfig: {
compilerOptions: {
moduleResolution: 'bundler' // Vite/esbuild 환경에 최적화된 모듈 해석
}
}
}
typeCheck: true는 빌드 속도를 다소 느리게 만들 수 있습니다. 개발 중에는 false로, CI/CD 파이프라인에서는 true로 설정하는 방식도 흔히 사용됩니다.
experimental — 실험적 기능
아직 정식 릴리즈되지 않았지만 미리 사용해볼 수 있는 기능들입니다.
experimental: {
viewTransition: true, // Chrome의 View Transitions API 활용
renderJsonPayloads: true, // JSON 페이로드 렌더링 최적화
componentIslands: true, // 특정 컴포넌트만 서버에서 렌더링하는 Island 아키텍처
payloadExtraction: false // 페이지 페이로드를 별도 파일로 추출 여부
}
viewTransition은 페이지 간 전환을 브라우저 네이티브 애니메이션으로 처리해 부드러운 UX를 제공합니다. 단, 브라우저 지원 범위를 확인하고 적용하는 것을 권장합니다.
componentIslands는 Astro의 Island 아키텍처에서 영감을 받은 기능으로, 정적 페이지 안에서 특정 컴포넌트만 서버 렌더링 또는 클라이언트 하이드레이션을 선택적으로 적용할 수 있습니다.
devServer — 개발 서버
devServer: {
port: 3000, // 기본 포트
host: '0.0.0.0', // 외부 기기에서 접근 허용 (모바일 테스트 등)
https: false // HTTPS 사용 여부
}
host: '0.0.0.0'으로 설정하면 같은 네트워크의 다른 기기(스마트폰 등)에서 개발 서버에 접근할 수 있어 모바일 반응형 테스트에 유용합니다.
devtools — Nuxt DevTools
devtools: {
enabled: true,
timeline: {
enabled: true // 컴포넌트 렌더링 타임라인 추적
}
}
Nuxt DevTools는 브라우저에서 컴포넌트 트리, 라우트 목록, 모듈 정보, composable 사용 현황 등을 시각적으로 확인할 수 있는 강력한 개발 도구입니다. 프로덕션 빌드에는 자동으로 포함되지 않습니다.
hooks — 빌드 라이프사이클 훅
Nuxt의 빌드 과정에 개입해 페이지 추가, 빌드 이벤트 처리 등을 수행할 수 있습니다.
hooks: {
// 페이지 라우트를 동적으로 추가
'pages:extend'(pages) {
pages.push({
name: 'custom',
path: '/custom',
file: '~/pages/custom.vue'
})
},
// 빌드 시작 전 실행
'build:before'() {
console.log('빌드 시작')
},
// Vite 설정에 개입
'vite:extendConfig'(config) {
config.plugins?.push(/* custom plugin */)
}
}
pages:extend는 파일 기반 라우팅 외에 조건부로 라우트를 추가해야 할 때 유용합니다. 예를 들어 CMS에서 페이지 목록을 받아와 동적으로 라우트를 생성하는 경우에 활용됩니다.
compatibilityDate — Nuxt 4 대비 설정
compatibilityDate: '2024-11-01'
Nuxt 4의 Breaking Change를 점진적으로 적용하기 위한 옵션입니다. 이 날짜를 기준으로 새로운 동작 방식이 활성화되며, 최신 프로젝트라면 반드시 추가하는 것을 권장합니다.
전체 섹션 요약
| 섹션 | 역할 |
|---|---|
app |
HTML head, 전환 효과, baseURL |
ssr |
SSR/SPA 모드 설정 (기본값: true) |
runtimeConfig |
서버/클라이언트 환경변수 분리 |
alias |
경로 별칭 설정 |
imports |
자동 import 스캔 범위 확장 |
components |
컴포넌트 자동 등록 설정 |
css |
전역 스타일 파일 등록 |
modules |
공식/커뮤니티 모듈 등록 |
router |
Vue Router 동작 방식 커스터마이징 |
build |
트랜스파일 대상 등 빌드 설정 |
vite |
Vite 번들러 레벨 커스터마이징 |
nitro |
서버 엔진, 배포 preset, 스토리지 |
routeRules |
라우트별 렌더링 전략 (Hybrid Rendering) |
typescript |
타입 검사 및 컴파일러 옵션 |
experimental |
실험적 기능 활성화 |
devServer |
개발 서버 포트/호스트 설정 |
devtools |
Nuxt DevTools 설정 |
hooks |
빌드 라이프사이클 훅 |
compatibilityDate |
Nuxt 4 마이그레이션 대비 |