[코드잇 스프린트] 고급 프로젝트 4 (commitlint)

이언덕·2025년 6월 23일
post-thumbnail

🔒 실무에서 안전한 커밋을 위한 자동화 — commitlint + husky 연동기

🤔 시작은 이랬다

우리 팀은 Jira를 이슈 관리 도구로 사용하고 있었다.
그래서 브랜치를 만들 때도 항상 [GN-42] 같은 티켓 번호를 포함한 네이밍을 썼다.


예를 들면 이런 식이다:

feature/GN-42-login-api

그런데 커밋할 때는 종종 이런 문제가 생겼다:

  • 커밋 메시지에 티켓 번호를 빼먹는 경우가 많았고
  • 나중에 Git 로그를 보면 이 커밋이 어떤 Jira 티켓에 해당하는지 알 수 없었다


    그래서 커밋할 때 브랜치명에서 티켓 번호를 자동으로 추출하고,
    커밋 메시지에 강제로 포함시키는 구조를 만들기로 했다.


🧰 핵심 도구 소개

commitlint

커밋 메시지가 특정 포맷에 맞게 작성되었는지 검사하는 도구



husky

Git hook을 설정해서, 커밋 전에 자동으로 스크립트를 실행하게 해주는 도구
이 둘을 함께 쓰면, 커밋할 때마다 메시지 포맷을 검사하고, 규칙 위반 시 커밋을 막을 수 있다.



⚙️ .husky/commit-msg 실제 코드

MSG_FILE=$1
//
# ───── 1) 브랜치에서 티켓 번호 추출 ─────
TICKET_ID=$(git symbolic-ref --short HEAD 2>/dev/null | grep -oE '[A-Z]+-[0-9]+')
//
# ───── 2) 커밋 메시지에 접두어 없으면 삽입 ─────
if [ -n "$TICKET_ID" ] && ! grep -q "\[$TICKET_ID\]" "$MSG_FILE"; then
  TMP=$(mktemp)
  {
    printf '[%s] %s\n' "$TICKET_ID" "$(head -n1 "$MSG_FILE")"
    tail -n +2 "$MSG_FILE"
  } > "$TMP"
  mv "$TMP" "$MSG_FILE"
fi
//
# ───── 3) commitlint 검사 ─────
npx --no -- commitlint --edit "$MSG_FILE" || {
  echo
  echo "❌  커밋 메시지 형식 오류!"
  echo "   예) [GN-42] feat(ui): 로그인 기능 추가"
  exit 1
}

✅ 무슨 역할을 하냐면:

  1. 현재 브랜치 이름에서 [GN-123] 같은 티켓 번호 추출
  2. 커밋 메시지에 이미 없으면 자동으로 앞에 붙여줌
  3. 마지막으로 commitlint로 검사해서 규칙 위반이면 커밋 실패!


🧾 commitlint.config.js 설정도 함께 필요하다

/** @type {import('@commitlint/types').UserConfig} */
module.exports = {
  extends: ["@commitlint/config-conventional"],
  /* ❶ 커스텀 헤더 패턴 등록 ----------------------------- */
  parserPreset: {
    parserOpts: {
      /* [GN-33] feat(ui): 로그인 추가 */
      headerPattern:
        /^\[(?<ticket>[A-Z]+-\d+)\]\s(?<type>feat|fix|chore|docs|style|refactor|test|perf|rename|remove)(?:\((?<scope>[a-z]+)\))?:\s(?<subject>.+)$/,
      /* 캡처 그룹 이름 → 규칙에서 참조 가능 */
      headerCorrespondence: ["ticket", "type", "scope", "subject"],
    },
  },
  rules: {
    /* type은 enum에 포함돼야 하고 비어 있으면 안 됨 */
    "type-enum": [
      2,
      "always",
      [
        "feat",
        "fix",
        "chore",
        "docs",
        "style",
        "refactor",
        "test",
        "perf",
        "rename",
        "remove",
      ],
    ],
    "type-empty": [2, "never"],
    /* subject 필수 */
    "subject-empty": [2, "never"],
    /* 헤더 길이 제한 */
    "header-max-length": [2, "always", 100],
    /* subject의 case 강제 비활성화 */
    "subject-case": [0, "never"],
  },
};

.



이 설정의 핵심:

  • [GN-42] feat(ui): 제목 형식을 강제
  • type, subject, ticket 누락을 막고
  • Jira 티켓과 연동되는 깔끔한 커밋 로그를 유지할 수 있다


✅ 실제로 써보니 어땠냐면...

  • 커밋 로그가 너무 깔끔해졌다
  • PR 리뷰할 때 "이거 어떤 이슈였지?" 라고 추적하는 게 훨씬 수월해짐
  • 다른 팀원이 실수로 메시지를 이상하게 써도 자동으로 막아줘서 안전


🧠 마무리 요약

  • Jira 기반 프로젝트에서 티켓 번호를 커밋 메시지에 넣는 건 협업 추적의 핵심
  • commitlint + husky + 브랜치명 파싱 스크립트로 자동화하면 실수도 줄고 로그도 깔끔해진다
  • 특히 이 구조는 "브랜치 이름 = 티켓 ID" 규칙을 쓰는 팀에게 매우 유용하다


    이건 "개발자들을 귀찮게 하는 장치"가 아니라,
    팀 전체의 개발 흐름을 더 똑똑하고 안정적으로 만드는 습관이다!
    🛠️ 커밋 메시지 자동 검사 도입기 — commitlint + husky 설치 & 연동 가이드

0개의 댓글