Communitygithub.com

Vite 패턴

Vite 빌드 도구 패턴: 설정, 플러그인, HMR, 환경 변수, 프록시 설정, SSR, 라이브러리 모드, 의존성 사전 번들링 및 빌드 최적화를 다룹니다. vite.config.ts, Vite 플러그인 또는 Vite 기반 프로젝트 작업 시 활성화됩니다.

Vite 패턴란 무엇인가요?

이 스킬은 Vite 8+ 프로젝트를 위한 포괄적인 빌드 도구 및 개발 서버 패턴을 제공합니다. 기본 설정 구조, 조건부 설정, 중요한 설정 옵션을 다루며, 필수 플러그인 목록과 사용자 정의 플러그인 작성 방법을 설명합니다. 또한 수동 청크 분할, 배럴 파일 회피, 가져오기 확장자 명시, 핫 패스 웜업 등 성능 최적화 팁을 제공합니다. HMR API, 환경 변수 보안(특히 `VITE_` 접두사가 보안 경계가 아님을 강조), 서버 프록시, 라이브러리 모드, SSR 외부 종속성, 의존성 사전 번들링을 다루며, 개발-빌드 불일치, 오래된 청크, Docker/컨테이너, 모노레포 파일 접근 등 일반적인 문제를 해결합니다. `vite build`는 타입 검사를 수행하지 않으므로 `vite-plugin-checker`를 추가하거나 CI에서 `tsc --noEmit`을 실행해야 한다는 중요한 주의사항을 포함합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/vite-patterns

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Vite 패턴은(는) 무엇을 하나요?

Vite 8+ 프로젝트를 위한 빌드 도구 및 개발 서버 패턴입니다. 설정, 환경 변수, 프록시 설정, 라이브러리 모드, 의존성 사전 번들링 및 일반적인 프로덕션 문제를 다룹니다.

사용 시기

  • vite.config.ts 또는 vite.config.js 설정
  • 환경 변수 또는 .env 파일 설정
  • API 백엔드를 위한 개발 서버 프록시 구성
  • 빌드 출력 최적화 (청크, 축소, 에셋)
  • build.lib로 라이브러리 배포
  • 의존성 사전 번들링 또는 CJS/ESM 상호 운용 문제 해결
  • HMR, 개발 서버 또는 빌드 오류 디버깅
  • Vite 플러그인 선택 또는 순서 지정

작동 방식

  • 개발 모드는 소스 파일을 네이티브 ESM으로 제공합니다 — 번들링하지 않습니다. 변환은 모듈 요청마다 온디맨드로 발생하므로 콜드 스타트가 빠르고 HMR이 정확합니다.
  • 빌드 모드는 Rolldown(v7+) 또는 Rollup(v5–v6)을 사용하여 프로덕션용 앱을 번들링하며, 트리 쉐이킹, 코드 분할 및 Oxc 기반 축소를 수행합니다.
  • 의존성 사전 번들링은 CJS/UMD 종속성을 esbuild를 통해 한 번 ESM으로 변환하고 결과를 node_modules/.vite에 캐시하여 이후 시작 시 작업을 건너뜁니다.
  • 플러그인은 개발과 빌드에 걸쳐 통일된 인터페이스를 공유합니다 — 동일한 플러그인 객체가 개발 서버의 온디맨드 변환과 프로덕션 파이프라인 모두에서 작동합니다.
  • 환경 변수는 빌드 시 정적으로 인라인됩니다. VITE_ 접두사가 붙은 변수는 번들에서 공개 상수가 되고, 접두사가 없는 모든 것은 클라이언트 코드에 표시되지 않습니다.

예제

설정 구조

기본 설정

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: { '@': new URL('./src', import.meta.url).pathname },
  },
})

조건부 설정

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig(({ command, mode }) => {
  const env = loadEnv(mode, process.cwd())   // VITE_ 접두사만 (안전)

  return {
    plugins: [react()],
    server: command === 'serve' ? { port: 3000 } : undefined,
    define: {
      __API_URL__: JSON.stringify(env.VITE_API_URL),
    },
  }
})

주요 설정 옵션

키기본값설명
root'.'프로젝트 루트 (index.html이 있는 위치)
base'/'배포된 에셋의 공개 기본 경로
envPrefix'VITE_'클라이언트에 노출되는 환경 변수 접두사
build.outDir'dist'출력 디렉터리
build.minify'oxc'축소 도구 ('oxc', 'terser', 또는 false)
build.sourcemapfalsetrue, 'inline', 또는 'hidden'

