원티드 프리온보딩 인턴십

팀으로 일하는 법-git, eslint, prettier, husky

crab. 2023. 2. 21. 22:45
반응형

개발자로써 갖춰야 할 역량

  • 흔히 업무에 필요한 역량을 말할 때 업무를 수행하는데 필요한 지식과 기술을 의미하는 “하드 스킬”과
  • 업무 효율성을 극대화 하기 필요한 능력인 **“소프트 스킬"**로 구분지어서 말하곤 한다.
  • 기술적인 역량은 개발자의 핵심이 되는 역량이므로 “하드 스킬” 이라고 할 수 있다.
  • 개발 능력 외에 커뮤니케이션 능력, 소통 능력, 협업 능력, 팀워크를 강조하는 경우가 많습니다. 이러한 것들이 개발자로서 갖춰야 할 **“소프트 스킬”**이라고 할 수 있다.
  • 일반적으로 개발자는 구두로 하는 소통보다는 문서로 하는 비동기적 소통을 더 많이 하고 선호한다.
  • 문서라는 단어를 들었을때는 일반적으로 구글 시트, PDF, PPT, 노션 등의 툴을 떠올릴 수도 있다.
  • 하지만 개발자가 주로 작성하는 문서는 commit, PR, 그리고 코드이다.
  • 이러한 문서를 통해서 개발자들은 서로 의도를 표현하고, 피드백을 주고받고, 팀의 능률을 올리기 위해 노력한다.
  • 따라서 이러한 문서들의 중요성을 인식하고 이를 잘 작성하고자 노력하는 것은 굉장히 중요한 일이다.
  • 이번에는 이와 연관해서 Git과 GitHub을 문서의 관점에서 알아보고, 협업 능력, 효율적인 소통을 위해서 어떤 부분들을 시도할 수 있는지
  • 그리고 개발자는 어떻게 팀으로 일하는지에 대해 알아보겠다.

git, github

git의 정의

  • 깃은 분산 버전 관리 시스템이다.
  • 깃허브는 깃의 원격 저장소이다.
    • 깃의 기능들을 인터넷을 이용해서 여러 사람들에게 공유하고, 팀원들과 공동으로 작업할 수 있게 한다.

git commit message

  • 왜 이런식으로 짰지? 같은 것을 알 수 있다.
  • 개발자가 다른 개발자의 코드를 분석할 때 이 코드가 어떤 목적을 가지고 언제 작성되었는가를 확인하기 위해서 가장 먼저 확인하는 것은 Git의 Commit Message이다.
  • 커밋메시지가 제대로 작성되어 있지 않다면 히스토리를 파악하기 힘들다.
  • 팀 내에서 일관된 커밋메시지 규칙을 정하는 것은 필수적이다.
  • 커밋메시지에는 정석, 무조건 이런 방식은 없지만
  • 커밋메세지에 어떤 내용들이 포함되어야 할 지 생각해보자.
  • 팀 내에서 어떤 규칙을 사용할지 레퍼런스를 찾아보고 논의하는 과정을 거치면서 다듬어 나가자.

History 관리 및 브랜치 관리 전략

  • 멘토님은 여기서 squash를 통해서 여러 커밋들을 하나로 합치는 방법을 잠깐 얘기하셨다.
  • 하지만 이 방법은 squash 명령을 단독으로 수행할 수는 없기에 일반적으로 rebase 동작을 하면서 interative 모드를 이용해서 squash를 진행해준다.
  • 여기서 이 rebase는 잘못하면 다른 개발자의 코드를 건드릴 수가 있고 물론 장점도 있지만 주니어인 나에게는 단점의 리스크가 너무 크다고 생각된다.
  • 관련 링크만을 남기고 다른 방법을 써보고자 한다.

Git 스쿼시 커밋

  • 나의 경우 회사에서 배웠던 브랜치 전략을 따른다.
    • 모든 코드는 master 혹은 main, 그리고 test에 직접 push 하지 않는다.
    • 개발 전에 pull을 하고 시작한다.
    • issue를 먼저 생성한다.
      • feature, bug
    • 브렌치의 경우 issue와 연동지어서 짓는데
    • 관련 issue번호를 사용해서 이름을 짓는다.
    • wiki를 작성해서 관련내용들을 정리한다.

