본문 바로가기

Front

프론트 환경 설정(PNPM, Vite, React, TypeScript, TailwindCss)

프로젝트를 시작할 때 보통 스캐폴딩 도구(CLI)를 사용하거나 이전에 사용했던 설정 파일을 복사해서 쓰곤 했었는데, 모노레포 구조를 연습하는 과정에서 많은 어려움을 겪었고, 프로젝트 설정에 대해 기본적인 개념을 공부해야할 필요성을 느꼈다. 프로젝트 초기 설정 방법을 공부하려는 목적인 만큼 스캐폴딩 도구 없이 굳이 빈폴더에서 부터 시작하여 평소 사용해 본 도구 및 라이브러리를 모두 추가하며 설정에 대해 공부한 내용을 기록해보았다.

추가 될 예정인 도구 및 라이브러리

  • 패키지 매니저 : PNPM
  • 빌드 도구 : Vite
  • 코어 : React, TypeScript
  • 스타일링 : Tailwind CSS, Shadcn UI
  • 데이터 및 네트워크 : Axios, Tanstack Query, MSW
  • 코드 퀄리티 : ESLint, Prettier

(Shadcn UI, Axios, Tanstack Query, MSW, ESLint, Prettier 에 대한 내용은 다음 포스팅에서 확인 가능하다)

 

1. 빈 폴더 생성, 패키지 매니저 초기화

node, pnpm이 이미 설치되어 있다는 전제 하에 원하는 프로젝트 명의 빈 폴더를 생성하고 해당 경로에서 pnpm init 명령어를 입력하면 package.json 파일 생성된다. 라이브러리 배포용이 아니기 때문에 관련 필드는 제거해주었다.

pnpm init
// ./package.json
{
  "name": "empty-project",
  "version": "1.0.0",
  "description": "",
//  "main": "index.js",
  "scripts": {
    "test": "echo \\"Error: no test specified\\" && exit 1"
  },
//  "keywords": [],
//  "author": "",
//  "license": "ISC",
//  "packageManager": "pnpm@10.27.0"
}

패키지 매니저에 대해 좋은 공부가 되었던 포스팅 > https://toss.tech/article/lightning-talks-package-manager

 

2. 핵심 도구 Vite + React 설치

스캐폴딩 도구를 사용해서 프로젝트를 생성할 땐 몰랐는데, 리액트 프레임워크를 사용하는 경우 react 와 react-dom 이 필요하며, react 는 컴포넌트 구조와 로직을 정의하는 역할, react-dom 은 이렇게 만들어 둔 컴포넌트를 실제로 웹에 연결하고 렌더링 해주는 역할이다.

react, react-dom 설치 명령어

pnpm add react react-dom

빌드 도구이자 번들러인 Vite 를 사용하기 위해 vite 와 @vitejs/plugin-react 가 필요하며, @vitejs/plugin-react 는 Vite 환경에서 React 를 사용하기 위해 필요한 공식 플러그인으로 JSX 변환이나 React Fast Refresh(HMR) 기능 등을 지원해주는 라이브러리이다.

vite, @vitejs/plugin-react 설치 명령어

pnpm add -D vite @vitejs/plugin-react

설치가 완료되면 package.json에 아래와 같이 추가 되어진다.

(보통 latest 버전이 설치 되기 때문에 버전은 설치하는 시점에 따라 다를 수 있다.)

// package.json
{
  ...
  "dependencies": {
    "react": "^19.2.3",
    "react-dom": "^19.2.3"
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^5.1.2",
    "vite": "^7.3.1"
  }
}

 

다음으로 vite 도구가 빌드하는 시점에 참고 할 설정 파일을 작성해준다.

설치해둔 @vitejs/plugin-react 플러그인을 plugins 에 추가해주어 이 프로젝트를 빌드할 때 해당 플로그인을 사용하여 JSX 변환 및 HMR 기능을 지원해 줄 수 있도록 한다. 추가로 루트(src) 경로에 ‘@’ 별칭을 지정해주는 설정도 추가 해준다.

