웹 버저닝과 배포내역관리 (feat. standard-version)

웹 버저닝과 배포내역관리 (feat. standard-version)

목차
정리 이미지

셋팅은 여기 레포에서 확인 가능하다.

최근 버그와 관련된 CS가 인입이 되어, 픽스 후 배포했음에도 불구하고 유사한 CS가 인입이 되었을때 또 다시 버그 개선 티켓이 생성되곤 했다. 버그 픽스가 제대로 되지 못했을 수도있지만, 상황을 확인해보면 이슈를 CS단계에서 확인하지 못하고 바로 넘어오는 상황이 많았다. (커뮤니케이션으로 해결가능한 것들도) 이런 상황이 반복되고 누적되다보니 개발 집중력이 떨어지고, 불필요한 커뮤니케이션에 시간을 쏟고 있다는 생각이 들어, 개선해야겠다는 생각이 들었다.
유저, CS담당자, 개발자

문제 사항

CS단계에서 진행되지 못하고 넘어올수밖에 없었던 이유

  1. CS 대응 메뉴얼에 새로고침과 관련된 항목이 없었음.

    CSR의 경우 새로운 배포가 이루어졌을때, 새로고침을 하지 않을 경우 새로 배포한 JS파일을 바라보지 못하고, 이전 JS파일을 바라보고 있게 된다.

  2. 새로고침 이전에 사용자가 바라보는 버전이 신규 배포 버전의 JS파일인지 확인을 해야하지만 서비스에 버전을 명시하지 않아, CS 담당자가 확인할 수 없었다는 점.
  3. 버전명을 확인해도 해당 버전에 어떤 배포가 이루어졌었는지. 이전에 등록됐던 버그 픽스건이 배포가 되었었는지 확인할 수 있는 내역을 슬랙에서 검색해서 찾는 등 히스토리를 찾아야하는 상황.

    배포 notice를 확인할 수 있는 채널이 있지만, CS담당자가 이를 확인하지 못했거나, 잊을수도 있다.

사실 1번과 2번의 경우 SSR형태의 프로젝트나, 브라우저를 오래 유지하지 않고 사용하는 프로젝트라면 화면을 이동할때나 새로 들어갈때 최근에 배포한 파일을 load하기때문에 문제가 거의 발생하지 않는다. 하지만 어드민과 같은 프로젝트의 경우 브라우저를 끄지 않거나 컴퓨터를 아예 끄지 않는 경우 등, 오랫동안 새로고침하지 않고 유지되는 상황이 존재하기에 위 상황이 발생할 가능성이 있다.

해결 방향

생각나는 해결 방법은 아래와 같았다.

  • CS담당자가 사용자가 바라보고 있는 버전을 확인할 수 있게 한다.
  • CS담당자가 배포된 내역을 확인할 수 있게 한다.
  • 사용자는 새로 배포된 버전이 있을 경우 새로고침을 유도하는 팝업을 받는다.

문제사항의 해결방향으로 다시 바라보면

  • 문제사항 1번의 경우 메뉴얼에 해당항목 추가
  • 문제사항 2번의 경우 해결방향 3번으로 해결 가능
  • 문제사항 3번의 경우 해결방향 1번, 2번으로 해결 가능하다.

해결방법 3번이 가장 효과적인 방법이긴하나, 이번 포스팅에서는..
해결방법 1,2번의 경우에 해당되는 버전관리, 배포내역관리에대해 작성하고자 했다.ㅎㅎ

구현 방향

버전관리와 배포내역 관리는 배포시점에 진행해야하는데, 생각나는 순서는 아래와 같았다.

  1. 프러덕션 배포 전 버전을 업데이트
    1. 버전의 경우 배포하는 기능의 범위와 유형에 따라 major, minor, patch를 올릴지 결정
    2. package.json의 버전을 결정한 버전으로 변경
  2. 빌드 및 배포
  3. 배포가 성공하면 배포사항을 내역에 추가

버전을 업데이트하고, 배포사항을 내역에 추가하는 일련의 과정을 배포때마다 한다는 것은 여간 번거로운 일이 아니다. 직접 구현전에 자동화로 만들어 놓은 오픈소스를 찾아보고, 배포시점때마다 진행되어야해서 CI툴에 JOB으로 단계별로 생성하여 진행하기로 했다.

  1. 관련 라이브러리 찾아보기
  2. 배포 파이프라인에 추가하기

1. 라이브러리 서칭

찾기전에 버전과 배포내역이라는 개념을 정리해볼 필요가 있었다.
두 가지는 오픈소스 프로젝트에서 자주 볼 수 있었다.
이를 참고하여 리서칭해보니 2가지 개념이 나온다.

  1. 시맨틱 버저닝
  2. CHANGLOG