ESLint, Prettier

  • 하나의 프로젝트에서 작업자마다 각자 다른 코딩 스타일을 가지고 있고, 그것이 코드에 드러난다면 이 프로젝트를 제 3자가 읽기도 어려워지며, 팀원들끼리도 다른 팀원들이 작성한 코드를 읽고 이해하기가 힘들어진다.
  • 이런 문제를 해결하기위해 자바스크립트 진영에서는 Linter로 ESLint를, Code Formatter 로는 Prettier를 사용하는것이 일반적이다.
  • 둘이 겹치는 부분이 있으므로
  • 일반적으로 Lintting 기능은 eslint에 Code Formatting 기능은 prettier에 일임한다.
  • 이런 코딩 스타일은 자동화 툴을 사용할 수 있는데
  • 자동화 될 수 없는 컨벤션은 최소화 하는것이 좋고 필요한 경우에는 반드시 문서화 시켜서 논의할 때 문서를 기준으로 의견을 주고받고 수정이 필요한 경우에는 논의결과가 문서에 반영되어야 한다.

설치

  • eslint
    • npm install eslint --save-dev
    • 여기서 —save-dev의 경우 붙이면
    • package.json에서 devDependencies에 관련 라이브러리 이름이 들어가는데
      • 개발관련 라이브러리라는 뜻이다.
    • 물론 안 붙여도 구현하는데 문제는 없지만 코드는 읽는 사람의 입장에서 작성해야하고
    • 이런 부분들이 디테일이기 때문에 지켜야 한다.
    • 참고로 CRA의 경우 내장되어 있기 때문에 따로 설치하지 않아도 된다.
  • prettier
    • npm install prettier --save-dev
  • eslint-config-prettier
    • eslint는 linting 기능을, prettier는 formatting을 담당하는 구조가 이상적이다.
    • 하지만, eslint에는 일부 formatting 관련된 rule도 포함되어 있다.
    • 이 rule들이 prettier와 다른 설정을 가지고 있다면 설정 충돌이 발생한다.
    • 따라서, eslint에서 formatting 관련 rule들을 모두 해제해야할 필요가 있다.
    • 수동으로 진행할 수도 있지만, 이를 적용해주는 eslint plugin이 존재한다.
    • npm install eslint-config-prettier --save-dev
  • optional
    • package들을 설치하면 terminal에서 명령어를 통해서 eslint와 prettier를 실행할 수 있다.
    • 물론 이 부분을 전에 했던 분들은 이런 생각을 할 수 있다.
    • IDE차원에서 일반적으로 terminal명령어로 실행하는 것보다.
    • 파일을 저장할때 formatting을 적용하는게 어떤지 말이다.
    • 하지만 자동화를 하기 위해서는 명령어가 디폴트이다!!!
    • 그리고 프론트개발자라도 명령어에 익숙해져야한다.

설정

  • Prettier는 프로젝트의 루트 디렉토리에 .prettierrc.확장자 파일을 통해서 설정을 할 수 있다.
  • 설정파일의 확장자 형식은 다양하게 지원하고 있다(JSON, YAML, JS, TOML)
  • prettier 설정은 포맷팅에만 관련되어있어서 비교적 설정 룰들이 간단한 편
  • 예시
  • // .prettierrc.js module.exports = { printWidth: 100, // printWidth default 80 => 100 으로 변경 singleQuote: true, // "" => '' arrowParens: "avoid", // arrow function parameter가 하나일 경우 괄호 생략 };
  • 참고자료
  • Options · Prettier
  • prettier의 경우 설정 룰들이 비교적 간단하니 공식문서를 잘 찾아보면 좋다.

실습

prettier

npm init -y

npm install eslint prettier eslint-config-prettier --save-dev
  • 이렇게 하면 package.json에(devDependencies)
    • eslint
    • prettier
    • eslint-config-prettier
  • 이렇게 3개가 추가된다.
  • 여기서 index.js를 만들어주고
  • 기본 코드에 무의미한 공백라인을 가득 만들어주면 prettier가 작동해야한다.
  • 그러면 우선 prettierrc.js를 만들어주고
//prettierrc.js