(타입스크립트를 사용할 예정이기 때문에 확장자를 미리 .ts 로 해주었다.)

// ./vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
})

 

3. TypeScript 추가 및 설정

TypeScript 는 자유분방한 JavaScript 문법에 ‘타입’이라는 규칙을 더해 예측 가능한 코드로 만들어주고 런타임 에러 발생 가능성을 줄여주게 된다.

리액트 프레임워크를 사용하고 있기 때문에 react 와 react-dom 에 대한 타입이 정의되어 있는 @types/react 와 @types/react-dom 패키지를 추가로 설치해주어야 한다. TypeScript 는 개발 단계에서 사용하는 패키지이므로 -D 옵션을 사용하여 설치해준다.

typescript, @types/react, @types/react-dom 설치 명령어

pnpm add -D typescript @types/react @types/react-dom
// package.json
{
  ...
  "devDependencies": {
    "@types/react": "^19.2.8",
    "@types/react-dom": "^19.2.3",
    "typescript": "^5.9.3",
  }
}

 

다음으로 TypeScript 컴파일러(tsc)와 IDE 가 참고할 설정 파일을 작성 해주는데, 총 3개의 설정파일을 작성해준다.

  • tsconfig.json : base가 될 설정 파일
  • tsconfig.app.json : 브라우저를 위한 설정 파일
  • tsconfig.node.json : node 환경을 위한 설정 파일

단일 레포지토리인 경우 tsconfig.json 파일 하나에 모든 설정을 넣기도 하지만, 혹시라도 각 환경에 대한 설정이 꼬이는 문제를 방지하기 위해 브라우저와 서버 환경을 위한 설정 파일을 분리해주는 것을 권장한다.

(추후 프로젝트가 커지거나, 모노레포 구조에 ts 설정을 해주어야 하는 상황을 대비해 연습 해두기에도 좋다.)

 

기본 base 가 되어줄 tsconfig.json 파일은 아래 첨부된 포스팅에 나온 Base Options 를 그대로 사용하였는데 불필요한 설정 없이, tsc 는 타입체크만 집중하고 컴파일은 Vite가 담당할 수 있도록 처리하기에 적합하다고 생각했기 때문이다.

tsconfig 설정 파일 작성시 참고하기 좋은 포스팅 > https://www.totaltypescript.com/tsconfig-cheat-sheet

// ./tsconfig.json
{
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ],
  "compilerOptions": {
    "target": "es2022",
    "moduleDetection": "force",
    "module": "preserve",
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true,
    "allowJs": true,
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noEmit": true,
    "skipLibCheck": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}
// ./tsconfig.app.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "lib": ["es2022", "dom", "dom.iterable"],
    "jsx": "react-jsx",
    "types": ["vite/client"]
  },
  "include": ["src"]
}
// ./tsconfig.node.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "lib": ["es2022"],
    "moduleResolution": "bundler",
    "types": ["node"]
  },
  "include": ["vite.config.ts"]
}

 

