Skip to content

Convention

Yunkyu Jung edited this page Nov 21, 2022 · 19 revisions

🔒 Convention

💻 Code Convention

안지키다 적발 시 -1000원 👍

🏷️ Naming

  • 컴포넌트 파일은 PascalCase로 작성한다. Ex) Component.tsx
  • jsx가 포함된 컴포넌트 파일은 확장자를 .tsx로 이외는 .ts로 작성한다.
  • 변수명은 기본적으로 camelCase로 작성한다.
  • 상수는 UPPER_SNAKE_CASE로 작성한다.
  • 백엔드 파일명은 kebab-case로 작성하고 목적을 "."으로 구분하여 작성한다. Ex) user-article.contorller.js
  • 폴더명은 kebab-case로 작성한다.
  • 컴포넌트 폴더명은 PascalCase로 작성한다.
  • boolean형 함수 or 변수명은 is로 시작한다.
  • 배열 변수명은 List를 뒤에 붙인다. Ex) chatList
  • 변수는 선언 시 초기화한다.
  • 매직 넘버 금지(상수 사용)
  • 비동기는 async-await로 통일한다.

🔒Typescript

  • 꼭 필요한 상황이 아니면 type alias말고 interface로 작성한다.
  • interface naming은 PascalCase로 작성한다. Ex) interface HeaderProps{}

React

  • 컴포넌트 함수형으로 작성한다.
  • 컴포넌트는 바로 export default
function Component() {
  return <div></div>;
}

export default Component;

💅 Prettier

  • 프론트엔드
{
  "tabWidth": 2,
  "semi": true,
  "singleQuote": true,
  "jsxSingleQuote": true,
  "trailingComma": "all",
  "printWidth": 120,
  "arrowParens": "always",
  "endOfLine": "auto",
  "bracketSameLine": false,
  "importOrderParserPlugins": ["typescript", "jsx"],
  "importOrder": [
    "^next",
    "^[a-z_\\-]+",
    "<THIRD_PARTY_MODULES>",
    "^@components/(.*)$",
    "^@contexts/(.*)$",
    "^@hooks/(.*)$",
    "^@apis/(.*)$",
    "^@types/(.*)$",
    "^@styles/(.*)$",
    "^@utils/(.*)$",
    "^~"
  ],
  "importOrderSortSpecifiers": true
}
  • backend prettier
{
 "tabWidth": 2,
 "semi": true,
 "singleQuote": true,
 "trailingComma": "all",
 "printWidth": 120,
 "arrowParens": "always",
 "endOfLine": "auto",
 "bracketSameLine": false,
 "importOrderParserPlugins": ["typescript", "decorators-legacy"],
 "importOrder": [
   "^@",
   "^~",
   "^[a-z]",
   "^\\.\\.(?!/?$)",
   "^\\.\\./?$",
   "^\\./(?=.*/)(?!/?$)",
   "^\\.(?!/?$)",
   "^\\./?$"
 ],
 "importOrderSortSpecifiers": true
}

✨Eslint

  • Frontend lint
module.exports = {
  env: {
    browser: true,
    node: true,
    es2021: true,
  },
  parser: '@typescript-eslint/parser',
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:import/recommended',
    'plugin:import/typescript',
    'plugin:prettier/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:storybook/recommended',
    'eslint-config-prettier',
  ],
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    project: 'tsconfig.eslint.json',
    tsconfigRootDir: __dirname,
    ecmaFeatures: {
      jsx: true,
    },
  },
  plugins: ['react', '@typescript-eslint', 'react-hooks', 'import', 'prettier'],
  rules: {
    'no-unused-vars': 'off',
    'no-console': 'off',
    'import/prefer-default-export': 'off',
    'react/prop-types': 'off',
    'react/jsx-filename-extension': ['warn', { extensions: ['js', 'jsx', '.ts', '.tsx'] }],
    'react/jsx-props-no-spreading': ['warn', { custom: 'ignore' }],
    'react/react-in-jsx-scope': 'off',
    'react/jsx-uses-react': 'off',
    'react-hooks/exhaustive-deps': 'warn',
    '@typescript-eslint/no-unused-vars': 'error',
    '@typescript-eslint/no-empty-interface': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/no-var-requires': 'off',
    'import/no-unresolved': 'off',
  },
  settings: {
    react: {
      version: 'detect',
    },
    'import/resolver': {
      node: {
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
      },
    },
    'prettier/prettier': [
      'error',
      {
        endOfLine: 'auto',
      },
    ],
  },
  ignorePatterns: ['build', 'dist', 'public', 'node_modules/'],
};
  • Backend lint
module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: 'tsconfig.json',
    tsconfigRootDir: __dirname,
    sourceType: 'module',
  },
  plugins: ['prettier', '@typescript-eslint/eslint-plugin'],
  extends: ['prettier', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
  overrides: [
    {
      files: ['**/*.js', '**/*.ts', '**/*.tsx'],
    },
  ],
  root: true,
  env: {
    node: true,
    jest: true,
  },
  ignorePatterns: ['.eslintrc.js'],
  rules: {
    'prettier/prettier': 'error',
    '@typescript-eslint/interface-name-prefix': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
  },
};

📨 Commit Convention

  • 제목은 최대 50 글자까지만 입력
  • 제목 아래 본문 사이에 공백은 필수로 포함
  • 본문은 구체적으로 설명이 필요할 경우 아랫줄에 작성
  • 여러 줄의 메시지를 작성할 땐 "-"로 구분 (한 줄은 72자 이내)
- feat: 새로운 기능 추가
- fix: 버그를 고친 경우
- design: Css등 사용자 UI 디자인 변경
- !breaking change: 커다란 API 변경
- !hotfix: 급하게 치명적인 버그를 고쳐야하는 경우
- style: 코드 포맷 변경, 세미 콜론 누락, 코드 수정이 없는 경우
- refactor: 코드 리팩토링
- comment: 주석 추가 및 변경
- docs: 문서 수정
- test: 테스트 추가, 테스트 리팩토링
- chore: 빌드 테스트 업데이트, 패키지 매니저 설정, 이외의 자잘한것들
- rename: 파일 혹은 폴더명 수정
- remove: 파일을 삭제하는 경우만 수행한 경우

🚀 Devrank

🏠 Home

팀 소개

👨‍👩‍👧‍👦 팀원

팀 문화

🤝 그라운드 룰
⌨️ 컨벤션
🌳 브랜치 전략

개발 문서

🎨 피그마
📚 기획서
📜 Backlog
🛠️ 기술스택
📒 API 명세
📝 Dev log

데일리 스크럼

💬 데일리 스크럼

스프린트 계획 회의

🏃 Week2
🏃 Week3
🏃 Week4
🏃 Week5
🏃 Week6

멘토링

👨‍🏫 Week1
👨‍🏫 Week2
👨‍🏫 Week3
👨‍🏫 Week4
👨‍🏫 Week5

회고

✒️ Week1
✒️ Week2
✒️ Week3
✒️ Week4
✒️ Week5
✒️ Week6

Clone this wiki locally