module.exports = {
  printWidth: 100, // printWidth default 80 => 100 으로 변경
  singleQuote: true, // "" => ''
  arrowParens: "avoid", // arrow function parameter가 하나일 경우 괄호 생략
};
  • 이런건 터미널 명령어로 실행을 할 수가 있다.
  • 개발자는 자동화에 미친자가 되어야 한다.
  • 자동화의 전제조건은
    • 인터넷에서 찾아 뭔가 설정하거나 하면 안되고
    • 명령어로 실행시켜야 할 수 있어야한다.
  • npx prettier .
    • 하면 글자가 막 뜬다. → 이렇게 하면 적용된거는 아니다.
  • npx prettier --write .
    • 이렇게 하면 prettierrc.js 35ms하면서 글자와 시간이 뜬다.
  • 그리고 다시 리프레쉬하면 포메팅 된것을 알 수 있다.
  • 그런데 이 방법은 모든 파일을 다 확인하기 때문에 전에 포메팅 한것은 캐쉬로 남겨 포메팅하지 말아야 한다.
  • 이때는
  • npx prettier --write --cache .
    • 이렇게 하면 변한 것들만 포메팅한다.
    • 프리티어의 캐시파일은 node_modules안에 있다.
  • 근데 매번 이렇게 명령어를 치면 불편하기 때문에 package.json에 명령어를 등록해 둘 수 있다.
    • 여기서 echo는 리눅스에서 console.log처럼 글자를 출력해주는 명령어이다.
    • 이제 npm run echo 라고 하면 저 script가 그대로 돌아간다.
    • 그래서 이제 포매팅 하는것도 매번 귀찮으니 여기에 설정을 해준다.
    "script" : {
    	"echo": "echo \\"Hello, World\\" && exit 1",
    	"format": "prettier --write --cache ."
    },
    
    • 여기서는 npm이나 npx를 적지 않아도 괜찮다.
    • 이렇게 하면 npm run format 했을 때 터미널로 포매팅을 실행할 수 있다.
  • "script" : { "echo": "echo \\"Hello, World\\" && exit 1" },

eslint

  • prettier때와 마찬가지로 .eslintrc를 만들어준다.
    • 단, 여기서는 뒤에 .js를 붙이지 않는다.
    • 그러면 json으로 인식된다.
    • 이때 주석을 허용해준다.
// .eslintrc

{
  "extends": ["react-app", "eslint:recommended"],
  "rules": {
    "no-var": "error", // var 금지
    "no-multiple-empty-lines": "error", // 여러 줄 공백 금지
    "no-console": ["error", { "allow": ["warn", "error", "info"] }], // console.log() 금지
    "eqeqeq": "error", // 일치 연산자 사용 필수
    "dot-notation": "error", // 가능하다면 dot notation 사용
    "no-unused-vars": "error" // 사용하지 않는 변수 금지
  }
}
  • extends는 필요가 없다.
    • react가 아니기 때문이다.
  • 쉽게 볼 수 있는 것만 두어보자.
// .eslintrc

{
  "rules": {
    "no-var": "error", // var 금지
    "eqeqeq": "error", // 일치 연산자 사용 필수
  }
}
  • 이렇게 하면 var를 썼을 때 문제가 생긴다.
  • lint가 기본적으로 인식하는 것은 es5이기 때문에 const를 쓰면 경고가 뜬다.
  • 따라서 추가적으로 설정을 해주어야 한다.
// .eslintrc

{
	"env": {
		"es6":true
	},
  "rules": {
    "no-var": "error", // var 금지
    "eqeqeq": "error", // 일치 연산자 사용 필수
  }
}
  • 이제 prettier와 마찬가지로 터미널에 npx eslint . 를 해주면
  • 문제가 있다고 알려준다.
  • error Unexpected var, use let or const instead no-var
  • no-var라는 규칙에 위배된다고 알려준다.
  • 만약 이때 룰을 모르겠으면 에러 밑에 나오는 공식문서를 보면 좋다.
  • extend를 알아보자.
    • 먼저 .exlintrc.base.js라는 파일을 만들어주고
    // .exlintrc.base.js
    
    module.exports = {
    	rules: {
    		eqeqeq: 'error', // 일치 연산자 사용 필수
    	},
    };
    
    • 다시 .eslintrc에 새로 적어주면
    // .eslintrc
    
    {
    	"env": {
    		"es6":true
    	},
    	"extends": ["./.exlintrc.base.js"],
      "rules": {
        "no-var": "error", // var 금지
      }
    }
    
    • .exlintrc.base.js의 규칙이었던 eqeqeq도 적용 가능하다.
      • true == true이면 error가 남
    • 따라서 "extends": ["react-app", "eslint:recommended"], 의 경우 react-app의 미리 셋팅되어 있는 config들을 가져와 쓰는거라고 생각하면 된다.
  • plugins의 경우 "plugin" : ["react"], 이면 react의 문법검사기능을 사용할 수 있다.
  • npm init @eslint/config 라는 명령어를 치면 eslint 셋팅파일을 만드는 것을 도와준다.
  • eslint도 npx eslint --cache . 를 하면 캐시기능을 쓸 수 있다.
    • 이러면 .eslintcache가 생기는 데 이 파일은 gitignore에 추가해야 한다.
  • 이제 lint도
  • "script" : { "echo": "echo \\"Hello, World\\" && exit 1", "format": "prettier --write --cache .", "lint": "exlint --cache ." },

