본문 바로가기

프로젝트/복지맵(일시중단)

[복지맵 프로젝트] 프로젝트 환경설정

반응형

개발 환경

구성하고자 하는 프로젝트 환경은 Husky + lint-staged 를 이용한 린트 및 프리티어, vitest 자동화를 목적으로 한다. 많은 개발 블로그에서 해당 설정에 대한 내용들을 다루고 있어서 몇 몇을 참고하여 본인의 입맛에 맡게 설정을 달리할 것이다.

 

패키지 설치

Vitest 패키지 설치

npm install --save-dev vitest

 

테스팅 라이브러리 외 관련 종속성 설치

 npm install -D @testing-library/jest-dom @testing-library/react @testing-library/user-event msw

 

Prettier와 eslint 설치

 npm install -D eslint eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y eslint-config-prettier eslint-plugin-prettier prettier

 

Husky 와 lint-staged 설치

npm install --save-dev husky lint-staged

 

 참고로 lint-staged 를 만든 개발자도 Husky 와 같이 사용하는 것을 권장하고 있다.

 

 

GitHub - lint-staged/lint-staged: 🚫💩 — Run linters on git staged files

🚫💩 — Run linters on git staged files. Contribute to lint-staged/lint-staged development by creating an account on GitHub.

github.com

 

 

환경설정

eslint 와 프리티어 등록 및 설정

우선, 앞서 패키지에서 설치한 eslint 관련 종속성들을 extends 와 plugins 배열에 각각 추가한다.

module.exports = {
  root: true,
  env: { browser: true, es2020: true },
  extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:react-hooks/recommended', 'plugin:jsx-a11y/recommended'],
  ignorePatterns: ['dist', '.eslintrc.cjs'],
  parser: '@typescript-eslint/parser',
  plugins: ['react', 'react-hooks', 'jsx-a11y', 'prettier'],
  rules: {
    'react-refresh/only-export-components': [
      'warn',
      { allowConstantExport: true },
    ],
  },
}

 

 

프리티어는 코드 포맷팅 라이브러리로 사용자가 지정한 옵션에 맞게 코드의 포맷팅을 정돈해주는 역할을 한다. 이를 설정해주려면 프로젝트의 루트 경로에 .prettierrc.js 파일을 생성 하여 다음과 같이 설정해준다. 참고로 자신의 프로젝트 환경에 맞게 필요한 옵션을 찾아보려면 프리피어 공식 사이트의 문서를 확인해보면 된다.

// root 경로 : .prettierrc.js

module.exports = {
    singleQuote: true, // 문자열은 무조건 작은 따옴표로 'string' (0) / "string" (x)
    semi: true, // 코드 끝에는 세미클론 붙이기
    useTabs: false, // 탭(tap) 사용금지 (들여쓰기는 무조건 스페이스바로 처리)
    tabWidth: 2,  // 들여쓰기 적용 스페이스바 공백 길이(스페이스바 두 번 입력 시 들여쓰기로 인정)
    trailingComma: 'all', // 객체나 배열로 구분된 마지막 요소 뒤에 콤마 붙일 것인지 설정(all 이면 전체 붙임)
  };

 

만일 프리티어 실행 시 특정 파일에 대해서는 제외하고자 한다면, .prettierignore 파일을 생성 후 다음 예시와 같이 추가해주면 된다.

// .prettierignore
dist
package.json
package-lock.json

 

.js 에 설정한 프리티어 옵션이 type 모듈 어쩌구 하면서 안 될수도 있는데, 이 때는 .js 를 json 으로 확장자를 변경하고, 다음 형식으로 바꿔주면 해결된다.

{
  "singleQuote": true,
  "semi": true,
  "useTabs": false,
  "tabWidth": 2,
  "trailingComma": "all"
}

 

프리티어 , 린트 설정 이후에 이를 실행하기 위해 스크립트를 등록한다.

    "scripts": {
      "lint": "eslint . --cache --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
      "format": "prettier --write .",
    }

 

스크립트에서 린트 옵션

--cache: ESLint의 캐시 기능을 사용하여 이전 검사 결과를 저장하고, 변경된 파일만 다시 검사
--ext ts,tsx: TypeScript 파일(.ts, .tsx)만 검사하도록 확장자를 지정
--report-unused-disable-directives: 사용되지 않는 ESLint의 eslint-disable 주석을 경고
--max-warnings 0: 경고를 허용하지 않고, 경고가 발생하면 오류로 처리

 

 