사용된 옵션 설명
  •  references
    • 참조할 하위 프로젝트의 tsconfig 파일 경로를 명시
    • typescript 는 하나의 설정파일이 관리하는 코드 범위를 하나의 프로젝트로 간주하기 때문에 tsconfig.app.json 과 tsconfig.node.json 를 각각 추가
  • target
    • 어떤 버전의 JavaScript 코드로 컴파일 할 건지. default = es5 es3, es5, es2015, es2016, es2017, es2018, esnext 가능
    • 구식 환경에 배포 된다면 낮은 버전을 지정, 신식 환경에만 배포된다면 높은 타겟 지정.
    • 타입스크립트 소스 코드 중 Promise 코드 있는 경우 es5 에서 지원해주지 않아 오류 발생 할 수 있음. 대부분의 브라우저에서 es6 지원하므로 es6 많이들 사용
    • ESNext 의 경우 타입스크립트 버전에 따라서 ESNext 의 버전이 달라질 수 있어 사용시 주의가 필요함
  • lib
    • 컴파일에 필요한 JavaScript 내장 라이브러리 지정 가능. Math API , document API 등
    • 지정하지 않는 경우 target 에 지정된 버전에 따라 자동으로 지정됨
  • moduleDetection
    • 타입스크립트는 기본적으로 모든 파일을 하나의 모듈로 취급하기 때문에 서로 다른 .ts 파일에서 동일한 변수명 사용시 오류 취급한다.
    • 이때 moduleDetection = force 옵션을 사용하면 각 .ts 파일을 독립 모듈로 취급하도록 만들 수 있다.
  • module & moduleResolution
    • 모듈 시스템을 결정하며, target & lib 관계처럼 module 값 지정시 moduleResolution 의 기본값이 지정됨
    • target & lib 은 결과물이 보여질 브라우저에 따라서 버전을 조절해야 한다면, module & moduleResilution 은 빌드 도구와 런타임에 따라서 정하면 됨
    • module 옵션의 경우 실제 브라우저와의 호환성은 Vite의 빌드 설정이 책임지기도 하고, Vite 에게 모듈 해석을 위임하면 빌드 속도도 향상됨
    • moduleResolution 옵션의 경우 번들러를 사용하여 빌드하는 경우, 번들러의 모듈 해석 방식과 TypeScript의 해석 방식이 충돌하지 않도록 도와주는 bundler 사용
  • resolveJsonModule
    • .json 파일(모듈)을 import 하여 사용할 수 있게 할지 결정함
    • ts 에서는 .ts, .tsx 파일만 모듈로 인식하기 때문에 json 파일을 import 해서 사용하려면 json 안의 프로퍼티들을 모두 타입 지정해줘야지만 사용이 가능. 이 옵션을 true로 해주면 json 파일에 있는 필드를 알아서 무슨 타입인지 인식하고 바로 사용 할 수 있도록 함
  • esModuleInterop
    • 기존 라이브러리 중에 amd(웹) 방식이나 CJS 방식을 기반으로 구현된 라이브러리가 많은데, 이를 컴파일 시점에 ESM 방식으로 가져와 사용할 수 있도록 해줌
  • isolatedModules
    • 각 .ts 파일이 독립적으로 변환되어도 런타임에 문제가 없도록 타입 엄격하게 검사할지 여부
    • Vite 의 esbuild 는 파일을 하나씩 변환하는데 이때 문제가 될 만한 문법들을 미리 검사해줌
      • 모듈 선언 없는 빈 파일 방지, type 키워드 누락 방지
  • verbatimModuleSyntax
    • type 을 import 하거나 export 할때 type 한정자를 명시하도록 설정하고, type 이 명시된 import/export 구문은 컴파일 시점에 제거됨
      • 번들 사이즈 감소 효과
      • 코드 가독성 및 명확성 증가
  • allowJs
    • TypeScript 는 기본적으로 JS 파일을 허용하지 않기 때문에 js 라이브러리를 사용해야 하거나, js에서 ts 로 점진적으로 변환하는 상황에서 true 로 사용
  • strict
    • ts 의 각종 타입 체킹 동작 모두 활성화. 기본적으로 ts 를 쓰겠다는 건 이걸 true 로 하고 쓰겠다는 의미.
    • 너무 엄격해서 싫은 경우 strict mode family 프로퍼티 사용하여 조절 가능
  • noUncheckedIndexedAccess
    • 배열이나 객체에서 인덱스를 통해 값을 사용하려 할때 해당 값이 존재하지 않을 수 있다고 가정하게 만들어 유효성 검사를 필수로 하도록 함. (typescript는 기본적으로 값이 반드시 존재한다고 가정)
  • noImplicitOverride
    • 클래스 상속 관계에서 기본적으로 자식 클래스에서 부모 클래스의 메서드를 재정의 할 때 실수로 메서드 이름을 다르게 사용한 경우에도 에러가 나지 않기 때문에 의도를 분명히 하기 위해 override 키워드를 필수로 붙이도록 함
  • noEmit
    • tsc(typescript compiler)가 JavaScript 파일, 소스맵, 선언 파일 등 컴파일러 출력물을 생성할 지 설정.
  • skipLibCheck
    • 쉽게 말해 내 소스가 아닌 다른 라이브러리의 타입 체킹을 스킵하는 설정. (node_modules 폴더 안에 .d.ts 파일들의 타입체킹 스킵)
    • 프로젝트 규모가 큰 경우 사용되는 라이브러리의 선언 파일들이 매우 많기 때문에 모두 매번 체크하기에 시간이 오래 걸림. 따라서 이 필드를 true 처리하여 타입 체크를 생략해버리고 컴파일 시간을 줄여줌
  • jsx
    • .tsx 확장자의 컴파일 결과 JSX 코드를 어떻게 컴파일 할 건지 결정 (아예 사용 안 하는 경우 jsx 변환 없이 타입 체크만 해주고, 사용하는 경우 주로 preserve , react-jsx 사용)
  • extends
    • 다른 tsconfig.json 파일의 설정들을 가져와 재사용할 수 있게 해줌
  • types
    • typescript 가 추가로 알아야할 타입들을 알려주는 부분.
      • 브라우저 환경에서 Vite 가 제공하는 기능들 사용하기 위해 vite/client 타입을 추가로 명시
      • 서버 환경에서 Node.js 가 제공하는 기능들 사용하기 위해 node 타입을 추가로 명시
  • include
    • 타입검사, 컴파일 할 파일 목록을 지정하는 속성

 

