어서와, 개발은 처음이지?

배포 프로세스 구성하기1 - commit 전 코드 검증 자동화 본문

EC2_Ubuntu_Devops

배포 프로세스 구성하기1 - commit 전 코드 검증 자동화

오지고지리고알파고포켓몬고 2020. 6. 23. 03:26
반응형

최근에 시간적 여유가 생겨서 개발 외에 다른 사항에도 투자할 시간이 생겼습니다.

그에 따라 이번에는 node 프로젝트의 배포 프로세스를 구성하는 과정을 기록하고자합니다.


1. 개요


오픈소스가 등장하고, IT 업계의 생태계 규모, 성숙도, 접근성이 높아지면서 바야흐로 협업의 시대가 도래했습니다.

그에 따라 컨벤션, 테스트 코드 등의 개발 요소에 대한 중요성도 높아지게 됐는데, 

아직도 통상 '귀찮다' 라는 이유로 마음 한 구석의 불편함을 무시한 채 잠재적 기술 부채를 키워가는 사람들이 많고, 저 또한 그랬습니다.



하지만 고맙게도, 우리는 협업 단계에서 이런 중요한 요소들을 지킬 수 있는 환경을 형상관리 도구를 사용하여 쉽게 구축할 수 있습니다.


지금부터 git 환경에서 이런 사항들을 자동으로 검증할 수 있는 프로세스를 구성해보도록 하겠습니다.



2. git hooks


git을 사용하는 프로젝트는 commit, push 등 이벤트를 후킹(hooking)할 수 있는 스크립트를 제공하고 있습니다.

프로젝트 경로의 .git/hooks에서 이를 확인할 수 있습니다.

이는 쉘 스크립트로 작성되어 있으며, 파일명의 '.sample'을 제거하면 해당 이벤트 발생 시 스크립트가 실행됩니다.

각 hook은 클라이언트 훅과 서버 훅으로 구분할 수 있는데 우리는 commit 전에 코드 검증에 대한 부분을 작성할 것으로, 이에 해당하는 hook은 pre-commit 입니다.


각 hook에 대한 설명은 이곳을 둘러보시기 바랍니다.


물론 이 파일들을 직접 수정해서 사용하여도 상관없지만 .git/ 하위 파일들은 형상관리 범위에 포함되지 않기 때문에 로컬에서 hook을 정의하여도 다른 환경에서 공유할 수 없는 문제가 있습니다.


이를 해결하기위해 husky를 사용하겠습니다.



3. husky


husky는 이런 git hooks을 프로젝트 영역에서 쉽게 핸들링할 수 있도록 도와주는 라이브러리입니다.

husky를 설치하면 존재하는 git hooks 코드가 husky를 향하도록 자동으로 수정되어서 핸들링할 수 있는 원리입니다.


우선 프로젝트에 husky를 설치하겠습니다.

$ npm i -D husky


설치 후 .git/hooks를 살펴보면 다음과 같이 수정된 모습을 볼 수 있습니다.

자세한 내용은 들여다봐야 알겠지만 이러한 원리로 hooks를 핸들링 할 수 있습니다.


이번엔 package.json을 아래와 같이 수정해줍니다.

...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "husky": {
    "hooks": {
      "pre-commit": "echo hi"
    }
  },
...


이제 프로젝트를 commit하면 commit 전에 hi가 출력되는 모습을 볼 수 있습니다.



마찬가지로 다른 hooks들도 핸들링 할 수 있습니다. 또한 '.huskyrc' 파일을 생성하여 별도로 이를 정의할 수 있습니다.



4. 컨벤션 검증 프로세스 적용(eslint)


이제 pre-commit hook을 통해 lint 검사를 자동화 할 수 있도록 구성해보겠습니다.


우선 eslint를 설치합니다.

$ npm i -D eslint


다음으로 eslint init 명령어를 사용하여 간단하게 규칙을 세팅합니다.

(각자 환경에 맞는 옵션을 선택하거나, 직접 정의해서 사용하시면 됩니다.)

$ ./node_modules/.bin/eslint --init


다음으로 package.json을 다음과 같이 수정하여 pre-commit 단계에서 lint 검사를 수행하도록합니다.

...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "lint": "eslint './**/*.js'"
  },
  "husky": {
    "hooks": {
      "pre-commit": "npm run lint"
    }
  },
...


다음으로 javascript 파일을 생성하여 lint 규칙에 어긋나는 코드를 작성합니다.

// something.js
var a = 10;


위 코드는 a를 정의해두고 사용하지 않았기 때문에 lint 규칙에 어긋납니다.


이제 이 코드를 추가하고 commit을 발생시켜봅니다.

와우! 에러가 발생하면서 commit이 중지되었습니다.


위와 같은 원리로 prettier를 적용하여 코드를 자동수정하게 할수도 있습니다.

다만, 컨벤션을 의식하고 있느냐, 도구에 의지하느냐의 차이를 생각하면 수정사항은 수동으로 작업하는 것도 좋은 습관일 것 같습니다.




5. 테스트 검증 프로세스 적용(jest)


다음은 테스트 라이브러리인 jest를 사용하여 test coverage에 대한 검증을 할 수 있도록 하겠습니다.


우선 jest를 설치합니다.

$ npm i -D jest


다음으로 package.json을 아래와 같이 수정합니다.

...
  "scripts": {
    "test": "jest --coverage",
    "lint": "eslint './**/*.js'"
  },
  "jest": {
    "collectCoverageFrom": [
      "*.js"
    ],
    "coveragePathIgnorePatterns": [
      "/node_modules/"
    ],
    "coverageThreshold": {
      "global": {
        "statements": 100,
        "branches": 100,
        "functions": 100,
        "lines": 100
      }
    }
  },
  "husky": {
    "hooks": {
      "pre-commit": "npm run lint && npm run test"
    }
  },
...


coverageThreshold를 설정하여서, 100%를 넘지못하면 commit을 진행할 수 없도록 합니다.


이 스크립트 동작을 확인하기 위해 something.js 파일을 수정해보겠습니다.

// something.js
exports.sum = function (a, b) {
  return a + b;
};


다음으로 비어있는 something.test.js 파일을 생성합니다.

/* global test expect */
// something.test.js


이제 commit을 발생시켜봅니다.

threshold를 통과하지 못하자 commit이 중지되었습니다.


정확시 말하면 스크립트의 exit code가 0이 아닐때 commit이 중지됩니다.


이제 something.test.js를 수정하여 sum함수를 테스트하도록 수정합니다.

/* global test expect */

const { sum } = require("./something");

test("sum test", () => {
  expect(sum(10, 20)).toBe(30);
});


그리고 다시 commit을 실행하면 조건을 통과하여 정상적으로 진행되는 것을 볼 수 있습니다.


6. 마무리


지금까지 git의 pre-commit hook을 사용하여 코드 검증 자동화를 세팅하는 법에 대하여 알아봤습니다.


위 예제에서는 eslint나 jest에 대한 간단한 설정으로 작업했는데, 메커니즘은 동일하니 각자 환경에 맞게 응용하여 사용하시면 될 것 같습니다.


이 글에서 작성한, 그리고 앞으로 작성될 코드는 이곳에서 확인하실 수 있습니다.


다음 글에서는 pre-push를 사용하여 직접 push를 제한하는 방법에 대해 알아보겠습니다.







Comments