husky 초기화

우선 husky init 을 통해 초기 셋팅을 자동화한다.

npx husky init

 

그러면 자동으로 초기 셋팅 파일들이 추가된 것을 볼 수 있다. 찾아온 다수의 기술 블로그에서는 init 을 사용하지 않고 수동으로 커맨드를 사용해서 사용할 파일만 추가하던데, husky 를 개발한 개발자는 init 을 통해 사용하는 것을 권장하였으므로 이를 따라보기로 했다(많은 파일이 생성되더라도 불필요하면 직접 삭제하면 되므로 큰 문제 없다)

 

package.json 에도 스크립트가 추가되어 있다.

 

vitest 테스트 실행 스크립트 설정 추가

vitest 실행을 위해 test 스크립트를 추가한다.

"scripts": {
    "test": "vitest "
}

 

[Husky동작 테스트] 간단한 테스트 코드 작성 후 커밋 해보기

앞서 테스트와 Husty 가 정상적으로 동작하는지 체크하기 위해 간단한 테스트를 작성하고 커밋을 시도해본다.

// App.tsx
import './App.css'

function App() {
  return (
    <div>텍스트</div>
  )
}

export default App
// App.test.tsx
import {expect, it} from 'vitest'
import {render, screen} from '@testing-library/react'
import App from '../App'

it('App 컴포넌트 정상 렌더링',()=>{
    render(<App/>)
    const divElement = screen.getByText('텍스트')
    expect(divElement).toBeInTheDocument()
})

 

여기 까지 작성이 끝났으면  커밋을 시도해 본다.

git add .
git commit -m '과연 어떻게 동작할 것인가'

 

커밋을 시도하는 순간 test 스크립트가 자동으로 실행되면서 앞서 설정한 테스트 스크립트가 자동으로 실행된다.

PS C:\Users\Administrator\Desktop\개발관련\리액트 프로젝트\welfare-link> git commit -m 'fsdfsd'

> welfare-link@0.0.0 test
> vitest


 DEV  v1.5.0 C:/Users/Administrator/Desktop/개발관련/리액트 프로젝트/welfare-link

 ❯ src/__test__/App.test.tsx  (1 test | 1 failed) 29ms
   ❯ src/__test__/App.test.tsx > App 컴포넌트 정상 렌더링
     → Unable to find an element with the text: 텍스. This could be because the text is broken up by multiple elements. In this case, 
you can provide a function for your text matcher to make your matcher more flexible.

Ignored nodes: comments, script, style
<body>
  <div>
    <div>
      텍스트
    </div>
  </div>
</body>

⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯

 FAIL  src/__test__/App.test.tsx > App 컴포넌트 정상 렌더링
TestingLibraryElementError: Unable to find an element with the text: 텍스. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

Ignored nodes: comments, script, style
<body>
  <div>
    <div>
      텍스트
    </div>
  </div>
</body>
 ❯ Object.getElementError node_modules/@testing-library/dom/dist/config.js:37:19
 ❯ node_modules/@testing-library/dom/dist/query-helpers.js:76:38
 ❯ node_modules/@testing-library/dom/dist/query-helpers.js:52:17
 ❯ getByText node_modules/@testing-library/dom/dist/query-helpers.js:95:19
 ❯ src/__test__/App.test.tsx:10:31
      8|     render(<App/>)
      9| 
     10|     const divElement = screen.getByText('텍스')
       |                               ^
     11| 
     12|     expect(divElement).toBeInTheDocument()

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

 Test Files  1 failed (1)
      Tests  1 failed (1)
   Start at  13:18:11
   Duration  1.13s (transform 45ms, setup 150ms, collect 120ms, tests 29ms, environment 519ms, prepare 124ms)


 FAIL  Tests failed. Watching for file changes...
       press h to show help, press q to quit

 

커밋 결과는?

 git log --oneline 깃 커맨드를 통해서 커밋 내역을 확인하면, 커밋이 추가되지 않은 것을 볼 수 있다.

 

 

 

참고로 커밋 시 git hook 을 실행하지 않도록 하려면 -n 옵션을 붙여주면 된다.

git commit -m "..." -n # Skips Git hooks

 

Q. toBeInTheDocument 사용이 불가능 한데요??..

더보기

