본문 바로가기

공부/프로젝트

KINS 프로젝트 초기 세팅

반응형

초기 세팅의 중요성 📖

프로젝트 초기 세팅은 개발의 방향을 결정짓는 중요한 작업입니다.

특히 협업 환경에서 코드 스타일과 퀄리티를 일관되게 유지하는 것이 필수적입니다.

이번 글에서 프로젝트 세팅에서 사용된 요 파일과 설정들을 하나씩 살펴보려고 합니다.

 

잘 몰라서 기록용으로 한 줄씩 해석해보려고 합니다!

ESLint 설정 📖

ESLint는 코드 방식을 일관성 있게 구현할 수 있도록 도와주는 도구입니다.

 

1. 모듈 가져오기

const { FlatCompat } = require('@eslint/eslintrc');
const tsParser = require('@typescript-eslint/parser');
const tsPlugin = require('@typescript-eslint/eslint-plugin');
const perfectionist = require('eslint-plugin-perfectionist');
const unusedImports = require('eslint-plugin-unused-imports');
const prettier = require('eslint-plugin-prettier');

 

`FlatCompat`: 최신 ESLint 설정 방식으로 이전 방식과 호환되도록 도와주는 도구입니다.

`@typescript-eslint/parser`: Typescript 코드를 ESLint가 이해할 수 있도록 분석하는 파서입니다.

`@typescript-eslint/eslint-plugin`: Typescript 코드에서 사용 가능한 ESLint 규칙 모음입니다.

`eslint-plugin-perfectionist`: import 정렬을 포함한 정리 작업을 지원합니다.

`eslint-plugin-unused-imports`: 사용하지 않는 import를 자동으로 제거합니다.

`eslint-plugin-prettier`: prettier와 ESLint를 함께 사용할 수 있도록 연결합니다.

 

 

2. FlatCompat 인스턴스 생성

const compat = new FlatCompat();

 

`FlatCompat`의 인스턴스를 생성 후 기존 `.eslintrc`형식의 설정을 현재 `eslint.config.js`형식으로 변환하는 데 사용됩니다.

 

 

3. ESLint 설정 배열

module.exports = [
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
      parser: tsParser,
      parserOptions: {
        ecmaFeatures: { jsx: true },
        project: './tsconfig.json',
      },
    },
    settings: {
      'import/resolver': {
        typescript: {
          alwaysTryTypes: true,
        },
      },
    },
    plugins: {
      '@typescript-eslint': tsPlugin,
      perfectionist,
      'unused-imports': unusedImports,
      prettier,
    },
    rules: {
      'no-alert': 'off',
      'camelcase': 'off',
      'no-console': 'off',
      '@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }],
      'perfectionist/sort-named-imports': ['warn', { order: 'asc', type: 'line-length' }],
      'unused-imports/no-unused-imports': 'warn',
    },
  },
  {
    files: ['postcss.config.js'],
    rules: {
      '@typescript-eslint/no-var-requires': 'off',
    },
  },
];

 

✅ 첫 번째 객체 (기본 설정)

 

`files`: 설정이 적용될 파일 패턴을 정의합니다. `**/*.{js,jsx,ts,tsx}`는 js, ts 파일을 모두 포함한다는 뜻.

`languageOptions`: 코드의 문법과 파서를 정의합니다.

  • ecmaVersion: 'latest': 최신 ECMAScript를 지원.
  • sourceType: 'module': ES 모듈을 사용.
  • parser: Typescript 코드를 분석하기 위해 사용.
  • parserOptions: JSX 지원 및 TypeScript 프로젝트 파일(tsconfig.json)을 지정.

`settings`: 플러그인 설정을 정의합니다.

  • import/resolver: Typescript를 사용해 import 경로를 확인하도록 설정.
  • alwaysTryTypes: true: Typescript의 @types 패키지를 자동으로 찾음.

`plugins`: 사용할 ESLint 플러그인을 정의합니다.

  • @typescript-eslint: Typescript 저용 규칙 제공.
  • perfectionist: 코드 정렬 규칙 제공.
  • unused-imports: 사용되지 않는 import를 감지.
  • prettier: Prettier 포맷팅 규칙 적용.