4. Tailwind CSS v4 설치

3버전에서는 Vite 가 빌드 될 때 tailwind css 문법을 css 파일로 변환하기 위해 PostCSS가 필요했지만, 4버전에서는 PostCSS 없이도 @tailwindcss/vite 플러그인이 직접 처리할 수 있게 되어 보다 간편하게 Tailwind CSS를 사용할 수 있게 되었다. 아래와 같이 설치해준다.

tailwindcss, @tailwindcss/vite 설치 명령어

pnpm add -D tailwindcss @tailwindcss/vite
// package.json 파일에 추가된다.
{
  ...
  "devDependencies": {
    "@tailwindcss/vite": "^4.1.18",
    "tailwindcss": "^4.1.18",
  }
}

vite의 설정 파일에 tailwindcss 플러그인을 추가하여 Vite가 빌드하는 과정에서 tailwind 엔진이 함께 구동될 수 있도록 한다.

// ./vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
    plugins: [react(), tailwindcss()],
})

메인 css 파일에 직접 tailwind 를 import 하여 tailwindcss 가 직접 스타일을 제어할 수 있도록 해준다.

// ./src/index.css
@import 'tailwindcss';

App.tsx 파일에서 index.css를 import 해주고, tailwind 문법을 사용해보면 잘 동작하는 것을 확일 할 수 있다.

import './index.css'

function App() {
    return (
        <div className="flex items-center justify-center w-40 h-10 bg-amber-200">
            <p className="text-pink-500">Vite + React</p>
        </div>
    )
}

export default App

화면을 확인해보기 위해 pnpm run dev 명령어 실행 또는 아래와 같이 package.json 의 scrips 수정 후 실행한다.

"scripts": {
    "dev": "vite --port 5173"
  },

화면을 확인해보면 적용한 tailwind css 속성이 정상적으로 반영되어 있는 것을 확인 할 수 있다.

 

다음 포스팅에서 Shadcn UI, Axios, Tanstack Query, MSW, ESLint, Prettier 설정에 대한 내용 확인 가능하다.

https://miroong.tistory.com/8

 

프론트 환경 설정(ESLint, Prettier, Axios, Tanstack Query, MSW, Shadcn UI)

이전 포스팅에서 PNPM, Vite, React, TypeScript, TailwindCss 를 설치 및 설정하였고, 이번 포스팅에서 이어서 진행해보겠다.https://miroong.tistory.com/7 프론트 환경 설정(PNPM, Vite, React, TypeScript, TailwindCss)프로젝

miroong.tistory.com