[React] React(TS) + Vite + npm(pnpm) 모노레포 프로젝트 구성하기
- 멋쟁이사자처럼 2주차 과제로 React + Vite 프로젝트 템플릿을 구성하는 과정과 유의점을 정리
1. Git
Git 초기화
프로젝트 버전 관리를 위한 Git 초기화
git init # -b main
Git 관리 제외
➕ .gitignore
Git 관리 제외 파일 - 제외 항목을 추가한다.
라인 엔딩 설정
라인 엔딩(line ending): 텍스트 파일 줄의 끝을 나타내는 문자나 문자 조합 UNIX 계열에서는 \\n을 사용하지만, MS-DOS와 Windows에서는 \\r\\n을 사용
Windows에서 작성한 파일을 macOS에서 열면 줄 바꿈 표시가 잘못될 수 있어, 모든 텍스트 파일의 줄 바꿈 문자를 자동 변환하도록 설정한다.
➕ .gitattributes
text eol=lf
2. 에디터 구성 및 기본 메타 데이터* 설정
*데이터에 대한 정보를 제공하는 데이터
에디터 구성 설정
➕ .editorconfig
일관된 코딩 스타일을 유지하는 데 도움이 되도록 .editorconfig 파일 추가
코드 확인
# root = true: 이 파일이 프로젝트의 최상위 .editorconfig 파일임을 나타냄
# (하위 디렉터리에는 이 설정이 자동으로 상속되지 않음)
root = true
# [*]: 모든 파일에 대한 기본 설정을 적용
[*]
# indent_style = space: 공백 문자로 들여쓰기를 설정
indent_style = space
# indent_size = 2: 들여쓰기 크기를 2로 설정
indent_size = 2
# end_of_line = lf: 파일의 끝에 LF(Line Feed)를 사용하여 줄 바꿈을 설정
end_of_line = lf
# charset = utf-8: 파일의 문자 인코딩을 UTF-8로 설정
charset = utf-8
# trim_trailing_whitespace = false: 줄 끝의 공백을 자동으로 제거하지 않도록 설정
trim_trailing_whitespace = false
# insert_final_newline = false: 파일 끝에 새로운 줄을 자동으로 추가하지 않도록 설정
insert_final_newline = false
메타 데이터
➕ package.json
패키지 매니저를 사용해 프로젝트를 관리하기 위한 메타 데이터 파일 작성
코드 확인
{
// private: 프로젝트가 비공개임. true로 설정하면 npm에 배포되지 않음.
"private": true,
// type: "module"로 설정하면 ES6 모듈 시스템을 사용하여 import/export 문법을 사용가능.
"type": "module",
// name: 프로젝트의 이름을 정의. 이 이름은 npm에 배포할 때 사용됨.
"name": "vite-react",
// description: 프로젝트에 대한 간단한 설명을 추가
"description": "Vite 빌드도구 React 커스텀 템플릿",
// version: 프로젝트의 버전 정보를 지정. 보통 semantic versioning을 따름
"version": "1.0.0",
// engines: 프로젝트가 요구하는 Node.js와 VSCode의 버전을 정의.
"engines": {
// node: 이 프로젝트는 최소 Node.js 22.12.0 버전 이상에서 실행됨.
"node": "^22.12.0",
// vscode: 이 프로젝트는 VSCode 1.96.0 이상에서 작동하도록 설정됨.
"vscode": "^1.96.0"
}
}
➕ .npmrc
코드 확인
# 참고: https://docs.npmjs.com/cli/v8/using-npm/config
package-lock=true
save-exact=true
yes=true
init-license=MIT
init-version=1.0.0
3. Vite 설정
설치 명령
npm i vite -D
pnpm add vite -D
개발 서버 구동, 빌드, 빌드 결과 미리보기(preview) NPM 스크립트 명령어 추가(터미널로 확인 가능)
➕ package.json 수정
"scripts": {
"start": "npm run dev --open",
"dev": "vite --host",
"build": "vite build",
"preview": "vite preview"
}
"scripts": {
"start": "pnpm dev --open",
"dev": "vite --host",
"build": "vite build",
"preview": "vite preview"
}
Vite 구성 파일
➕ vite.config.ts
Vite 구성 파일을 읽어 터미널에 등록된 명령이 실행됨
import { defineConfig } from 'vite';
/** @type {import('vite').UserConfig} */
export default defineConfig({
server: {
host: 'localhost',
port: 3000,
},
preview: {
port: 8080
}
});
4. React & React DOM + TypeScript 구성
React, ReactDOM은 JavaScript로 개발되어 별도로 타입 정의를 제공하지 않으므로 VS Code에서 타입 정의를 읽어와@types/react, @types/react-dom 타입 정의 패키지를 개발 종속성 모듈로 설치
npm i react@19 react-dom@19
npm i @types/{react,react-dom} -D # 타입 정의
pnpm add react@19 react-dom@19
pnpm add @types/{react,react-dom} -D # 타입 정의
React 플러그인 구성
프로젝트 @vitejs/plugin-react 플러그인을 설치
이 플러그인을 설치하면 다음 기능이 활성화됨
- 개발 중 빠르게 새로고침
- JSX 런타임을 자동 주입
- Babel 플러그인/프리셋을 사용
npm i @vitejs/plugin-react -D
pnpm add @vitejs/plugin-react -D
설치한 플러그인을 Vite 구성 파일에 설정
➕ vite.config.ts
코드 확인
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
/** @type {import('vite').UserConfig} */
export default defineConfig({
plugins: [
react({
jsxRuntime: 'automatic',
}),
],
// ...
});
플러그인이 설정되면 import React from 'react' 구문 생략가능
5. TypeScript 구성
설치 명령
npm i typescript -D
pnpm add typescript -D
TypeScript 구성 파일
➕ tsconfig.json
tsconfig.json 파일에 참조(references)하는 2개의 JSON 파일을 추가
{
"files": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.node.json"
}
]
}
➕ tsconfig.app.json
React 앱 개발에 사용된 src 폴더의 TypeScript 파일 컴파일에 사용
코드 확인
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* 별칭 */
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
/* 번들러 모드 */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* 린팅 */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}
➕ tsconfig.node.json
vite.config.ts 파일 컴파일에 사용
코드 확인
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* 번들러 모드 */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* 린팅 */
"strict": true,
"noUnusedLocals": true,
"noUncheckedSideEffectImports": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["vite.config.ts"]
}
✔unknown complier option Error가 발생할 경우
- 해당 타입스크립트 버전을 확인한다.
- VScode를 사용할 시 workspace에서 타입스크립트 변경 버전이 곧바로 작동하지 않을 수 있다.
- ctrl+shift+p으로 명령팔레트를 연 후 typeScript: Select TypeScript Version 을 선택하고 최신 버전을 확인해보자.
Client 타입 정의 참조
TypeScript 파일에서 이미지, 폰트, 스타일시트 파일 등을 불러오려 시도하면 오류가 발생한다. 해당 파일에 대한 타입 정보가 없기 때문이다. 따라서 아래의 파일을 설정해준다.
➕ vite-env.d.ts
/// <reference types="vite/client" />
6. ESLint & Prettier 구성
ESLint 설치 명령
npm i @eslint/config@latest
pnpm create @eslint/config@latest
ESLint 플러그인 추가 구성 설치
npm i eslint-plugin-react-{refresh,hooks} eslint-plugin-jsx-a11y -D
pnpm add eslint-plugin-react-{refresh,hooks} eslint-plugin-jsx-a11y -D
설치한 플러그인 설정을 eslint.config.js 파일에 추가
➕ eslint.config.js
코드 확인
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import jsxA11y from "eslint-plugin-jsx-a11y";
export default tseslint.config(
{
ignores: ["dist"],
},
{
files: ["**/*.{ts,tsx}"],
...jsxA11y.flatConfigs.recommended,
settings: {
react: {
version: "19.0.0",
},
},
languageOptions: {
ecmaVersion: 2020,
globals: {
...globals.browser,
...globals.node,
},
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: import.meta.dirname,
ecmaFeatures: { jsx: true },
},
},
},
{
extends: [
js.configs.recommended,
...tseslint.configs.recommendedTypeChecked,
...tseslint.configs.stylisticTypeChecked,
],
plugins: {
react,
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...react.configs.flat.recommended.rules,
...react.configs["jsx-runtime"].rules,
...reactHooks.configs.recommended.rules,
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
},
}
);
ESLint 린팅* 명령 추가
*소스 코드를 분석하여 잠재적인 오류, 스타일 규칙 위반, 비효율적인 코드 등을 찾아내는 과정. 주로 코드 품질을 향상시키기 위해 사용
src 폴더 내부의 파일만 린팅 검사를 수행하도록 package.json 파일에 lint 명령을 추가
➕ package.json
"scripts": {
"lint": "eslint --cache 'src/**/*.{ts,tsx}'"
}
Prettier 포멧팅 구성
설치 명령
npm i prettier -D
Prettier 포멧터 구성
➕ prettier.config.cjs
포멧팅 구성 옵션을 설정
코드 확인
module.exports = {
// 화살표 함수 식 매개변수 () 생략 여부 (ex: (a) => a)
arrowParens: 'always',
// 닫는 괄호(>) 위치 설정
// ex: <div
// id="unique-id"
// class="contaienr"
// >
htmlWhitespaceSensitivity: 'css',
bracketSameLine: false,
// 객체 표기 괄호 사이 공백 추가 여부 (ex: { foo: bar })
bracketSpacing: true,
// 행폭 설정 (줄 길이가 설정 값보다 길어지면 자동 개행)
printWidth: 80,
// 산문 래핑 설정
proseWrap: 'preserve',
// 객체 속성 key 값에 인용 부호 사용 여부 (ex: { 'key': 'xkieo-xxxx' })
quoteProps: 'as-needed',
// 세미콜론(;) 사용 여부
semi: true,
// 싱글 인용 부호(') 사용 여부
singleQuote: true,
// 탭 너비 설정
tabWidth: 2,
// 객체 마지막 속성 선언 뒷 부분에 콤마 추가 여부
trailingComma: 'es5',
// 탭 사용 여부
useTabs: false,
};
Prettier 포멧 명령 추가
➕ package.json
src 폴더 내부의 파일만 포멧팅 적용되도록 package.json 파일에 format 명령을 추가
"scripts": {
"format": "prettier --cache 'src/**/*.{ts,tsx}'"
}
절대 경로 구성
➕ vite.config.ts
Vite 프로젝트에서 절대 경로(absolute path)를 사용하려면 resolve.alias 설정이 필요
import { fileURLToPath } from 'node:url';
export default defineConfig({
// ...
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
});
pnpm add @types/node
하지만 VS Code는 @ 별칭 절대 경로에 대한 정보가 없으므로 정상적인 파일 탐색이 되지 않는다. 문제 해결을 위해 tsconfig.app.json 파일에 다음 구성을 추가해 VS Code에서 파일 탐색이 가능하도록 설정한다.
➕ tsconfig.app.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
7. Husky
허스키는 푸시 할 때 린팅, 테스트 등을 수행하여 Git 커밋을 향상시키는데 도움을 주는 도구
Husky
typicode.github.io
허스키는 모든 Git 훅(hooks)*을 지원하며 훅을 손쉽게 생성할 수 있는 기능을 제공
- git 실행 특정 지점에서 작업 실행을 위해 hooks 디렉터리에 배치할 수 있는 프로그램
설치 및 자동 구성
npm i husky -D
npx husky init
pnpm add husky -D
pnpm husky init
lint-staged
린팅(linting)은 코드를 커밋하기 전에 실행해야 의미가 있다. 커밋 전에 코드를 린팅하면 Git 저장소에 오류 없이 코드 스타일을 적용할 수 있다.
설치 명령
lint-staged는 준비된 파일 목록을 인자로 설정하고 지정된 glob 패턴을 통해 필터링 된 임의의 셸 작업을 실행하는 스크립트가 포함되어 있다.
npm i lint-staged -D
pnpm add lint-staged -D
GitHub - lint-staged/lint-staged: 🚫💩 — Run tasks like formatters and linters against staged git files
🚫💩 — Run tasks like formatters and linters against staged git files - lint-staged/lint-staged
github.com
구성
➕ package.json
package.json 파일에 lint-staged 항목을 추가하고, 사전에 설정한 린팅, 포멧팅 명령을 설정한다.
"lint-staged": {
"src/**/*.{ts,tsx}": [
"pnpm lint",
"pnpm format"
]
}
pre-push 훅
➕ .husky/pre-push
pre-push 파일을 작성한 뒤 npx lint-staged 명령을 입력하면 푸시하기 전 린팅, 포멧팅을 수행
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
해당 환경에서의 index (엔트리 파일) 파일 구성과 컴포넌트 작성 방식은 git 저장소를 참고하길 바란다.
GitHub - akman12914/likelion-react-homework: likelion-react-homework 2주차 과제 - vite-react 템플릿
likelion-react-homework 2주차 과제 - vite-react 템플릿 . Contribute to akman12914/likelion-react-homework development by creating an account on GitHub.
github.com
출처
멋쟁이 사자처럼 12기 - 리액트 커스텀 앱 빌드 - 야무 쌤