테스트를 실행하려고 하니까 toBeInDocument() 가 인식되지 않는 문제가 발생하였다. 이 부분은 현재 jest-dom 을 vite 프로젝트 내에서 전역적으로 인식하지 못해서 생기는 문제이므로 다음 챕터에서 언급한 과정을 따르면 해결할 수 있다.

 

 

 

ToBeInDocument 인식 불가 문제 해결하려면 

src 폴더 내에 setupTests.ts 파일 생성

src/setupTests.ts 파일을 생성하고 /jest-dom 패키지를 import 해온다.

import '@testing-library/jest-dom'

src 바깥의 루트 경로에 vitest.config.ts 파일 설정 추가

그 다음 src 폴더 바깥(node_modules 와 나란히 있는 경로)에 vitest.config.ts 파일을 생성하고, setUpFiles 에 앞서 생성했던 setupTests.ts 파일 경로를 지정한다.

import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react-swc'

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: ['./src/setupTests.ts'],
    coverage: {
      provider: 'v8'
    }
  }
})

 

이렇게만 설명해둔다면 문제 없이 테스트를 진행할 수 있다.

 

Husky 마저 설정하기

정상적으로 동작되는 것을 확인하였으니 프로젝트 환경에 맞게 커스텀 할 것이다.

 

현재는 기본 셋팅으로 commit 시 테스트만 실행하고 있는데, 여기에 lint 와 prettier 까지 함께 커밋 전에 실행되도록 할 것이다.

 

husky install 스크립트 추가하기

아래 명령어를 입력하면

npm pkg set scripts.postinstall="husky install"

 

postinstall 스크립트가 추가된다. husky install 은 npm install 시 husky 프로젝트 설정을 불러와서 초기화해주는 역할을 수행한다.

 

 

 

lint-staged 옵션을 Package.json 에 추가하기

아래 옵션을 package.json 의 속성들 사이에 나란히 포함시켜 준다. 이렇게 되면 pre-commit 파일에 적힌 명령어 lint-staged 가 실행될 때, 아래 옵션으로 지정해둔 스크립트가 순차적으로 실행된다. 이 중에서 하나라도 실패하면 커밋도 실패한다.

 

  "lint-staged": {
    "*.{js,css,ts,tsx,jsx}": [
      "npm run format",
      "npm run lint",
      "npm test"
    ]
  }

 

prettier 를 우선적으로 입력하여 실행해야, elint 와 충돌이 발생하지 않을 수 있다고 하니 참고하길 바란다.

 

.husky/pre-commit 파일에 npx lint-staged 입력하기

husky 를 초기화 했으면 아래 파일 목록들이 보일 것이다. 이 중에서 _ 경로에 들어 있는  pre-commit 파일이 아니라 .husky/ 경로에 있는 pre-commit 파일에 npx lint-staged 를 입력해야 한다.

./husky/pre-commit

 npx lint-staged

 

 

커밋 시도해보기

그 다음 커밋을 시도해보자. 

PS C:\Users\Administrator\Desktop\개발관련\리액트 프로젝트\welfare-link> git commit -m 'fsdfds'

[STARTED] Preparing lint-staged...
[COMPLETED] Preparing lint-staged...
[STARTED] Running tasks for staged files...
[STARTED] package.json — 9 files
[STARTED] src/**/*.{js,jsx,ts,tsx} — 3 files
[STARTED] npm format
[FAILED] npm format [FAILED]
[FAILED] npm format [FAILED]
[COMPLETED] Running tasks for staged files...
[STARTED] Applying modifications from tasks...
[SKIPPED] Skipped because of errors from tasks.
[STARTED] Reverting to original state because of errors...
[COMPLETED] Reverting to original state because of errors...
[STARTED] Cleaning up temporary files...
[COMPLETED] Cleaning up temporary files...

✖ npm format:
Unknown command: "format"

Did you mean this?
    npm run format # run the "format" package script

To see a list of supported npm commands, run:
  npm help
husky - pre-commit script failed (code 1)

 

 

그러면 package.json 에 설정한 lint-staged 에 입력한 스크립트 순서대로 실행이 되는 것을 볼 수 있다. 만일 순차적으로 스크립트가 실행될 때 우선 실행된 스크립트가 실패하면 이 후 스크립트는 실행되지 않고 커밋 요청이 취소되어 버린다.

 

 

따라서 실패한 이후에는 커밋 로그를 확인했을 때, 앞서 추가한 커밋 로그는 보이지 않는 것을 볼 수 있다.

 

 

 

[추가] Vite React 환경에서 절대경로 커스텀 하기

