Programming/React

[React] React(TS) + Vite + npm(pnpm) 모노레포 프로젝트 구성하기

보간 2025. 1. 20. 02:28
  • 멋쟁이사자처럼 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

+ 숨김 폴더 .git 은 현재 표시되지 않으나 존재한다.


 

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

package-lock은 패키지가 업데이트될 때마다 버전 변경 정보를 저장한다.


 

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기 - 리액트 커스텀 앱 빌드 - 야무 쌤