프로젝트를 시작할 때 제일 먼저 잡고 싶었던 건 **“사람이 실수해도 시스템이 보정해주는 기본 장치”**였습니다.
- 커밋 메시지에 이슈 번호가 빠지지 않게 만들기
- 프론트는 코드 스타일/임포트 정렬까지 자동으로 맞추기
- 백엔드는 커밋 전에 포맷팅을 강제해서 리뷰 비용 줄이기
- (TODO) 푸시 전에 빌드까지 확인하면 더 탄탄해짐
아래는 떠글보글에서 적용한 프론트엔드/백엔드 초기 설정 정리입니다.
프론트엔드 설정
1) Husky로 커밋 메시지에 이슈 번호 자동 부착
브랜치명에 이슈 번호를 포함하는 규칙을 전제로 했습니다.
예: feature/add-login-123
커밋할 때마다 메시지 끝에 (#123)이 자동으로 붙도록 commit-msg 훅을 설정했습니다.
- 현재 브랜치명에서 숫자를 추출
- 커밋 메시지에 이미
(#번호)가 있으면 중복 추가하지 않음 - 없으면 메시지 끝에
(#번호)를 붙여 저장
#!/bin/sh. "$(dirname "$0")/_/husky.sh" COMMIT_MSG_FILE=$1BRANCH_NAME=$(git symbolic-ref --short HEAD)ISSUE_NUMBER=$(echo "$BRANCH_NAME" | grep -oE '[0-9]+' | head -n 1) if [ -n "$ISSUE_NUMBER" ]; then ORIGINAL_MSG=$(cat "$COMMIT_MSG_FILE") if ! echo "$ORIGINAL_MSG" | grep -q "(#$ISSUE_NUMBER)"; then echo "$ORIGINAL_MSG (#$ISSUE_NUMBER)" > "$COMMIT_MSG_FILE" echo "✅ Husky: 커밋 메시지 끝에 이슈 번호(#$ISSUE_NUMBER)를 추가했습니다." fifi이걸 해두면, “이 커밋이 어떤 작업(이슈)에서 나온 건지”를 커밋 단위로 추적하기가 쉬워져서 협업/회고/릴리즈 노트 작성이 훨씬 편해집니다.
2) ESLint(Flat Config) + Prettier + import 정렬(perfectionist)
프론트는 TypeScript + React 기반이라, lint를 “에러 잡기 + 스타일 통일”까지 같이 가져가도록 세팅했습니다.
포인트는 크게 3가지였습니다.
- TS 권장 규칙 기반 (
typescript-eslint) - React Hooks / React Refresh 규칙 포함
- import / named import 정렬을 강제해서 리뷰에서 불필요한 코멘트를 없애기
import js from "@eslint/js";import globals from "globals";import reactHooks from "eslint-plugin-react-hooks";import reactRefresh from "eslint-plugin-react-refresh";import tseslint from "typescript-eslint";import perfectionist from "eslint-plugin-perfectionist";import prettierConfig from "eslint-config-prettier"; export default [ { ignores: ["dist", ".path", "node_modules", "public"], }, js.configs.recommended, ...tseslint.configs.recommended, prettierConfig, { files: ["**/*.{ts,tsx}"], languageOptions: { ecmaVersion: 2020, globals: globals.browser, parser: tseslint.parser, parserOptions: { project: ["./tsconfig.app.json", "./tsconfig.node.json"], tsconfigRootDir: import.meta.dirname, }, }, plugins: { "react-hooks": reactHooks, "react-refresh": reactRefresh, perfectionist, }, rules: { ...reactHooks.configs.recommended.rules, "react-refresh/only-export-components": [ "warn", { allowConstantExport: true }, ], "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-explicit-any": "warn", "perfectionist/sort-imports": [ "error", { type: "natural", order: "asc", groups: [ "builtin", "external", "internal", ["parent", "sibling", "index"], ], internalPattern: ["^@/.*"], }, ], "perfectionist/sort-named-imports": [ "error", { type: "natural", order: "asc", }, ], }, },];이 설정으로 얻는 효과
- import 순서가 매번 동일해서 diff가 깔끔해짐
- Hooks 룰이 강제되니까 사이드이펙트/의존성 누락 같은 실수를 초기에 차단
any, 사용하지 않는 변수 같은 “미래의 버그 씨앗”을 경고로 계속 노출
3) 빌드로 한 번 더 검증 (npm run build)
github workflow로 배포를 자동화하고는 build에서 특히 더, build에서 실패할 일을 막아야하기 때문에 푸시/병합 전에 아래 명령으로 한 번 더 확인하도록 했습니다.
npm run build백엔드 설정
1) commit-msg 훅: 브랜치명 이슈 번호 자동 부착
백엔드도 동일하게 “브랜치명에서 숫자를 뽑아서 커밋 메시지에 붙이기”를 적용했습니다.
- 이미
(#숫자)가 있으면 그대로 둠 - 없으면
(#이슈번호)를 붙임
#!/bin/sh COMMIT_MSG_FILE=$1COMMIT_MSG=$(cat "$COMMIT_MSG_FILE") # 현재 브랜치명 가져오기BRANCH_NAME=$(git symbolic-ref --short HEAD) # 브랜치명에서 숫자 추출 (예: feature/123-add-login -> 123)ISSUE_NUMBER=$(echo "$BRANCH_NAME" | grep -o '[0-9]\+' | head -1) # 이미 (#숫자) 형식이 있는지 체크if echo "$COMMIT_MSG" | grep -qE '\(#[0-9]+\)'; then exit 0fi # 숫자가 있으면 커밋 메시지에 추가if [ -n "$ISSUE_NUMBER" ]; then echo "$COMMIT_MSG (#$ISSUE_NUMBER)" > "$COMMIT_MSG_FILE"fi exit 02) pre-commit 훅: Java 파일이 있으면 Spotless 적용 + 재스테이징
백엔드는 “포맷팅이 흔들리면 리뷰가 힘들어지는” 문제가 커서, 커밋 전에 Spotless를 자동으로 돌리도록 했습니다.
구성 포인트는 이거였습니다.
- 스테이징된 파일 중
.java가 없으면 포맷팅 스킵 - 있으면
spotlessApply실행 - 처음에 스테이징했던 Java 파일만 다시
git add해서 “원치 않는 파일이 커밋되는 사고”를 줄임
#!/bin/sh echo "🔍 Pre-commit hook 실행 중..." STAGED_JAVA_FILES=$(git diff --name-only --cached --diff-filter=ACMR | grep ".*\.java$") if [ -z "$STAGED_JAVA_FILES" ]; then echo "✨ 변경된 Java 파일이 없습니다. 포맷팅을 건너뜁니다." exit 0fi echo "📝 스테이징된 파일 포맷팅 중..." # 전체 프로젝트 포맷팅./gradlew spotlessApply --daemon --quiet # 원래 스테이징했던 파일들만 다시 스테이징for file in $STAGED_JAVA_FILES; do if [ -f "$file" ]; then git add "$file" fidone echo "✅ Pre-commit 체크 완료!"exit 0이렇게 해두면 “로컬 개발자마다 들쭉날쭉한 포맷” 때문에 PR에서 소모되는 시간을 크게 줄일 수 있습니다.
3) (TODO) 푸시 전에 빌드 검증까지 붙이면 더 완성형
백엔드는 아직 “푸시 전에 빌드 되는지 확인”을 훅으로 못 묶어둔 상태라, 다음 단계로는 아래 중 하나를 추천합니다.
./gradlew test(가장 안전)./gradlew build(테스트 포함)- 빠르게만 보려면
./gradlew compileJava(컴파일만)
예시로 pre-push 훅을 추가한다면 이런 형태가 됩니다.
#!/bin/shecho "🚀 pre-push: 백엔드 빌드/테스트 확인 중..."./gradlew test --daemonRESULT=$? if [ $RESULT -ne 0 ]; then echo "❌ 테스트 실패로 푸시를 중단합니다." exit 1fi echo "✅ 테스트 통과! 푸시 진행"exit 0마무리
초기 설정을 이렇게 잡아두니, 개발하면서 체감한 변화는 딱 두 가지였습니다.
- 작업 추적이 쉬워짐 (커밋 메시지에 이슈 번호가 자동으로 남음)
- 리뷰가 편해짐 (프론트는 import/스타일이 고정되고, 백엔드는 커밋 전에 포맷이 정리됨)