`rules`: 플러그인별 적용할 규칙을 정의합니다.

  • 'no-alert': 'off': alert 사용을 허용.
  • 'camelcase': 'off': camelCase 규칙을 강제하지 않음.
  • `no-console`: 'off': console.log 사용을 허용. 
  • @typescript-eslint/no-unused-vars: 사용되지 않는 변수를 경고하지만 함수 인수는 무시.
  • perfectionist/sort-named-imports: named import를 오름차순으로 정렬하며 줄 길이를 기준으로 정렬.
  • unused-imports/no-unused-imports: 사용되지 않는 import 경고.

✅ 두 번째 객체 (특정 파일 설정)

 

`files`: postcss.config.js 파일에만 적용되는 설정

`rules`: @typescript-eslint/no-var-requires: off: Typescript에서 require 사용을 허용.

 

전체 코드

// ✅ eslint.config.js

const { FlatCompat } = require('@eslint/eslintrc');
const tsParser = require('@typescript-eslint/parser');
const tsPlugin = require('@typescript-eslint/eslint-plugin');
const perfectionist = require('eslint-plugin-perfectionist');
const unusedImports = require('eslint-plugin-unused-imports');
const prettier = require('eslint-plugin-prettier');

const compat = new FlatCompat();

module.exports = [
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
      parser: tsParser,
      parserOptions: {
        ecmaFeatures: { jsx: true },
        project: './tsconfig.json',
      },
    },
    settings: {
      'import/resolver': {
        typescript: {
          alwaysTryTypes: true,
        },
      },
    },
    plugins: {
      '@typescript-eslint': tsPlugin,
      perfectionist,
      'unused-imports': unusedImports,
      prettier,
    },
    rules: {
      'no-alert': 'off',
      'camelcase': 'off',
      'no-console': 'off',
      '@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }],
      'perfectionist/sort-named-imports': ['warn', { order: 'asc', type: 'line-length' }],
      'unused-imports/no-unused-imports': 'warn',
    },
  },
  {
    files: ['postcss.config.js'],
    rules: {
      '@typescript-eslint/no-var-requires': 'off',
    },
  },
];

 

Prettier 설정 📖

Prettier는 일관적인 코드 스타일을 유지할 수 있게 도와주는 도구입니다.

ex) 들여쓰기, 따옴표, 줄 길이 등

 

1. 설정 파일

// ✅ .prettierrc

{
  "printWidth": 120,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true,
  "bracketSpacing": true,
  "trailingComma": "none",
  "plugins": ["prettier-plugin-tailwindcss"]
}

 

`printWidth`: 한 줄에 허용되는 최대 문자 수 설정.

`tabWidth`: 들여쓰기에 사용되는 공백 수 설정.

`useTabs`: 들여쓰기에 탭 대신 공백을 사용할지 설정.

`semi`: 코드 끝에 세미콜론을 추가할지 설정.

`singleQuote`: 문자열에 작은따옴표를 사용할지 설정.

`bracketSpacing`: 객체 리터럴에서 중괄호 사이에 공백을 넣을지 설정.

`trailingComma`: 객체나 배열 마지막 항목 뒤 쉼표를 넣을지 설정.

`plugins: ["prettier-plugin-tailwindcss"]`: TailwindCSS 전용 Prettier 플러그인 사용.

 

 

2. .prettierignore

 

Prettier가 코드 포맷팅을 실행할 때 불필요한 파일이나 디렉터리를 무시하도록 하기 위함.