개념) 시멘틱 버저닝이란?

시맨틱 버저닝의 경우 이 링크에서 자세히 확인 가능하다. 소프트웨어의 버전 변경 규칙에 대한 제안이다. 간단히 말하자면 의존성 지옥을 해결하고자 배포시 버전번호를 명시하여 정의를 내림으로써 의존성관리를 용이하게 한다. SemVer의 형태는 아래와 같다.

1
MAJOR.MINOR.PATCH
출처: bytearcher

npm에서는 버전을 관리할 수 있는 cli를 제공한다.
이 명령어를 통해서 package.json의 버전명을 올릴 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
npm version 
[
<newversion>
| major
| minor
| patch
| premajor
| preminor
| prepatch
| prerelease [--preid=<prerelease-id>]
| from-git
]

개념) CHANGELOG란?

  • 체인지로그(CHANGLOG, 변경 기록)는 웹 사이트나 프로그램을 제작하는 것 같은 어떤 프로젝트를 진행할 때에 변경 사항에 대한 기록이다.
  • 많은 오픈소스 프로젝트에서는 체인지로그 파일을 가장 상위에 포함해서 배포한다.
    (위키)
CHANGELOG

릴리즈 노트와 CHANGLOG

CHANGLOG

  • CHANGLOG의 경우 조금 더 개발레벨의 변경사항을 작성한거에 가깝다고 생각한다.
  • 만약 지금과같은 문제사항이서 CS담당자에게는 CHANGLOG파일보다는 기능요약, 버그수정을 비개발자가 알 수 있는 언어로 정리된 릴리즈노트를 제공하는게 맞다고 생각한다.
  • 만약 릴리즈 노트를 작성하지 않는 팀이라면, 비개발용어로 commit 타입을 생성하여 개발자가 일반용어로 작성하여 CHANGLOG에 포함하는 것도 나쁘지 않다고 본다.
    1
    2
    3
    4
    5
    6
    7
    8
    // .versionrc
    {
    "types": [
    ...
    {"type":"release"}, // release용으로 생성
    ...
    ]
    }
Gatsby.js내의 릴리즈노트 페이지

release note

  • 릴리스 정보 는 제품 또는 서비스의 새 버전 릴리스에 대한 자세한 설명을 제공하기 위해 고객에게 제공되는 문서이다.
  • 이 문서는 일반적으로 PM 또는 PO가 생성하고 기능 요약, 버그 수정, 사용 사례 및 기타 자료를 포함한다.
  • 릴리스 정보는 사용자 문서 외부에서 변경된 사항에 대한 빠른 가이드로 사용된다.

library) standard-version

이 2가지를 관리할 수 있는 standard-version이라는 라이브러리가 존재한다.
standard-version 스크립트 하나로 여러가지 일을 실행해주는데 아래와 같다.

  1. 깃의 commit로그를 확인하여
    1. 새로운 버전을 생성하고 package.json의 버전 업데이트 (npm version 명령어 대체가능)
    2. 커밋을 기준으로 CHANGLOG파일 생성 및 갱신
  2. 해당 과정이 마무리되면 CHANGLOG파일과 package.json의 변경내역 커밋을 진행한다.
    • 자동 커밋메세지 : chore(release): 버전명
  3. 버전명을 Tag로 만들어서 추가한다.

생각 및 고민

  1. 장점) 버전 업데이트, 릴리즈 tag명시, CHANGLOG 갱신을 한번에 해결해준다.
  2. 고민) 기여자 모두가 커밋을 conventional commit 스펙에 맞추어 엄격하게 작성해야한다.
  3. 장점) 커밋 규칙을 지키며 개발하는 덕분에 커밋정리 및 규칙도 정리된다.
  4. 확장) 배포때마다 tag관리가 되어 롤백등의 상황에서도 태그기준으로 롤백이 편리하게 가능하다.

커밋에 의존적인 상황

하나 걱정되는 것은 기여자 모두가 conventional commit 스펙을 정확히 맞춰서 작성해야하는 부분이였는데
아래 라이브러리들로 해결이 가능했다.

  • 휴먼에러나 규칙을 자동으로 체킹하기 위해 lint와 같은 기능이 필요
  • 내가 개발한 코드가 어떤 목적인지 카테고라이징을 하는 기준이 각자 정의하기 애매하다면?
'commitizen/cz-cli' 셋팅 후 commit 진행시

규격) conventional commit