플러그인

필수 플러그인

대부분의 플러그인 요구는 잘 관리되는 몇 가지 패키지로 충족됩니다. 직접 작성하기 전에 먼저 이것들을 사용하세요.

플러그인목적사용 시기
@vitejs/plugin-react-swcSWC를 통한 React HMR + Fast RefreshReact 앱의 기본값 (Babel 변형보다 빠름)
@vitejs/plugin-reactBabel을 통한 React HMR + Fast RefreshBabel 플러그인(emotion, MobX 데코레이터)이 필요한 경우에만
@vitejs/plugin-vueVue 3 SFC 지원Vue 앱
vite-plugin-checkerHMR 오버레이와 함께 워커 스레드에서 tsc + ESLint 실행모든 TypeScript 앱 — Vite는 vite build 중 타입 검사를 하지 않음
vite-tsconfig-pathstsconfig.json paths 별칭 준수tsconfig.json에 이미 별칭이 있는 경우
vite-plugin-dts라이브러리 모드에서 .d.ts 파일 생성TypeScript 라이브러리 배포
vite-plugin-svgrSVG를 React 컴포넌트로 가져오기SVG를 컴포넌트로 사용하는 React 앱
rollup-plugin-visualizer번들 트리맵/선버스트 보고서주기적인 번들 크기 감사 (enforce: 'post' 사용)
vite-plugin-pwa설정 없는 PWA + Workbox오프라인 지원 앱

중요 참고: vite build는 트랜스파일하지만 타입 검사는 하지 않습니다. vite-plugin-checker를 추가하거나 CI에서 tsc --noEmit을 실행하지 않으면 타입 오류가 프로덕션에 조용히 배포됩니다.

사용자 정의 플러그인 작성

사용자 정의 플러그인 작성은 드뭅니다 — 대부분의 요구는 기존 플러그인으로 충족됩니다. 필요할 경우, vite.config.ts에서 인라인으로 시작하고 재사용 시에만 분리하세요.

// vite.config.ts — 최소 인라인 플러그인
function myPlugin(): Plugin {
  return {
    name: 'my-plugin',                       // 필수, 고유해야 함
    enforce: 'pre',                           // 'pre' | 'post' (선택 사항)
    apply: 'build',                           // 'build' | 'serve' (선택 사항)
    transform(code, id) {
      if (!id.endsWith('.custom')) return
      return { code: transformCustom(code), map: null }
    },
  }
}

주요 훅: transform (소스 수정), resolveId + load (가상 모듈), transformIndexHtml (HTML에 주입), configureServer (개발 미들웨어 추가), hotUpdate (사용자 정의 HMR — v7+에서 handleHotUpdate를 대체).

가상 모듈은 \0 접두사 규칙을 사용합니다 — resolveId가 '\0virtual:my-id'를 반환하여 다른 플러그인이 건너뛰도록 합니다. 사용자 코드는 'virtual:my-id'를 가져옵니다.

전체 플러그인 API는 vite.dev/guide/api-plugin을 참조하세요. 개발 중 변환 파이프라인을 디버깅하려면 vite-plugin-inspect를 사용하세요.

HMR API

프레임워크 플러그인(@vitejs/plugin-react, @vitejs/plugin-vue 등)은 HMR을 자동으로 처리합니다. import.meta.hot은 사용자 정의 상태 저장소, 개발 도구 또는 업데이트 간 상태를 유지해야 하는 프레임워크에 구애받지 않는 유틸리티를 빌드할 때만 직접 사용하세요.

// src/store.ts — 일반 모듈용 수동 HMR
if (import.meta.hot) {
  // 업데이트 간 상태 유지 (반드시 변경해야 함, .data를 재할당하지 마세요)
  import.meta.hot.data.count = import.meta.hot.data.count ?? 0

  // 모듈이 교체되기 전에 부작용 정리
  import.meta.hot.dispose((data) => clearInterval(data.intervalId))

  // 이 모듈 자체 업데이트 수락
  import.meta.hot.accept()
}

모든 import.meta.hot 코드는 프로덕션 빌드에서 트리 쉐이킹되어 제거됩니다 — 가드 제거가 필요하지 않습니다.

환경 변수

Vite는 .env, .env.local, .env.[mode], .env.[mode].local을 순서대로 로드합니다 (나중 것이 이전 것을 덮어씀). *.local 파일은 gitignore되며 로컬 비밀용입니다.

클라이언트 측 접근

VITE_ 접두사가 붙은 변수만 클라이언트 코드에 노출됩니다:

