Vite의 react-ts 템플릿이 만든 폴더와 파일이 각각 어떤 역할을 하는지 살펴보고, 프로젝트가 커질 때 쓸 만한 폴더 구성과 설정 방법을 정리합니다.
기본 폴더 구성
my-app/
├── public/
│ └── vite.svg
├── src/
│ ├── assets/
│ │ └── react.svg
│ ├── App.css
│ ├── App.tsx
│ ├── index.css
│ └── main.tsx
├── eslint.config.js
├── index.html
├── package.json
├── tsconfig.json
├── tsconfig.app.json
├── tsconfig.node.json
└── vite.config.ts
index.html과 main.tsx
다른 번들러와 달리 Vite에서는 index.html이 프로젝트 루트에 있고, 이 파일이 곧 진입점입니다. <script type="module">이 가리키는 src/main.tsx부터 의존성을 따라가며 모듈을 불러옵니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>my-app</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
main.tsx는 react-dom/client의 createRoot로 #root 요소에 React 루트를 만들고 App을 그립니다. 앱 전체에 필요한 Provider(라우터, 데이터 요청 라이브러리, 테마 등)도 보통 이곳에서 감쌉니다.
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>,
);
package.json 스크립트
{
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
}
}
Vite는 빌드 속도를 위해 타입 검사를 하지 않고 코드 변환만 합니다. 그래서 build 스크립트는 먼저 tsc -b로 타입을 검사하고, 오류가 없을 때만 vite build를 실행합니다. preview는 빌드 결과물을 로컬에서 확인할 때 씁니다.
vite.config.ts와 경로 별칭
../../components/Button 같은 긴 상대 경로 대신 @/components/Button처럼 쓰고 싶다면 Vite와 TypeScript 양쪽에 별칭을 등록합니다.
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
resolve: {
alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) },
},
server: { port: 3000 },
});
{
"compilerOptions": {
"paths": { "@/*": ["./src/*"] }
}
}
위 paths 설정은 앱 코드를 검사하는 tsconfig.app.json의 compilerOptions에 추가합니다. 설정 파일에서 node:url을 쓰려면 npm install -D @types/node가 필요할 수 있습니다.
환경 변수
Vite는 프로젝트 루트의 .env, .env.local, .env.production 같은 파일을 읽습니다. 이 가운데 VITE_로 시작하는 변수만 클라이언트 코드에 노출되며, import.meta.env로 읽습니다.
# .env.local (Git에 올리지 않습니다)
VITE_API_URL=http://localhost:8080
const apiUrl = import.meta.env.VITE_API_URL;
const isDev = import.meta.env.DEV;
이 값들은 빌드 시점에 코드에 그대로 박히므로 누구나 볼 수 있습니다. API 비밀 키 같은 비밀 값은 절대 VITE_ 변수에 넣지 말고 서버 쪽에서 다룹니다.
커지는 프로젝트의 폴더 구성
React는 폴더 구조를 강제하지 않습니다. 작은 앱은 src/components/ 하나로 충분하고, 커지면 기능(feature) 단위로 나누는 방식이 흔히 쓰입니다.
src/components/: 버튼, 모달처럼 여러 화면에서 쓰는 공용 컴포넌트src/features/<기능>/: 한 기능에 속한 컴포넌트, 훅, API 호출을 한곳에src/hooks/: 여러 기능에서 쓰는 사용자 정의 훅(useDebounce.ts 등)src/lib/: 화면과 무관한 함수, API 클라이언트src/pages/ 또는 src/routes/: 라우터를 쓸 때 페이지 단위 컴포넌트
관례적으로 컴포넌트 파일은 UserCard.tsx처럼 파스칼 표기법(PascalCase)을, 훅은 useUser.ts처럼 use로 시작하는 이름을 씁니다. 스타일은 전역 CSS를 import하거나, 이름이 겹치지 않는 CSS Modules(Button.module.css)를 쓰거나, Tailwind CSS 같은 도구를 붙일 수 있습니다.
정리
index.html이 진입점이고, src/main.tsx가 #root에 React 앱을 연결합니다.npm run build는 tsc -b로 타입을 검사한 뒤 vite build로 묶습니다.- 경로 별칭은
vite.config.ts와 tsconfig.app.json 두 곳에 등록합니다. VITE_ 환경 변수는 공개 값이므로 비밀을 넣지 않습니다.- 앱이 커지면 기능 단위 폴더와 일관된 파일 이름 규칙으로 정리합니다.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.