[GitHub] Commit Message Convention

이연우·2025년 7월 17일

TIL

목록 보기
8/100

🔥 커밋 메시지 컨벤션(Commit Message Convention)이란?

  • Git 커밋 메시지를 일관된 형식으로 작성하기 위한 규칙
  • 협업을 원활하게 하고, 변경 이력을 깔끔하게 관리할 수 있음

📝 커밋 메시지 컨벤션의 필요성

목적설명
가독성 향상변경 내용을 한눈에 파악할 수 있게 함
협업 효율성팀원 간 이해를 높이고 충돌 가능성 감소
자동화 도구 연동changelog 자동 생성, semantic versioning 연동 가능
버전 관리 일관성커밋 메시지로 변경 타입을 명확히 분류

🔧 커밋 메시지 구조 (예: Conventional Commits)

<type>(optional scope): <subject>
(blank line)
<body>
(blank line)
<footer>
feat(login): add OAuth login feature

사용자가 구글 계정으로 로그인할 수 있도록 OAuth2 인증을 추가했습니다.

BREAKING CHANGE: 기존 로그인 로직이 변경되었습니다. 프론트엔드도 수정이 필요합니다.

<type>(optional scope): <subject>

📚 커밋 메시지 <type> 종류

타입설명
feat새로운 기능 추가
fix버그 수정
docs문서 수정 (README 등)
style코드 포맷팅, 세미콜론 누락 등 (기능 변경 X)
refactor코드 리팩토링 (기능 변경 X)
test테스트 코드 추가/수정
chore빌드 시스템, 패키지 매니저 설정 변경 등
perf성능 개선
ciCI 설정 변경 (예: GitHub Actions)
build 빌드 관련 변경 (예: webpack 설정 수정)
revert이전 커밋 되돌리기

🔍 (optional scope)scope란?

  • 선택 사항으로, 변경된 부분의 범위(모듈, 기능)을 나타냄
  • ex) feat(auth), fix(cart)

📝 subject 작성 규칙

  • 명령문으로 작성
  • 첫 글자 소문자(Add, Fixadd, fix)
  • 마침표 사용하지 않음
  • 50자 이내 권장

<body>, <footer>

💡 bodyfooter(선택 사항)

  • body: 변경 이유나 이전 동작 대비 변화 설명
  • footer:
    • BREAKING CHANGE → 하위 호환 깨질 때
    • Closes #123 → 관련 이슈 자동 닫기

✅ 실제 예시 모음

  • 기능 추가 (feat)
feat(auth): 소셜 로그인 기능 추가

사용자는 구글 계정을 통해 로그인할 수 있습니다.
Firebase Authentication API를 사용했습니다.

closes #102
  • 버그 수정 (fix)
fix(ui): 버튼 클릭 시 페이지 이동 안 되는 오류 수정

이벤트 위임 방식 문제로 인해 클릭이 무시되었습니다.
이벤트 리스너 위치를 상위 컴포넌트로 이동했습니다.

관련 이슈: #88
  • 문서 작성 (docs)
docs(readme): 설치 및 실행 방법 추가

개발 환경 구성 방법, `.env` 설정 방법 등을 추가했습니다.
  • 코드 제거 (remove)
chore(legacy): 오래된 로그인 페이지 제거

`/legacy-login` 라우트 및 관련 스타일, API 제거
closes #120

📌 관련 도구

도구설명
Commitizen커밋 메시지를 CLI로 가이드해 주는 도구
standard-version커밋 메시지 기반 자동 릴리즈 도구
semantic-releaseSemantic Versioning을 자동화하는 툴

  • 실제 깃허브로 실습해 보기 → 간단한 사칙 연산 예제

1. 기본 구조 생성

  • 코드 작업
    • App.java 클래스 생성
    • 기본 메뉴 출력 구성
public class App {
    public static void main(String[] args) {
        System.out.println("계산기 앱 시작");
        // 메뉴 구성 예정
    }
}
  • 커밋 메시지