import.meta.env.VITE_API_URL   // 문자열
import.meta.env.MODE            // 'development' | 'production' | 사용자 정의
import.meta.env.BASE_URL        // base 설정 값
import.meta.env.DEV             // 불리언
import.meta.env.PROD            // 불리언
import.meta.env.SSR             // 불리언

설정에서 Env 사용

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd())          // VITE_ 접두사만 (안전)
  return {
    define: {
      __API_URL__: JSON.stringify(env.VITE_API_URL),
    },
  }
})

보안

VITE_ 접두사는 보안 경계가 아닙니다

VITE_ 접두사가 붙은 모든 변수는 빌드 시 클라이언트 번들에 정적으로 인라인됩니다. 축소, base64 인코딩 및 소스 맵 비활성화는 이를 숨기지 않습니다. 결심한 공격자는 제공된 JavaScript에서 모든 VITE_ 변수를 추출할 수 있습니다.

규칙: 공개 값(API URL, 기능 플래그, 공개 키)만 VITE_ 변수에 넣으세요. 비밀(API 토큰, 데이터베이스 URL, 개인 키)은 반드시 API 또는 서버리스 함수 뒤의 서버 측에 있어야 합니다.

loadEnv('') 함정

// 나쁨: 세 번째 인수로 ''를 전달하면 모든 환경 변수(서버 비밀 포함)를 로드하고
// `define`을 통해 클라이언트 코드에 인라인할 수 있게 만듭니다.
const env = loadEnv(mode, process.cwd(), '')

// 좋음: 명시적인 접두사 목록
const env = loadEnv(mode, process.cwd(), ['VITE_', 'APP_'])

프로덕션 소스 맵

프로덕션 소스 맵은 원본 소스 코드를 유출합니다. 오류 추적기(Sentry, Bugsnag)에 업로드하지 않거나 이후 로컬에서 삭제하지 않는 한 비활성화하세요:

build: {
  sourcemap: false,                                  // 기본값 — 이 상태 유지
}

.gitignore 체크리스트

  • .env.local, .env.*.local — 로컬 비밀 재정의
  • dist/ — 빌드 출력
  • node_modules/.vite — 사전 번들 캐시 (오래된 항목은 유령 오류 발생)

서버 프록시

// vite.config.ts — server.proxy
server: {
  proxy: {
    '/foo': 'http://localhost:4567',                    // 문자열 단축

    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,                               // 가상 호스트 백엔드에 필요
      rewrite: (path) => path.replace(/^\/api/, ''),
    },
  },
}

WebSocket 프록시의 경우 경로 설정에 ws: true를 추가하세요.

빌드 최적화

수동 청크

// vite.config.ts — build.rolldownOptions
build: {
  rolldownOptions: {
    output: {
      // 객체 형식: 특정 패키지 그룹화
      manualChunks: {
        'react-vendor': ['react', 'react-dom'],
        'ui-vendor': ['@radix-ui/react-dialog', '@radix-ui/react-popover'],
      },
    },
  },
}
// 함수 형식: 휴리스틱으로 분할
manualChunks(id) {
  if (id.includes('node_modules/react')) return 'react-vendor'
  if (id.includes('node_modules')) return 'vendor'
}

성능

배럴 파일 피하기

배럴 파일(디렉터리의 모든 것을 다시 내보내는 index.ts)은 단일 심볼을 가져올 때도 Vite가 다시 내보내진 모든 파일을 로드하도록 강제합니다. 이는 공식 문서에서 지목한 #1 개발 서버 속도 저하 원인입니다.

// 나쁨 — 하나의 유틸을 가져오면 Vite가 전체 배럴을 로드하도록 강제
import { slash } from '@/utils'

// 좋음 — 직접 가져오기, 해당 파일만 로드됨
import { slash } from '@/utils/slash'

가져오기 확장자 명시하기

각 암시적 확장자는 resolve.extensions를 통해 최대 6번의 파일 시스템 검사를 강제합니다. 대규모 코드베이스에서는 이 비용이 누적됩니다.

// 나쁨
import Component from './Component'

// 좋음
import Component from './Component.tsx'

tsconfig.json의 allowImportingTsExtensions + resolve.extensions를 실제 사용하는 확장자로만 좁히세요.

핫 패스 경로 웜업

server.warmup.clientFiles는 브라우저가 요청하기 전에 알려진 핫 항목을 미리 변환하여 대규모 앱의 콜드 로드 요청 워터폴을 제거합니다.