컨벤셔널 커밋은 페이지에서 이렇게 설명한다.

  • Conventional Commits 스펙은 커밋 메시지에 곁들여진 가벼운 컨벤션으로
    명확한 커밋 히스토리를 생성하기 위한 간단한 규칙을 제공합니다.
  • 이렇게 만들어진 커밋 히스토리를 이용하여 더 쉽게 자동화된 도구를 만들 수 있습니다.
    (commitlint, standard-version)
  • 이 컨벤션은 커밋 메세지에 신규 기능 추가, 문제 수정, 커다란 변화가 있음을 기술함으로써
    유의적 버전(Sementic Versioning)과 일맥상통한 면이 있습니다.

프로젝트에 셋팅하지 않아도 커밋 습관을 들이기 좋은 컨벤션이라고 생각이 들었다.

형태는 아래와 같다.

1
2
3
4
5
<타입>[적용 범위(선택 사항)]: <설명>

[본문(선택 사항)]

[꼬리말(선택 사항)]

즉, 위의 규격을 지키며 커밋을 진행해야한다.

(예시)

1
2
3
4
5
6
7
8
fix: correct minor typos in code

see the issue for details

on typos fixed.

Reviewed-by: Z
Refs #133

library) commitlint

commitlint를 사용해 commit시에 컨벤션을 잘 지켰는지 체크한다. 컨벤션은 어느정도 규격화되어있다.

  1. 컨벤션 셋팅
  2. commit hook에 셋팅

컨벤션 셋팅

  • standard-version에서 따르는 conventional-commit을 따르려면 @commitlint/config-conventional를 상속받아서 사용하면된다.
.commitlintrc.js파일. 기본 아이콘 이뿜
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module.exports = {
extends: ["@commitlint/config-conventional"],
rules: {
"type-enum": [
2,
"always",
[
"build",
"ci",
"chore",
"docs",
"feat",
"fix",
"perf",
"refactor",
"revert",
"style",
"test",
"release",
],
],
},
};

commit hook에 셋팅

husky를 사용하여 셋팅하였다.

1
2
3
4
5
6
// package.json
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
}
}

정리

정리 이미지
  • 버전관리, 배포내역관리를 자동화하기 위해 standard-version를 사용한다.
    • conventional-commit 규격에 엄격하므로,
      해당 컨벤션을 적용하기 힘든 상황이라면
      • npm version 명령어를 통해 버전을 관리하고,
      • 배포때마다 직접 CHANGLOG를 작성한다.
  • standard-version 이외에 필요한 라이브러리는
    • (필수) @commitlint/cli : 커밋 작성시 컨벤션용 린트
    • (옵션) commitizen/cz-cli : conventional commit의 규격을 하나씩 문항에 답하면서 커밋을 완성한다.

2. 배포 파이프라인에 추가하기

  • 문제사항 2번을 해결하기 위해 footer같은 곳에 버전명을 명시할 수 있다.
  • 이처럼 버전명이 서비스에 명시되기 때문에 프러덕션 배포시 빌드전 새로운 버전명 업데이트되어야하며 이에 맞춰 버전업과 CHANGLOG셋팅은 빌드 전에 진행한다.
  • jenkins를 쓴다면 파이프라인 프로젝트로 만들어서 사용하고, github action을 사용한다면 worflow에 셋팅하면된다.
  • 이번 포스팅에서는 github action으로 설명
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
build:
...
steps:
- uses: actions/checkout@v2 # 레포 바라보게 하기용
- uses: fregante/setup-git-user@v1 # 유저 셋팅용

- name: 패키지 설치
run: yarn

# 커밋타입에 release 타입을 추가하여
# 릴리즈 노트를 마지막 커밋에 대신 작성하게 하였다.
# 해당 스크립트는 lastCommit.sh 파일을 실행한다.
- name: 릴리즈 내역 커밋 확인
run: yarn check:lastCommit

# standard-version 진행
- name: version 업데이트 changelog 생성
run: yarn release

# 빌드 및 배포 start
- name: 빌드 시작
run: yarn build

- name: 배포
run: echo "배포2"
# 빌드 및 배포 end

- name: 변경내역 푸시
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
tags: true # 태그까지 생성되기때문에 같이 추가한다.

- name: 배포완료 사항 노티
...

- name: Job 상태 노티
...
github action 캡쳐

마치며

운영이슈에서 오는 피로감을 개선하고자 여러가지 방향을 고민해보았는데, 문제해결로 가다가 살짝 옆으로 샌감이 없지않아 있다.ㅎㅎ 무튼 덕분에 버전관리와 배포내역관리에 대한 라이브러리들 을 알 수 있었고 github액션도 사용해보아서 개인적으로 재밌었던 포스팅이었다.


참고자료

  1. SemVr
  2. wiki-CHANGELOG
  3. standard-version
  4. commitlint
  5. commitizen/cz-cli
  6. 규격화
📚