Vite Vue Project Scaffold
참고: https://www.heropy.dev/p/aBLqC5 코딩 규칙 참고: https://www.heropy.dev/p/EzuOg2
Vite 기반 Vue 3 프로젝트를 스캐폴딩하거나, 기존 프로젝트의 누락된 설정을 자동 보완하는 스킬.
필수 실행 체크리스트 (MANDATORY)
스킬 시작 즉시, 아래 항목을 TodoWrite에 1:1로 등록한 뒤 순서대로 진행한다. 건너뛰기 금지.
- 프로젝트 상태 감지 (1단계)
- 모드 결정: 스캐폴딩 모드 vs 보완 모드 (2단계)
- 프로젝트 생성 [스캐폴딩 모드일 때만] (3단계)
- Tailwind CSS 설치 및 구성 [tailwindcss 미설치 시] (4단계)
- 경로 별칭 구성 [vite.config/tsconfig에 alias 미설정 시] (5단계)
- ESLint + Prettier 구성 [eslint.config.* 파일이 없을 때] (6단계)
- Prettier 구성 파일 [Prettier 구성 파일이 없을 때 생성, 공식 스타터의 .prettierrc.json에는 병합, Oxfmt 프로젝트는 skip] (7단계)
- .vscode/settings.json 생성 [파일 없을 때] (8단계)
- typecheck 스크립트 구성 [TypeScript 프로젝트인데 typecheck 또는 type-check 스크립트가 없을 때] (9단계)
- 최종 검증: 1단계 감지 표를 다시 돌며 모든 구성이 충족됐는지 확인하고 실제로 실행해 본다 (10단계)
각 항목은 조건 충족 시 "skipped"로 완료 처리하되, 조건 판단 근거(파일/패키지 존재 여부)를 명시한 뒤 넘어간다.
동작 흐름
1단계: 프로젝트 상태 감지
다음 파일들을 확인하여 현재 프로젝트 상태를 판별한다:
| 확인 대상 | 감지 방법 |
|---|---|
| 빈 디렉토리 여부 | 현재 디렉토리에 파일이 없거나 package.json이 없음 |
| Vite 프로젝트 | vite.config.ts 또는 vite.config.js 존재 |
| Vue | package.json의 dependencies에 vue 존재 |
| TypeScript | tsconfig.json 또는 tsconfig.app.json 존재 |
| 공식 스타터 여부 | .oxlintrc.json 또는 eslint.config.ts 존재 |
| Tailwind CSS | package.json에 tailwindcss 존재 |
| 전역 CSS 파일 | src/main.ts(또는 src/main.js)가 import하는 .css 파일 경로. Vite 템플릿은 src/style.css, 공식 스타터는 src/assets/main.css |
| ESLint 구성 | eslint.config.js, eslint.config.ts, eslint.config.mjs 중 하나 존재 |
| 포매터 종류 | .oxfmtrc.json 존재 -> Oxfmt, .prettierrc* 파일 또는 package.json의 prettier 키 존재 -> Prettier, 둘 다 없음 -> 없음 |
| Prettier 구성 파일 | .prettierrc, .prettierrc.json, .prettierrc.yaml 등 .prettierrc* 파일 또는 package.json의 prettier 키 |
| VSCode 설정 | .vscode/settings.json 파일 존재. .vscode/extensions.json만 있는 경우는 미설정으로 본다 |
| 스크립트 | package.json의 typecheck 또는 type-check, lint, format 스크립트 존재 여부 |
| 패키지 매니저 | pnpm-lock.yaml -> pnpm, yarn.lock -> yarn, bun.lockb 또는 bun.lock -> bun, package-lock.json 또는 lock 파일 없음 -> npm |
{pm}은 프로젝트의 lock 파일로 판별한 패키지 매니저로 대체한다.pnpm-lock.yaml->pnpm,yarn.lock->yarn,bun.lockb또는bun.lock->bun,package-lock.json또는 lock 파일 없음 ->npm.{pmx}는 해당 패키지 매니저의 실행 명령으로 대체한다.npm->npx,pnpm->pnpm dlx,yarn->yarn dlx,bun->bunx.
2단계: 분기 처리
빈 디렉토리인 경우 (스캐폴딩 모드):
- 3단계 A(Vite 최소 템플릿)로 생성한다. 사용자가 "공식 스타터", "Official Vue Starter", "create-vue"를 언급한 경우에만 B로 생성한다. 어느 쪽인지 묻지 않는다.
- 아래 설정 전부 자동 적용
기존 Vite Vue 프로젝트인 경우 (보완 모드):
- 위 감지 기준으로 설치 상태 자동 판별
- 누락된 설정만 식별하여 자동 생성
- 이미 존재하는 설정 파일은 건드리지 않음. 같은 역할의 파일이 다른 이름으로 있으면(
eslint.config.ts,.prettierrc.json) 새 파일을 만들지 않고 그 파일을 기준으로 병합한다
3단계: 프로젝트 생성
요구사항: Node.js 20.19+ (22.x를 쓴다면 22.12+). 공식 스타터(B)는 Node.js 22.18+ (24.x를 쓴다면 24.12+).
A. Vite 최소 템플릿 (기본값. 이 스킬이 나머지 구성을 채운다)
{pm} create vite@latest . -- --template vue-ts --no-interactive
JavaScript 프로젝트라면 --template vue를 쓴다.
B. Official Vue Starter (사용자가 명시적으로 요청했을 때만. 라우터, Pinia, 테스트, 린터, 포매터를 한 번에 포함)
스킬이 자동으로 진행할 때는 비대화형 플래그로 생성한다. create-vue는 DIRECTORY가 .이거나 유효한 패키지 이름이 아니면
패키지 이름을 묻는 대화형으로 바뀌므로, 현재 폴더 이름(소문자, 하이픈만 허용)으로 하위 폴더에 생성한 뒤 내용을 현재 폴더로 옮긴다.
{pm} create vue@latest <프로젝트_이름> -- --ts --router --pinia --vitest --eslint --prettier
mv <프로젝트_이름>/.[!.]* <프로젝트_이름>/* . && rmdir <프로젝트_이름>
사용자가 직접 대화형으로 만들 때는 다음 순서로 묻는다. Select a variant에서 공식 스타터를 고르면 이후 질문은 create-vue의 것이다.
{pm} create vite@latest <프로젝트_폴더_이름>
Select a framework: Vue
Select a variant: Official Vue Starter
Use TypeScript? Yes
Select features to include in your project:
JSX Support / Router (SPA development) / Pinia (state management) /
Vitest (unit testing) / End-to-End Testing / Linter (error prevention) /
Prettier (code formatting)
Linter (error prevention)를 고르면 ESLint와 oxlint가 함께 들어간다. 실험 기능(Enable experimental features)에서
Replace Prettier with Oxfmt, Vue 3.6 (Release Candidate)를 고를 수 있지만 이 스킬은 고르지 않는다.
공식 스타터는 경로 별칭 @, .editorconfig, .vscode/settings.json, eslint.config.ts, .prettierrc.json,
type-check와 lint, format 스크립트를 이미 포함하므로 5, 6, 8, 9단계를 건너뛴다.
Tailwind는 포함되지 않으므로 4단계는 그대로 수행하고, 7단계는 .prettierrc.json에 병합한다.
이어서 아래 "공식 스타터 추가 처리"를 본다.
4단계: Tailwind CSS 설치 [조건: tailwindcss 미설치 시]
{pm} add -D tailwindcss @tailwindcss/vite
vite.config.ts의 기존 plugins 배열 끝에 Tailwind 플러그인(tailwindcss())을 추가한다.
vue(), vueDevTools(), resolve.alias 등 기존 항목은 그대로 유지한다.
Vite 최소 템플릿:
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [vue(), tailwindcss()]
})
공식 스타터:
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [vue(), vueDevTools(), tailwindcss()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
1단계에서 감지한 전역 CSS 파일 최상단에 추가한다. 뒤따르는 기존 @import(공식 스타터의 ./base.css)는 유지한다.
@import 'tailwindcss';
해당 CSS 파일이 src/main.ts에서 import되고 있는지 확인한다.
5단계: 경로 별칭 구성 [조건: vite.config 또는 tsconfig에 @ alias 미설정 시]
vite.config.ts에 resolve.alias 설정을 추가한다. 기존 plugins는 그대로 유지한다.
@와 node_modules 두 별칭을 항상 함께 추가한다.
// vite.config.ts
export default defineConfig({
plugins: [vue(), tailwindcss()],
resolve: {
alias: [
{ find: '@', replacement: '/src' },
{ find: 'node_modules', replacement: '/node_modules' }
]
}
})
node_modules 별칭은 <style> 안에서 @import 'node_modules/swiper/swiper.css'처럼
패키지 CSS를 가져올 때 쓴다.
TypeScript 프로젝트라면 tsconfig.app.json에 경로 별칭을 추가한다.
Vite가 만든 tsconfig.json은 다른 구성 파일을 참조만 하므로 거기에 넣으면 동작하지 않는다.
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"node_modules/*": ["./node_modules/*"]
}
}
}
TypeScript v5 이하(
tsc --version으로 확인)인 경우,"baseUrl": "."을paths위에 추가한다.
6단계: ESLint + Prettier 구성 [조건: eslint.config.* 파일이 없을 때]
eslint.config.js, eslint.config.ts, eslint.config.mjs 중 하나라도 있으면(공식 스타터 포함) 이 단계 전체를 건너뛴다.
ESLint는 .js를 .ts보다 먼저 읽으므로, 새 파일을 만들면 기존 구성이 통째로 무시된다.
Vite의 Vue 템플릿에는 ESLint가 포함되지 않는다. 전부 직접 설치한다.
TypeScript 프로젝트:
{pm} add -D eslint @eslint/js eslint-plugin-vue @vue/eslint-config-typescript prettier eslint-config-prettier eslint-plugin-prettier
JavaScript 프로젝트:
{pm} add -D eslint @eslint/js globals eslint-plugin-vue prettier eslint-config-prettier eslint-plugin-prettier
Tailwind를 설치했다면 Prettier 플러그인도 함께 추가한다:
{pm} add -D prettier-plugin-tailwindcss
포매터가 Oxfmt(.oxfmtrc.json 존재)인 프로젝트에서는 prettier, eslint-config-prettier, eslint-plugin-prettier,
prettier-plugin-tailwindcss를 설치하지 않고, 아래 구성에서 prettierRecommended를 뺀다.
| 패키지 | 설명 |
|---|---|
eslint |
ESLint 코어 |
@eslint/js |
ESLint 기본 추천 규칙 모음 |
globals |
실행 환경 전역 변수 목록 (JavaScript일 때) |
eslint-plugin-vue |
Vue 문법 분석 및 검사 |
@vue/eslint-config-typescript |
TypeScript 규칙 + *.vue의 <script lang="ts">를 분석할 파서 연결 |
prettier |
Prettier 코어 |
eslint-config-prettier |
Prettier와 충돌하는 ESLint 규칙 비활성화 |
eslint-plugin-prettier |
Prettier 규칙을 ESLint 규칙으로 통합 |
prettier-plugin-tailwindcss |
Tailwind 클래스 정렬 (Tailwind 설치 시) |
프로젝트 루트에 eslint.config.js를 생성한다.
TypeScript 프로젝트:
// eslint.config.js
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import {
defineConfigWithVueTs,
vueTsConfigs
} from '@vue/eslint-config-typescript'
import prettierRecommended from 'eslint-plugin-prettier/recommended'
import { globalIgnores } from 'eslint/config'
export default defineConfigWithVueTs(
{ files: ['**/*.{vue,ts,mts,tsx}'] },
globalIgnores(['**/dist/**']),
js.configs.recommended,
pluginVue.configs['flat/recommended'],
vueTsConfigs.recommended,
prettierRecommended
)
JavaScript 프로젝트:
// eslint.config.js
import js from '@eslint/js'
import globals from 'globals'
import pluginVue from 'eslint-plugin-vue'
import prettierRecommended from 'eslint-plugin-prettier/recommended'
import { defineConfig, globalIgnores } from 'eslint/config'
export default defineConfig([
{ files: ['**/*.{vue,js,mjs,jsx}'] },
globalIgnores(['**/dist/**']),
{ languageOptions: { globals: globals.browser } },
js.configs.recommended,
pluginVue.configs['flat/recommended'],
prettierRecommended
])
TypeScript에서
defineConfigWithVueTs를 쓰는 이유는*.vue파일의<script lang="ts">내부를 분석할 파서까지 함께 연결해 주기 때문이다.typescript-eslint를 직접 나열하면 파서가 연결되지 않아Parsing error가 발생한다.vueTsConfigs.recommended는 TypeScript 규칙만 포함하므로,no-empty같은 ESLint 기본 추천 규칙까지 쓰려면js.configs.recommended를 함께 넣는다.ESLint 9부터
eslint.config.js플랫 구성이 기본이고, 10에서.eslintrc.*지원이 제거됐다.
사용자가 Vue 커스텀 규칙을 요청하면 구성의 가장 마지막에 아래 객체(조각)를 추가한다.
{
rules: {
'vue/html-closing-bracket-newline': ['error', {
singleline: 'never',
multiline: 'never'
}],
'vue/html-self-closing': ['error', {
html: { void: 'always', normal: 'never', component: 'always' },
svg: 'always',
math: 'always'
}],
'vue/comment-directive': 'off',
'vue/no-v-html': 'off'
}
}
7단계: Prettier 구성 파일 [조건: Prettier 구성 파일이 없을 때 생성. 공식 스타터의 .prettierrc.json에는 병합]
포매터가 Oxfmt인 프로젝트에서는 이 단계를 건너뛴다. .oxfmtrc.json과 format 스크립트는 건드리지 않는다.
Prettier 구성 파일이 전혀 없으면 프로젝트 루트에 .prettierrc를 생성한다.
Tailwind를 설치하지 않았으면 plugins 항목을 뺀다.
{
"semi": false,
"singleQuote": true,
"singleAttributePerLine": true,
"bracketSameLine": true,
"endOfLine": "auto",
"trailingComma": "none",
"arrowParens": "avoid",
"plugins": ["prettier-plugin-tailwindcss"]
}
공식 스타터의 .prettierrc.json이 있으면 새 파일을 만들지 않고 그 파일에 위 옵션을 병합한다.
$schema는 유지하고, 스타터가 넣은 printWidth는 삭제해 두 스캐폴드(react-vite-scaffold, vue-vite-scaffold)의 규칙을 같게 맞춘다.
prettier-plugin-tailwindcss가 설치되어 있지 않으면 {pm} add -D prettier-plugin-tailwindcss로 추가한다.
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"singleQuote": true,
"singleAttributePerLine": true,
"bracketSameLine": true,
"endOfLine": "auto",
"trailingComma": "none",
"arrowParens": "avoid",
"plugins": ["prettier-plugin-tailwindcss"]
}
8단계: .vscode/settings.json [조건: 파일 없을 때]
판단 기준은 settings.json 파일이다. Vite 템플릿이 만드는 .vscode/extensions.json만 있는 경우는 없는 것으로 보고 생성한다.
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
포매터가 Oxfmt인 프로젝트에서는 editor.defaultFormatter를 oxc.oxc-vscode로 둔다.
사용자에게 아래 VS Code 확장 설치를 안내한다.
dbaeumer.vscode-eslint(ESLint)esbenp.prettier-vscode(Prettier - Code formatter)Vue.volar(Vue - Official): Vue 프로젝트에 필수
9단계: typecheck 스크립트 [조건: TypeScript 프로젝트인데 typecheck 또는 type-check 스크립트가 없을 때]
<template> 안의 타입 오류는 편집기를 열지 않으면 드러나지 않는다.
존재하지 않는 속성 참조, 문자열 자리에 들어간 ref 객체, 잘못 쓴 Props 이름이 모두 여기서 걸린다.
AI가 작성한 Vue 코드를 검증하는 가장 중요한 수단이다.
vue-tsc와 typescript가 없으면 설치한다:
{pm} add -D vue-tsc typescript
package.json에 스크립트를 추가한다. lint 스크립트가 이미 있으면(공식 스타터의 run-s "lint:*" 등) 건드리지 않는다.
{
"scripts": {
"typecheck": "vue-tsc --build",
"lint": "eslint . --fix"
}
}
10단계: 최종 검증 (MANDATORY)
모든 단계 수행 후, 1단계의 감지 표를 다시 한 번 스캔하고 실제로 명령을 실행해 확인한다.
-
tailwindcss,@tailwindcss/vite설치됨 +vite.config.ts에 플러그인 등록됨(기존 플러그인 유지) + 전역 CSS에@import 'tailwindcss'존재 - [Vite 템플릿]
vite.config.ts와tsconfig.app.json(TypeScript) 모두에@,node_modules경로 별칭 존재. [공식 스타터]@별칭 존재 -
prettier설치됨 (Oxfmt 프로젝트 제외) - [이 스킬이 eslint.config.*를 만든 경우]
eslint-config-prettier,eslint-plugin-prettier설치됨 -
eslint.config.*의 맨 마지막 항목이prettierRecommended또는skipFormatting - Prettier 구성 파일(
.prettierrc*) 존재. Tailwind 설치 시plugins에prettier-plugin-tailwindcss포함 (Oxfmt 프로젝트 제외) - [Oxfmt 프로젝트]
.oxfmtrc.json과format스크립트가 변경되지 않음 -
.vscode/settings.json존재 - [TypeScript]
typecheck또는type-check스크립트 존재 - 이 스킬이 생성하거나 수정한
.vue파일이 "Vue 코딩 규칙"을 지킨다 (<script setup lang="ts">,scoped스타일,@/별칭) - [TypeScript]
{pm} run typecheck(공식 스타터는type-check) 통과 -
{pm} run lint통과 -
{pm} run build통과 (TypeScript 검사 포함)
누락 항목이 있으면 해당 단계로 돌아가 즉시 보완한다. 검증 통과 전에는 작업 종료 금지.
공식 스타터 추가 처리
3단계에서 공식 스타터로 생성했거나, 기존 프로젝트에 .oxlintrc.json이나 eslint.config.ts가 있으면 아래를 확인한다.
- 5, 6, 8, 9단계는 건너뛴다. 4단계는 기존
plugins를 유지한 채 수행하고, 7단계는.prettierrc.json에 병합한다. - 스타터에서 라우터를 골랐다면
src/router/index.ts와src/views/가 이미 있다. 이 경우vue-router-use스킬은 부분 기능 추가 모드로만 쓴다.
린터 버전 맞추기
eslint-plugin-oxlint와 oxlint는 같은 버전이어야 한다. 템플릿 구성 문제로
버전이 달라 설치가 실패할 수 있다.
npm error code ERESOLVE
npm error Found: oxlint@1.74.0
npm error Could not resolve dependency:
npm error peer oxlint@"~1.73.0" from eslint-plugin-oxlint@1.73.0
이 경우 package.json에서 두 패키지 버전을 더 낮은 쪽으로 맞춘 뒤 다시 설치한다.
둘 다 같은 최신 버전으로 올려도 된다.
{
"devDependencies": {
"eslint-plugin-oxlint": "~1.73.0",
"oxlint": "~1.73.0"
}
}
ESLint와 oxlint 중복 제거
oxlint는 Rust로 만든 빠른 린터지만, 타입 정보를 쓰는 규칙이나 eslint-plugin-vue의
Vue 전용 규칙까지 대신하지는 못해서 ESLint를 함께 쓴다. 둘은 검사 범위가 겹치므로
그대로 두면 같은 문제를 두 번 보고한다. eslint.config.ts의
buildFromOxlintConfigFile 호출이 이를 해결한다.
스타터가 만든 eslint.config.ts에 Vitest 블록(pluginVitest, files: ['src/**/__tests__/*'])이 있으면 그대로 둔다.
// eslint.config.ts
import { globalIgnores } from 'eslint/config'
import {
defineConfigWithVueTs,
vueTsConfigs
} from '@vue/eslint-config-typescript'
import pluginVue from 'eslint-plugin-vue'
import pluginOxlint from 'eslint-plugin-oxlint'
import skipFormatting from 'eslint-config-prettier/flat'
export default defineConfigWithVueTs(
{ files: ['**/*.{vue,ts,mts,tsx}'] },
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
...pluginVue.configs['flat/essential'],
vueTsConfigs.recommended,
...pluginOxlint.buildFromOxlintConfigFile('.oxlintrc.json'),
skipFormatting
)
{pm} run lint는 oxlint를 먼저 돌리고 ESLint를 이어서 돌린다.
파일 중첩
공식 스타터는 .vscode/settings.json에 파일 중첩(File Nesting)을 켜 둔다.
사용자가 불편하다고 하면 제거하지 말고 false로 명시한다. 그래야 전역 설정과
무관하게 이 프로젝트에서만 꺼진다.
{
"explorer.fileNesting.enabled": false
}
Vue 코딩 규칙
생성한 프로젝트에서 Vue 코드를 작성할 때 따르는 규칙이다.
프로젝트에 CLAUDE.md나 .claude/rules/vue.md가 있으면 그 내용이 이 스킬보다 우선한다. 기존 코드가 있으면 파일 위치, 이름, 선언 형식을 먼저 확인하고 같은 스타일로 만든다.
- 모든 Vue 컴포넌트는
<script setup lang="ts">를 사용한다. Options API는 쓰지 않는다. - 반응형 상태는
ref()를 기본으로 쓴다.reactive()는 특수한 상황이 아니면 쓰지 않는다.reactive()는 원시형에서 반응성을 잃고 구조 분해에서도 반응성이 끊어진다. 두 함수가 섞이면 어느 쪽 제약이 걸리는지 매번 판단해야 하고, 틀리면 화면이 갱신되지 않는 버그가 된다. - 파생 값은
computed()로 만든다.watch()로 다른 상태를 갱신해 파생 값을 만들지 않는다. - 로직 재사용은 컴포저블로 한다. 믹스인(mixin)은 쓰지 않는다.
- 컴포저블 파일은
src/composables/useXxx.ts에 두고, 함수 이름은use접두사로 시작한다. <style>에는 항상scoped를 붙인다. 전역 스타일은 전역 CSS 파일 한 곳에만 작성한다.- 컴포넌트 파일 이름은 PascalCase 다중 단어로 짓는다. (
MovieCard.vue) - 상대 경로는 같은 폴더 안의 파일을 가져올 때만 쓴다. 다른 폴더의 파일은
@/별칭으로 가져온다. - Props는
defineProps<T>()형태의 타입 기반 선언만 쓴다. - 컴포넌트 사이 통신은 Props와 Emits로 한다.
provide/inject는 레이아웃 수준에서만 쓴다. - 템플릿과 JSX에서 속성이 2개 이상이면 한 줄에 하나씩 쓴다. (
.prettierrc의singleAttributePerLine)
문법 상세는 아래 참조 문서를 필요할 때만 읽는다.
| 파일 | 다루는 내용 |
|---|---|
| references/composition-api.md | 반응형 데이터(ref vs reactive), 템플릿 문법, 양식 바인딩, computed와 watch, 생명주기 훅, 컴포저블 |
| references/components.md | 컴파일러 매크로, Props, Emits, Slots, 폴스루 속성, v-model, 동적 컴포넌트, provide/inject |
주의사항
- 프로젝트에
CLAUDE.md나.claude/rules/vue.md가 있으면 그 내용이 이 스킬보다 우선한다. 기존 코드가 있으면 파일 위치, 이름, 선언 형식을 먼저 확인하고 같은 스타일로 만든다. - 이미 존재하는 설정 파일은 덮어쓰지 않는다. 같은 역할의 파일이 있으면 병합만 한다
- 기존 프로젝트 보완 모드에서는 질문 없이 자동으로 진행한다
prettierRecommended(또는skipFormatting)는 항상 ESLint 구성의 마지막에 온다. 앞에 두면 뒤따르는 구성이 포맷 규칙을 다시 켠다- 빈 디렉토리(스캐폴딩 모드)에서는
npm을 사용한다
함께 보는 스킬
| 필요한 것 | 스킬 |
|---|---|
| 라우팅 (Vue Router) | vue-router-use |
| 전역 상태 (스토어) | pinia-use |
| 성능, 접근성, SEO 측정 | lighthouse |