build/*
dist/*
public/*
**/out/*
**/.next/*
**/node_modules/*

package-lock.json
yarn.lock
eslint.config.js

 

주요 목적

 

1. 불필요한 포맷팅 작업 방지

  • 자동 생성 파일이나 수정하지 않은 파일을 대상으로 포맷팅을 시도하는 시간 절약.

2. 포맷팅으로 인한 문제 방지

  • JSON 구조를 변경하거나 설정 파일에 예기치 않은 수정이 발생하는 것을 방지.

3. 성능 최적화

  • Prettier가 불필요한 파일을 처리하지 않으므로 포맷팅 속도를 개선.

 

.editorconfig 설정 📖

에디터 및 IDE의 코드 스타일을 통일하기 위한 설정 파일로, 모든 개발 환경에서 코드 포맷을 일관성 있게 유지하기 위해 사용합니다.

// ✅ .editorconfig

root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

 

`root = true`: .editorconfig 파일이 최상위 파일임을 선언.

`[*]`: 파일 확장자와 무관하게 모든 파일에 적용할 설정 정의.

`charset = utf-8`: 파일의 문자 인코딩을 UTF-8로 설정.

`end_of_line = lf`: 줄 끝을 LF방식으로 설정.

`indent_style = space`: 들여 쓰기 스타일을 스페이스로 지정.

`indent_size = 2`: 들여 쓰기에 사용할 스페이스 개수를 2개로 지정.

`trim_trailing_whitespace = true`: 각 줄 끝에 남아있는 불필요한 공백 제거.

`insert_final_newline = true`: 파일의 마지막에 빈 줄 하나를 자동을 추가.

 

❗`.editorconfig`는 기본 스타일을 통일하기 위한 설정이고, `.prettierrc`는 구체적인 코드 스타일을 정의할 때 사용합니다.

 

.nvmrc 설정 📖

Node.js 버전을 .nvmrc 파일에 명시하는 이유는 프로젝트에서 사용하는 Node.js 버전을 통일하기 위해서 사용합니다.

// ✅ .nvmrc

21.7.1

 

 주요 목적

 

1. 일관된 개발 환경 유지

  • 개발자마다 로컬에 설치된 Node.js 버전이 다를 수 있습니다.
  • .nvmrc에 특정 버전을 명시하면, 모든 개발자가 nvm을 사용해 동일한 Node.js 버전을 쉽게 설정할 수 있습니다.
  • nvm use 명령어로 .nvmrc 파일에 명시된 버전을 자동으로 적용합니다.

2. 의존성 문제 방지

  • Node.js 버전에 따라 의존성(Dependencies)의 동작이 달라질 수 있습니다.
  • 예를 들어, Node.js 최신 버전에서는 일부 패키지가 호환되지 않을 수 있습니다.

3. 빌드 및 배포 환경 통일

  • CI/CD 또는 배포 서버에서도 .nvmrc에 지정된 버전을 사용하면 로컬과 동일한 환경에서 빌드 및 배포가 가능합니다.
  • 이는 "로컬에서는 잘 되는데 서버에서는 안 된다"와 같은 문제를 방지합니다.

4. 미래 확장성과 관리

  • Node.js는 LTS(Long-Term Support)와 Current(최신) 릴리스로 나뉩니다.
    .nvmrc에 특정 버전을 명시하면 LTS 버전으로 관리하거나, 팀 규칙에 따라 버전을 주기적으로 업데이트하기 쉽게 됩니다.

 

GitHub Actions 설정 📖

GitHub Actions 워크플로우로, 자동화된 코드 검증으로 품질을 유지할 수 있습니다.

name: pull_request_check
on:
  pull_request:
    branches:
      - dev

 

`name: pull_request_check`: 워크플로우의 이름, GitHub Actions 대시보드에서 워크플로우를 식별하는 데 사용.

`on`:

  • pull_request: pr 이벤트가 발생했을 때 해당 워크플로우 실행.
  • branches: dev 브랜치에 대한 pr에만 워크플로우를 실행하도록 제한.

jobs:
  Deploy-Production:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [20.x]

 

`jobs`: 워크플로우에서 실행할 작업을 정의.

`Deploy-Production`:

  • runs-on: ubuntu-latest: 작업이 실행될 환경을 정의. 최신 버전의 Ubuntu에서 실행
  • matrix: 매트릭스 전략을 사용해 여러 Node.js 버전에서 작업을 실행할 수 있게 설정. 여기선  node.js 20.x 버전만 사용

steps:
  - uses: actions/checkout@v3

  - name: Use Node.js ${{ matrix.node-version }}
    uses: actions/setup-node@v3
    with:
      node-version: ${{ matrix.node-version }}

  - name: Install pnpm
    run: npm install -g pnpm

  - name: Get pnpm store directory
    id: pnpm-store
    run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

  - uses: actions/cache@v3
    id: pnpm-cache
    with:
      path: ${{ steps.pnpm-store.outputs.STORE_PATH }}
      key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
      restore-keys: |
        ${{ runner.os }}-pnpm-

  - name: Install the project dependencies
    run: pnpm install

  - name: Prettier check
    run: pnpm run prettier:check

  - name: Lint check
        run: pnpm lint

 

`steps`: 작업 내에서 실행할 단계를 정의.

`- uses: actions/checkout@v3`: GitHub Actions 공식 액션으로, 레포지토리 코드를 다운로드합니다.

`- name: Use Node.js ${{ matrix.node-version }}`: Node 환경을 설정합니다.

  • uses: actions/setup-node@v3를 사용해 Node.js를 설치.
  • with: node-version: ${{ matrix.node-version }}: 매트릭스에서 정의한 Node.js 20.x 버전을 설치.

`- name: Install pnpm`: pnpm 패키지 관리자를 전역 설치합니다.

  • run: npm instal -g pnpm 명령어를 실행해 글로벌 환경에 설치.

`- name: Get pnpm store directory`: pnpm store 디렉터리 경로를 가져옵니다.

  • id: pnpm-store: 이 단계의 ID를 pnpm-store로 지정해 이후 단계에서 참조할 수 있도록 설정.
  • run: pnpm store path 명령어를 실행해 pnpm 저장소 경로를 출력 후 결과를 GitHub Actions 환경 변수(GITHUB_OUTPUT)로 저장.

`- uses: actions/cache@v3`: 캐시 액션으로, pnpm 저장소를 캐싱해 종속성 설치 속도를 개선합니다.

  • id: pnpm-cache: 이 단계의 ID를 pnpm-cache로 설정.
  • with:
    • path: 캐싱할 경로로 pnpm store 경로를 지정.
    • key: 캐시 키를 생성. 파일 변경 여부를 판단하기 위해 pnpm-lock.yaml 파일의 해시값을 사용.
    • restore-keys: 캐시 키가 없을 경우 사용할 기본키.

`- name: Install the project dependencies`: pnpm install 명령어를 실행해 프로젝트 종속성 설치.

`- name: Prettier check`: Prettier를 사용해 코드 포맷팅 검사.

  • run: pnpm run prettier:check: 명령어를 실행

`- name: Lint check`: Lint 도구를 사용해 코드 스타일 및 규칙 검사.

  • run: pnpm lint 명령어를 실행.

 

✨ 요약

1. PR이 dev 브랜치로 생성되면 트리거
2. Ubuntu 환경에서 실행
3. Node.js 20.x와 pnpm 설치
4. pnpm store를 캐싱해 의존성 설치 속도 최적화
5. 프로젝트 의존성을 설치하고, Prettier와 Lint를 통해 코드 검사 수행

 

전체 코드

// ✅ .github/workflows/pull_request_check.yml

name: pull_request_check
on:
  pull_request:
    branches:
      - dev

jobs:
  Deploy-Production:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [20.x]

    steps:
      - uses: actions/checkout@v3

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install pnpm
        run: npm install -g pnpm

      - name: Get pnpm store directory
        id: pnpm-store
        run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

      - uses: actions/cache@v3
        id: pnpm-cache
        with:
          path: ${{ steps.pnpm-store.outputs.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-

      - name: Install the project dependencies
        run: pnpm install

      - name: Prettier check
        run: pnpm run prettier:check

      - name: Lint check
        run: pnpm lint

 

 

 

회고 🧐

이전 부트캠프 프로젝트까지만 하더라도 초기 세팅을 정말 가볍게 생각해 간단하게 설정하고 넘어간 경우가 대부분이었습니다.

근데 이번 프로젝트는 주니어, 시니어 개발자분들이 합류하면서 초기 세팅을 대신해주셨는데 초기 세팅이 중요한 걸 깨달았고 정말 아무것도 모르고 있었구나 라는 생각이 많이 들었습니다.

반응형