이번 포스트 마지막으로 vite.config.ts 와 tsconfig.json 파일을 수정하여 상대경로를 절대경로로 커스텀하는 설정을 추가할 것이다.

 

vite.config.ts 파일에서 경로 별칭 지정

해당 파일로 들어가면, defineConfig 이 보이는데, 그 내부에  resolve 속성을 추가 후 다시 alias 정의한다. 그리고 해당 값으로 대체될 경로(replacement)의 정보와 대체할 find 옵션을 지정하여, 이를 배열 형태로 필요한 만큼 요소를 추가하면 된다.

export default defineConfig({
  server: {
    port: 3000,
  },
  resolve: {
    alias: [
      { find :'@', replacement:"/src" }  ,
      { find: "@components", replacement: "/src/components" },
      { find: "@headers", replacement: "/src/components/headers" },
      { find: "@pages", replacement: "/src/pages" },
      { find: "@common", replacement: "/src/common" },
  ]
  },

 

 

다만 이렇게만 하는 경우 타입스크립트에서는 해당 절대경로를 인식하지 못해서 타입에러를 띄울 수 있다. 따라서 tsconfig.json 파일에 가서 아래와 같이 추가적인 구성을 통해 알려주어야 한다.

{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "@/*": ["*"],
      "@components/*": ["components/*"],
      "@pages/*": ["pages/*"],
      "@headers/*": ["components/headers/*"],
      "@common/*": ["common/*"]
    },
 	...
}

 

 

참고자료

Vite 기반 프로젝트 초기 셋팅 참고 블로그

 

Building a Modern React App with Vite, Vitest, TypeScript, ESLint, Prettier, and Husky

In the ever-evolving world of web development, staying up-to-date with the latest tools and technologies is essential. This tutorial will…

leandroaps.medium.com

 

Vitest 에서 toBeInTheDocument  찾을 수 없는 문제 이슈

 

Upgrading to v6.0.0 remove the `toBeInTheDocument` interface with vitest · Issue #515 · testing-library/jest-dom

@testing-library/jest-dom version: 6.0.0 node version: 18.16 npm (or yarn) version: 9.5.1 Relevant code or config: import '@testing-library/jest-dom/vitest'; import { vitest } from 'vitest'; await ...

github.com

 

허스키 깃 훅 적용

 

[개발자로 협업하기] husky 로 git hook 적용하기

이전 글에서 작성한 prettier 와 ESLint 설정을 세팅하고 팀별로 개발 정책을 아무리 열심히 논의해도 실수로 팀원 한명이라도 그것을 적용하지 않는다면? 또 다시 왜 팀 규칙을 지키지 않았는지에

velog.io

 

정복하기

 

Husky, lint-staged 정복하기.

강력한 협업 및 git hook 툴, husky, lint-staged 에 대해 알아보자!

velog.io

 

Chat GPT 

 

ChatGPT

A conversational AI system that listens, learns, and challenges

chat.openai.com

 

 

Dale Seo 기술 블로그

 

Prettier 상세 설정 가이드

Engineering Blog by Dale Seo

www.daleseo.com

 

상대경로를 절대경로로

 

 

[React] 절대 경로 커스텀하기(CRA, Vite)

프로젝트를 진행하다보면 import를 할 때 ../../../.....처럼 경로가 길어질 때가 있다. 상대 경로를 사용하기 때문인데, 다른 분들의 프로젝트를 보면 @components/..... 이런 식으로 매우 간단하게 작성

velog.io

 

 

다음 포스트(1) | 폴더구조 설정

 

[복지맵 프로젝트] 프론트엔드 환경설정 - 폴더 구조

이번에 시작하는 프로젝트의 폴더 구조를 어떻게 가져갈지 고민이 많았는데, 대중적으로 권장되고 있는 형식을 참고하여 뼈대를 구성하기로 하였다. 현재 사용하고 있는 기술 스택이 Vite + React

duklook.tistory.com

 

 

다음 포스트(2) | PWA 셋팅

 

[복지링크 프로젝트] 환경설정 - Vite 기반 리액트 웹 PWA 설정

PWA 설정 이유 모바일 환경에서도 웹을 앱과 유사한 환경에서 구동할 수 있다는 것은 많은 이점을 준다. 현재 내가 개발하고자 하는 웹 사이트는 모바일에서도 오프라인 환경에서도 많은 사용자

duklook.tistory.com

 

반응형