Husky

  • 팀원 전체가 자동으로 적용이 되고 특정 상황에서 강제로 되도록 자동화를 하자!
  • commit된 코드는 무조건 formatting이 완료되어야 하고, push된 코드는 무조건 eslint가 pass된 상태에서 push가 되도록 자동화를 구축해야 함

실행방안

  • git hook 도입
  • hook은 사이클안에서 중간에 끼어들어서 중간처리를 한다는 뜻
  • git hook은 중간에 무언가한다.
  • git hook? git에서 특정 이벤트 발생하기 전,후로 특정 hook 동작을 실행할 수 있게 하는것 (ex. commit, push)
  • git hook 설정은 까다롭고, 모든 팀원들이 사전에 repo를 클론받고 메뉴얼하게 사전 과정을 수행해야지만 hook이 실행됨을 보장할 수 있음
  • 실수로라도 사전 과정을 시행하지 않는다면 hook이 실행되지 않음
  • 해결법은? husky

husky

  • Modern native git hooks made easy
  • git hook 설정을 도와주는 npm package
  • 번거로운 git hook 설정이 편함 + npm install 과정에서 사전에 세팅해둔 git hook을 다 적용시킬 수 있어서 모든 팀원이 git hook 실행이 되도록 하기가 편함
  • husky를 통해서 pre-commit, pre-push hook을 설정 가능함
  • husky는 제로 디펜던시에 용량도 작아서 좋다.
  • npm install husky --save-dev
    • 프로그램 돌릴때 말고 개발할때만 필요하기 때문에 dev-dependencies 설치한다.
  • 그 다음 clone 받아서 사용하는 사람들이 npm install 이후 자동으로 특정 명령어를 실행하게 해야 하므로
  • npm의 hook인 "postinstall" 을 쓴다.
// package.json

{
  "scripts": {
    "postinstall": "husky install"
  },
}
  • 이렇게 하면 다음 사람들은 npm install만해도 그 이후 추가로 husky install을 하게 된다.
  • 이후
    • add pre-commit, pre-push hook
      1. npx husky add .husky/pre-commit "npm run format"
      2. npx husky add .husky/pre-push "npm run lint"

husky 실습

npm install husky --save-dev 

// 깃훅을 쓰는 것이므로 
git init -y

npx husky install
  • 이렇게 husky를 install하면 .husky 로 폴더가 생긴다.
    • 여기에 hook들이 셋팅된다.
  • 이후 터미널에 npx husky add .husky/pre-commit "npm run format" 를 하면
    • husky에 추가할것이다.
    • commit 하기 전에
    • npm run format 하는 것을
    • 이라는 뜻이다.
  • 이렇게 하면 package.json에 설정해놓은 명령어로 인해 자동으로 prettier가 돌게된다.
  • .husky폴더를 보면 pre-commit파일에 npm run format이 있다.
    • 밑에
    • echo “pre commit start”와
    • echo “format finish”를 써주면 좀 더 보기 편해진다.
  • 이렇게 설정하고 commit을 하면
    • pre commit start가 먼저 뜨고
    • 명령어 >> prettier --write --cache . 가 자동으로 입력된다.
  • 또한 push전에 eslint가 통과되어야 push를 하고 싶다이면
  • npx husky add .husky/pre-push "npm run lint" 를 해주면 된다.
  • 이 상태로 push를 했는데 코드에 lint에 걸리는 에러가 있다면
  • 먼저 push 전에 eslint 명령어가 돌기 때문에 걸러진다.
    • push가 안된다.
  • 고치고 push를 하면 잘 된다.

참고사항

  • git hook에서 eslint 에러가 발견하면 실행중인 script가 종료되기에 이 rule에 대해서 error로 설정할 지 warn으로 설정할 지 잘 고려해야함
    • 예시)
      • 아래와 같이 되어있으면 console.log 코드가 있어도 푸쉬가 되지만
        • "no-console": ["warn", { "allow": ["warn", "error", "info"] }]
      • error로 설정할 경우 console.log가 하나라도 있으면 푸쉬가 안됨
        • "no-console": ["error", { "allow": ["warn", "error", "info"] }]
    • 참고사항)
      • 린트에서 warning도 엄격하게 하나도 허용하지 않으려면
      • eslint --max-warings=0 으로 옵션을 붙여서 스크립트를 실행하면 됨
      // package.json
      
      {
        "scripts": {
      		"lint": "eslint --cache --max-warnings=0",
        },
      }
      

출처

원티드 프리온보딩 인턴십 프론트엔드 노션페이지

https://pollen-port-115.notion.site/9-45ebf1964918490ea2e2575cd330421e

반응형