feat: create CalculatorApp main structure

2. 연산자 Enum 분리

  • 코드 작업
    • Operator.java enum 생성
    • 연산 기호 매핑
public enum Operator {
    ADD, SUB, MUL, DIV;

    public static Operator from(String symbol) {
        return switch (symbol) {
            case "+" -> ADD;
            case "-" -> SUB;
            case "*" -> MUL;
            case "/" -> DIV;
            default -> throw new IllegalArgumentException("지원하지 않는 연산자입니다.");
        };
    }
}
  • 커밋 메시지
feat(operator): define enum for basic operators

3. 계산 로직 분리

  • 코드 작업
    • Calculator.java 클래스 생성
    • calculate(int a, int b, Operator op) 메서드 구현
public class Calculator {
    public static int calculate(int a, int b, Operator op) {
        return switch (op) {
            case ADD -> a + b;
            case SUB -> a - b;
            case MUL -> a * b;
            case DIV -> a / b;
        };
    }
}
  • 커밋 메시지
feat(calculator): implement basic calculate method with switch expression

4. 예외 처리 추가

  • 코드 작업
    • InvalidOperatorException.java 생성
    • 0으로 나눌 경우 예외 발생
public class InvalidOperatorException extends Exception {
    public InvalidOperatorException(String message) {
        super(message);
    }
}
// Calculator.java 수정
case DIV -> {
    if (b == 0) throw new InvalidOperatorException("0으로 나눌 수 없습니다.");
    yield a / b;
}
  • 커밋 메시지
fix(calculator): handle division by zero with custom exception

5. 사용자 입력 처리

  • 코드 작업
    • Scanner 사용하여 입력받기
    • 결과 출력
public class App {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("첫 번째 숫자: ");
        int a = sc.nextInt();

        System.out.print("두 번째 숫자: ");
        int b = sc.nextInt();

        System.out.print("연산자 (+, -, *, /): ");
        String opSymbol = sc.next();

        try {
            Operator op = Operator.from(opSymbol);
            int result = Calculator.calculate(a, b, op);
            System.out.println("연산 결과: " + result);
        } catch (Exception e) {
            System.out.println("! 에러 발생: " + e.getMessage());
        }
    }
}
  • 커밋 메시지
feat(app): complete user input and output for calculator app

- 최종 커밋 로그


> 전체 코드

- Operator.java

public enum Operator {
    ADD, SUB, MUL, DIV;

    public static Operator from(String symbol) {
        return switch (symbol) {
            case "+" -> ADD;
            case "-" -> SUB;
            case "*" -> MUL;
            case "/" -> DIV;
            default -> throw new IllegalArgumentException("지원하지 않는 연산자입니다.");
        };
    }
}

- InvalidOperatorException.java

public class InvalidOperatorException extends Exception {
    public InvalidOperatorException(String message) {
        super(message);
    }
}

- Calculator.java

public class Calculator {
    public static int calculate(int a, int b, Operator op) throws InvalidOperatorException {
        return switch (op) {
            case ADD -> a + b;
            case SUB -> a - b;
            case MUL -> a * b;
            case DIV -> {
                if (b == 0) throw new InvalidOperatorException("0으로 나눌 수 없습니다.");
                yield a / b;
            }
        };
    }
}

- App.java

public class App {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("첫 번째 숫자: ");
        int a = sc.nextInt();

        System.out.print("두 번째 숫자: ");
        int b = sc.nextInt();

        System.out.print("연산자 (+, -, *, /): ");
        String opSymbol = sc.next();

        try {
            Operator op = Operator.from(opSymbol);
            int result = Calculator.calculate(a, b, op);
            System.out.println("연산 결과: " + result);
        } catch (Exception e) {
            System.out.println("! 에러 발생: " + e.getMessage());
        }
    }
}

0개의 댓글