환경 설정 — Vite + React 프로젝트 구성
Vite를 선택하는 이유
2021년 이전까지는 **Create React App(CRA)**이 공식 스캐폴딩 도구였습니다. 하지만 CRA는 내부적으로 Webpack을 사용하여 개발 서버 시작에 수십 초가 걸리는 문제가 있었습니다. 현재 React 공식 문서는 CRA 대신 Vite, Next.js, Remix 등을 권장합니다.
CRA vs Vite 비교
| 항목 | CRA | Vite |
|---|---|---|
| 번들러 | Webpack | esbuild(개발) + Rollup(빌드) |
| 콜드 스타트 | 20~60초 | 1~3초 |
| HMR 속도 | 느림 | 즉각 반응 |
| 유지보수 | 사실상 중단됨 | 활발히 개발 중 |
| 번들 크기 | 더 큼 | 더 작음 |
Vite + React 프로젝트 생성
기본 생성
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
TypeScript 템플릿
npm create vite@latest my-react-app -- --template react-ts
인터랙티브 모드
npm create vite@latest
# 프롬프트에 따라 선택:
# ✔ Project name: my-app
# ✔ Select a framework: React
# ✔ Select a variant: JavaScript / TypeScript / JavaScript + SWC / TypeScript + SWC
**SWC(Speedy Web Compiler)**는 Rust로 작성된 초고속 Babel 대체재입니다. 성능이 중요하다면
react-swc변형을 선택하세요.
프로젝트 폴더 구조
my-react-app/
├── public/ # 정적 파일 (그대로 복사됨)
│ └── vite.svg
├── src/ # 소스 코드
│ ├── assets/ # 이미지, 폰트 등
│ ├── components/ # 재사용 컴포넌트
│ ├── pages/ # 페이지 컴포넌트 (라우터 사용 시)
│ ├── hooks/ # 커스텀 훅
│ ├── App.jsx # 루트 컴포넌트
│ ├── App.css
│ ├── main.jsx # 진입점
│ └── index.css
├── index.html # Vite의 진입점 HTML
├── vite.config.js # Vite 설정
├── package.json
└── .eslintrc.cjs # ESLint 설정
main.jsx — 진입점
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App.jsx';
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
);
App.jsx — 루트 컴포넌트
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import './App.css';
function App() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Vite + React</h1>
<button onClick={() => setCount(count + 1)}>
count is {count}
</button>
</div>
);
}
export default App;
개발 명령어
npm run dev # 개발 서버 시작 (기본 포트: 5173)
npm run build # 프로덕션 빌드 (dist/ 폴더 생성)
npm run preview # 빌드 결과물을 로컬에서 미리보기
npm run lint # ESLint 실행
포트 변경
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
port: 3000, // 개발 서버 포트
open: true, // 브라우저 자동 열기
},
});
경로 별칭(Path Alias) 설정
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@hooks': path.resolve(__dirname, './src/hooks'),
},
},
});
이후 절대 경로로 import 가능합니다.
// 변경 전
import Button from '../../components/Button';
// 변경 후
import Button from '@components/Button';
ESLint + Prettier 설정
설치
npm install -D eslint-config-prettier prettier
npm install -D @typescript-eslint/parser @typescript-eslint/eslint-plugin # TypeScript 사용 시
.eslintrc.cjs
module.exports = {
root: true,
env: { browser: true, es2024: true },
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'prettier', // prettier와 충돌하는 규칙 비활성화
],
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
plugins: ['react-refresh'],
rules: {
'react/react-in-jsx-scope': 'off', // React 17+ 자동 JSX Transform
'react-refresh/only-export-components': 'warn',
},
};
.prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
React DevTools 설치
브라우저 확장 프로그램으로 설치합니다.
주요 기능
| 탭 | 용도 |
|---|---|
| Components | 컴포넌트 트리 탐색, props/state 확인 및 수정 |
| Profiler | 렌더링 성능 측정, 어느 컴포넌트가 왜 렌더링됐는지 |
DevTools 팁
// 컴포넌트에 displayName 설정 (익명 함수 시 유용)
const MemoizedCard = React.memo(function Card({ title }) {
return <div>{title}</div>;
});
MemoizedCard.displayName = 'MemoizedCard';
실전 예제: 추천 폴더 구조 (Feature-based)
src/
├── features/
│ ├── auth/
│ │ ├── components/ LoginForm.jsx, RegisterForm.jsx
│ │ ├── hooks/ useAuth.js
│ │ ├── api.js # auth 관련 API 호출
│ │ └── index.js # public API export
│ └── products/
│ ├── components/ ProductCard.jsx, ProductList.jsx
│ ├── hooks/ useProducts.js
│ └── index.js
├── shared/
│ ├── components/ Button.jsx, Modal.jsx, Input.jsx
│ ├── hooks/ useDebounce.js, useLocalStorage.js
│ └── utils/ formatDate.js, validators.js
├── App.jsx
└── main.jsx
고수 팁
1. Vite 환경 변수
# .env
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App
// 컴포넌트에서 사용
const apiUrl = import.meta.env.VITE_API_URL;
VITE_ 접두사가 붙은 변수만 클라이언트에 노출됩니다.
2. HMR 유지를 위한 export 규칙
// ✅ 컴포넌트를 named export 또는 default export 하나만
export default function Counter() { /* ... */ }
// ❌ 컴포넌트와 다른 값을 같은 파일에서 export하면 HMR 경고 발생
export const CONSTANT = 42;
export default function Counter() { /* ... */ }
3. 빌드 최적화 확인
npm run build
# dist/ 폴더 내 파일 크기 확인
# index-[hash].js: 앱 코드
# vendor-[hash].js: node_modules 코드 (청크 분리됨)
vite-bundle-visualizer 패키지로 번들 구성을 시각적으로 분석할 수 있습니다.