Vite 개발 서버 설정 문제: 핫 리로딩 및 프록시 구성
Vite 개발 서버 설정 시 발생하는 문제와 핫 리로딩, 프록시 설정 방법을 설명합니다.
Vite 개발 서버 설정 문제
Introduction
Vite는 빠르고 경량적인 프론트엔드 개발 서버로, 네이티브 ES 모듈을 활용하여 즉시 시작되는 개발 경험을 제공합니다. 하지만 프로젝트 규모가 커지면서 핫 모듈 리플레이스먼트(HMR), 프록시 설정, 환경 변수 등에서 다양한 문제에 직면할 수 있습니다. 이 글에서는 Vite 개발 서버 설정 문제 해결 방법을 다루겠습니다.
Environment
// package.json
{
"name": "my-vite-app",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.2.0",
"vite": "^5.0.0",
"typescript": "^5.3.0"
}
}npx vite --version
# vite/5.0.11Problem
Vite 개발 서버 설정 시 발생하는 문제들:
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
port: 3000,
proxy: '/api'
}
});
// 문제점:
// 1. HMR이 작동하지 않음
// 2. 프록시 설정 오류
// 3. 환경 변수 로딩 실패# 개발 서버 실행 시 에러
npm run dev
# 에러:
# Port 3000 is already in use
# [vite] server error: Cannot use 'in' operator to search for 'VITE_' in undefined// 환경 변수 접근 오류
const apiUrl = import.meta.env.VITE_API_URL;
console.log(apiUrl); // undefined
// 환경 변수 파일 로딩 실패
// .env 파일에 VITE_API_URL 정의했으나 접근 불가Analysis
Vite 설정 구조를 분석했습니다:
// vite.config.ts 구조 분석
import { defineConfig } from 'vite';
export default defineConfig({
// 플러그인 설정
plugins: [],
// 개발 서버 설정
server: {
port: 3000,
strictPort: false,
host: 'localhost',
open: true,
proxy: {}
},
// 빌드 설정
build: {
outDir: 'dist',
sourcemap: true,
minify: 'terser'
},
// 환경 변수 접두사
envPrefix: 'VITE_',
// 미리보기 설정
preview: {
port: 4173
}
});# Vite 환경 변수 파일 우선순위
# .env # 모든 경우
# .env.local # 모든 경우, git 무시
# .env.[mode] # 특정 모드
# .env.[mode].local # 특정 모드, git 무시Solution
1단계: 기본 설정 구성
// vite.config.ts
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig(({ mode }) => {
// 환경 변수 로드
const env = loadEnv(mode, process.cwd(), '');
return {
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@utils': path.resolve(__dirname, './src/utils')
}
},
server: {
port: 3000,
strictPort: false,
host: 'localhost',
open: true,
cors: true,
// 에러 오버레이 설정
appType: 'spa'
},
build: {
outDir: 'dist',
sourcemap: true,
minify: 'terser',
// 번들 분석
reportCompressedSize: true,
chunkSizeWarningLimit: 1000,
// 코드 분할
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
utils: ['lodash']
}
}
}
},
envPrefix: 'VITE_',
css: {
devSourcemap: true
}
};
});2단계: 프록시 설정
// vite.config.ts (프록시 설정)
export default defineConfig({
server: {
port: 3000,
proxy: {
// 기본 API 프록시
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
secure: false,
rewrite: (path) => path.replace(/^\/api/, '')
},
// WebSocket 프록시
'/ws': {
target: 'ws://localhost:8080',
ws: true,
changeOrigin: true
},
// GraphQL 프록시
'/graphql': {
target: 'http://localhost:8080',
changeOrigin: true,
secure: false
},
// 정적 파일 프록시
'/uploads': {
target: 'http://localhost:8080',
changeOrigin: true
}
},
// 프록시 커스터마이징
configure: (proxy) => {
proxy.on('error', (err) => {
console.log('proxy error', err);
});
proxy.on('proxyReq', (proxyReq, req, res) => {
console.log('Proxying:', req.method, req.url);
});
proxy.on('proxyRes', (proxyRes, req, res) => {
console.log('Response from proxy:', proxyRes.statusCode);
});
}
}
});3단계: HMR 최적화
// vite.config.ts (HMR 설정)
export default defineConfig({
server: {
hmr: {
// HMR 연결 설정
host: 'localhost',
port: 3000,
// WebSocket 프로토콜
protocol: 'ws',
// HMR 업데이트 필터링
overlay: {
errors: true,
warnings: false
}
},
watch: {
// 파일 감시 설정
usePolling: false,
interval: 100,
// 무시할 디렉토리
ignored: ['**/node_modules/**', '**/dist/**', '**/.git/**']
}
},
// 환경 변수 정의
define: {
__APP_VERSION__: JSON.stringify(process.env.npm_package_version),
__DEV_MODE__: JSON.stringify(process.env.NODE_ENV)
}
});4단계: 환경 변수 관리
# .env.development
VITE_API_URL=http://localhost:8080
VITE_APP_TITLE=My App (Dev)
VITE_LOG_LEVEL=debug
# .env.production
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App
VITE_LOG_LEVEL=error
# .env.local (git 무시)
VITE_API_KEY=your-secret-key// src/config/env.ts
interface EnvConfig {
API_URL: string;
APP_TITLE: string;
LOG_LEVEL: string;
}
export const env: EnvConfig = {
API_URL: import.meta.env.VITE_API_URL || 'http://localhost:3000',
APP_TITLE: import.meta.env.VITE_APP_TITLE || 'My App',
LOG_LEVEL: import.meta.env.VITE_LOG_LEVEL || 'info'
};
// 타입 안전한 환경 변수 사용
export function getEnv(key: keyof EnvConfig): string {
const value = env[key];
if (!value) {
throw new Error(`Environment variable ${key} is not defined`);
}
return value;
}Lessons Learned
- HMR 설정: HMR이 작동하지 않으면
server.watch옵션과 파일 감시 설정을 확인해야 합니다 - 프록시 설정: CORS 문제 해결을 위해
changeOrigin: true옵션을 반드시 설정해야 합니다 - 환경 변수 접두사: Vite 환경 변수는
VITE_접두사가 붙어야 클라이언트에서 접근 가능합니다 - 타입 안전성:
import.meta.env타입을 정의하여 환경 변수의 타입 안전성을 확보해야 합니다 - 빌드 최적화: 코드 분할과 청크 크기 경고를 설정하여 빌드 결과를 최적화해야 합니다
이 블로그는 외부 스폰서십, 제휴 마케팅 또는 광고 수익을 받지 않습니다.