// vite.config.ts
server: {
  warmup: {
    clientFiles: ['./src/main.tsx', './src/routes/**/*.tsx'],
  },
}

느린 개발 서버 프로파일링

vite dev가 느리게 느껴질 때, vite --profile로 시작하고 앱과 상호 작용한 다음 p+enter를 눌러 .cpuprofile을 저장하세요. Speedscope에 로드하여 어떤 플러그인이 시간을 소비하는지 찾으세요 — 일반적으로 커뮤니티 플러그인의 buildStart, config 또는 configResolved 훅입니다.

라이브러리 모드

npm 패키지를 배포할 때는 build.lib를 사용하세요. 설정 세부 사항보다 두 가지 문제가 더 중요합니다:

  1. 타입이 생성되지 않습니다 — vite-plugin-dts를 추가하거나 별도로 tsc --emitDeclarationOnly를 실행하세요.
  2. 피어 의존성은 반드시 외부화되어야 합니다 — 나열되지 않은 피어는 라이브러리에 번들링되어 소비자에서 중복 런타임 오류를 발생시킵니다.
// vite.config.ts
build: {
  lib: {
    entry: 'src/index.ts',
    formats: ['es', 'cjs'],
    fileName: (format) => `my-lib.${format}.js`,
  },
  rolldownOptions: {
    external: ['react', 'react-dom', 'react/jsx-runtime'],  // 모든 피어 종속성
  },
}

SSR 외부 종속성

단순한 createServer({ middlewareMode: true }) 설정은 프레임워크 작성자의 영역입니다. 대부분의 앱은 대신 Nuxt, Remix, SvelteKit, Astro 또는 TanStack Start를 사용해야 합니다. 프레임워크 사용자로서 조정할 것은 종속성이 SSR에서 깨질 때 외부화 설정입니다:

// vite.config.ts — ssr 옵션
ssr: {
  external: ['node-native-package'],           // SSR 번들에서 require()로 유지
  noExternal: ['esm-only-package'],            // SSR 출력에 강제 번들링 (대부분의 SSR 오류 수정)
  target: 'node',                              // 'node' 또는 'webworker'
}

의존성 사전 번들링

Vite는 종속성을 사전 번들링하여 CJS/UMD를 ESM으로 변환하고 요청 수를 줄입니다.

// vite.config.ts — optimizeDeps
optimizeDeps: {
  include: [
    'lodash-es',                              // 알려진 무거운 종속성을 강제 사전 번들링
    'cjs-package',                            // 상호 운용 문제를 일으키는 CJS 종속성
    'deep-lib/components/**',                 // 깊은 가져오기를 위한 글롭
  ],
  exclude: ['local-esm-package'],             // 제외 시 유효한 ESM이어야 함
  force: true,                                // 캐시 무시, 재최적화 (임시 디버깅)
}

일반적인 문제

개발과 빌드 불일치

개발은 esbuild/Rolldown을 변환에 사용하고, 빌드는 Rolldown을 번들링에 사용합니다. CJS 라이브러리는 둘 사이에서 다르게 동작할 수 있습니다. 배포 전에 항상 vite build && vite preview로 확인하세요.

배포 후 오래된 청크

새 빌드는 새 청크 해시를 생성합니다. 활성 세션이 있는 사용자는 더 이상 존재하지 않는 이전 파일 이름을 요청합니다. Vite에는 내장된 해결책이 없습니다. 완화 방법:

  • 배포 기간 동안 이전 dist/assets/ 파일을 계속 유지
  • 라우터에서 동적 가져오기 오류를 포착하고 페이지 새로고침 강제

Docker 및 컨테이너

Vite는 기본적으로 localhost에 바인딩되며, 이는 컨테이너 외부에서 연결할 수 없습니다:

// vite.config.ts — Docker/컨테이너 설정
server: {
  host: true,                                  // 0.0.0.0에 바인딩
  hmr: { clientPort: 3000 },                   // 역방향 프록시 뒤에 있는 경우
}

모노레포 파일 접근

Vite는 파일 제공을 프로젝트 루트로 제한합니다. 루트 외부의 패키지는 차단됩니다:

// vite.config.ts — 모노레포 파일 접근
server: {
  fs: {
    allow: ['..'],                             // 상위 디렉터리 허용 (워크스페이스 루트)
  },
}

안티 패턴

// 나쁨: envPrefix를 ''로 설정하면 모든 환경 변수(비밀 포함)가 클라이언트에 노출됨
envPrefix: ''

// 나쁨: Vite 빌드에서 require()가 작동한다고 가정

...

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

관련 스킬