Skip to content

Split View: Vibe 코딩 팀 협업 완전 가이드: CI/CD 구축, 코드 품질, 충돌 없는 기여 전략

|

Vibe 코딩 팀 협업 완전 가이드: CI/CD 구축, 코드 품질, 충돌 없는 기여 전략

Vibe 코딩 팀 협업 완전 가이드: CI/CD 구축, 코드 품질, 충돌 없는 기여 전략

AI 기반 Vibe 코딩은 개인 생산성을 크게 향상시키지만, 팀 환경에서는 새로운 도전이 생깁니다. AI가 생성한 코드가 팀원의 코드와 충돌하거나, 일관성 없는 스타일이 섞이거나, CI/CD 파이프라인이 AI 생성 코드의 빠른 속도를 따라가지 못할 수 있습니다. 이 가이드에서는 Vibe 코딩 팀이 효율적으로 협업하기 위한 Git 전략, CI/CD 파이프라인, 코드 품질 관리, Skills 파일 활용법을 종합적으로 다룹니다.


1. Git 브랜칭 전략: Trunk-Based Development vs GitFlow

1.1 Vibe 코딩 팀에 GitFlow가 맞지 않는 이유

GitFlow는 release 브랜치, develop 브랜치, feature 브랜치, hotfix 브랜치 등 복잡한 브랜치 구조를 사용합니다. AI 보조 개발에서는 이 구조가 비효율적입니다.

GitFlow의 문제점 (Vibe 코딩 환경):

  • AI가 빠르게 코드를 생성할수록 feature 브랜치 수명이 길어져 머지 지옥 발생
  • develop → main 머지 시 충돌 해결에 AI 컨텍스트 소실
  • release 브랜치 관리 오버헤드가 높음

1.2 Trunk-Based Development (TBD)

TBD는 모든 개발자가 main 브랜치에 짧은 주기(최소 하루 한 번)로 커밋하는 전략입니다. Vibe 코딩 팀에 이상적입니다.

TBD 핵심 원칙:

  • 브랜치 수명: 최대 2일 (피처 플래그 사용 시 메인에 바로 머지)
  • 빈번한 통합: 하루 2~3회 main에 푸시
  • 완전한 자동화: 모든 머지에 CI 통과 필수
  • 작은 PR: 400줄 이하 권장

TBD 브랜치 전략:

main (항상 릴리즈 가능)
├── feature/us-123-recommendation-api (수명: 1-2)
├── feature/us-124-websocket-updates (수명: 1-2)
└── fix/recommendation-null-check (수명: 4시간)

피처 플래그로 미완성 코드 숨기기:

// src/config/feature-flags.ts
export const FEATURE_FLAGS = {
  RECOMMENDATION_V2: process.env.FEATURE_RECOMMENDATION_V2 === 'true',
  WEBSOCKET_REAL_TIME: process.env.FEATURE_WEBSOCKET === 'true',
} as const;

// 컴포넌트에서 사용
function HomePage() {
  return (
    <div>
      {FEATURE_FLAGS.RECOMMENDATION_V2 && <RecommendationSection />}
      <ProductList />
    </div>
  );
}

1.3 Vibe 코딩 팀을 위한 Git 규칙

# .git/config 또는 팀 공유 설정
[branch "main"]
  # main 브랜치에 직접 푸시 금지
  # GitHub Branch Protection Rules로 설정

# 권장 워크플로우
git checkout -b feature/us-123-recommendation-api
# Claude와 함께 개발 (여러 작은 커밋)
git commit -m "feat(recommendation): add purchase history query"
git commit -m "test(recommendation): add unit tests for recommendation service"
git commit -m "feat(recommendation): add recommendation API endpoint"
# PR 생성 → CI 통과 → 코드 리뷰 → 머지

2. Conventional Commits + 자동 Changelog

2.1 Conventional Commits 규격

Conventional Commits는 커밋 메시지에 구조적 의미를 부여하는 규격입니다. AI 보조 개발에서 특히 중요합니다.

형식:

type(scope): description

[optional body]

[optional footer(s)]

타입 목록:

타입의미버전 영향
feat새 기능Minor 버전 증가
fix버그 수정Patch 버전 증가
docs문서만 변경없음
style포맷팅, 세미콜론 등없음
refactor리팩토링없음
test테스트 추가/수정없음
chore빌드 설정, 패키지없음
perf성능 개선Patch 버전 증가
BREAKING CHANGE하위 호환성 파괴Major 버전 증가

예시:

feat(recommendation): add purchase history based product recommendations

- Implement collaborative filtering algorithm
- Add RecommendationService with top-10 product selection
- Exclude already purchased products from recommendations

Closes #123

2.2 자동 Changelog 생성

# conventional-changelog 설치
npm install --save-dev @commitlint/cli @commitlint/config-conventional
npm install --save-dev conventional-changelog-cli

# .commitlintrc.json
{
  "extends": ["@commitlint/config-conventional"]
}

# package.json scripts
{
  "scripts": {
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
    "release": "standard-version"
  }
}

자동 생성된 CHANGELOG 예시:

# Changelog

## [1.3.0] - 2026-03-17

### Features

- **recommendation:** add purchase history based product recommendations

### Bug Fixes

- **cart:** fix quantity update when adding duplicate items

### Performance

- **recommendation:** add Redis caching for recommendation results

3. PR 전략: 작은 PR, AI 보조 코드 리뷰, 브랜치 보호

3.1 작은 PR의 원칙

Vibe 코딩 환경에서 AI가 빠르게 코드를 생성하면 대형 PR을 만들고 싶은 유혹이 생깁니다. 이를 저항해야 합니다.

PR 크기 가이드라인:

  • 이상적: 200줄 이하
  • 최대: 400줄 (예외적)
  • 절대 안 됨: 1000줄 이상 PR

큰 PR을 쪼개는 방법:

  1. 수직 분리: 레이어별 분리 (DB 레이어 PR → 서비스 레이어 PR → API PR)
  2. 수평 분리: 피처 플래그 활용, 테스트와 구현 분리
  3. 리팩토링 + 기능 분리: 리팩토링은 별도 PR

3.2 AI 보조 코드 리뷰 자동화

GitHub Actions에서 Claude로 자동 리뷰:

# .github/workflows/ai-code-review.yml
name: AI Code Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  ai-review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Get PR diff
        id: diff
        run: |
          git diff origin/main...HEAD > pr_diff.txt
          echo "diff_size=$(wc -l < pr_diff.txt)" >> $GITHUB_OUTPUT

      - name: AI Review with Claude API
        if: steps.diff.outputs.diff_size < 1000
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Claude API 호출 스크립트
          node scripts/ai-review.js

3.3 브랜치 보호 규칙

GitHub Branch Protection Rules 설정:

# GitHub CLI로 설정
gh api repos/OWNER/REPO/branches/main/protection \
--method PUT \
--field required_status_checks='{"strict":true,"contexts":["ci/build","ci/test","ci/lint"]}' \
--field enforce_admins=true \
--field required_pull_request_reviews='{"required_approving_review_count":1,"dismiss_stale_reviews":true}' \
--field restrictions=null

필수 상태 체크:

  • ci/build: 빌드 성공
  • ci/test: 테스트 통과 (커버리지 80% 이상)
  • ci/lint: ESLint, Prettier 통과
  • ci/security: 보안 취약점 스캔

CODEOWNERS 설정:

# .github/CODEOWNERS
# 핵심 아키텍처 파일
/src/core/ @senior-dev @tech-lead
/src/domain/ @domain-expert

# 보안 관련
/src/auth/ @security-team
*.env* @security-team

# CI/CD 설정
/.github/ @devops-team
/docker/ @devops-team

4. GitHub Actions CI/CD 파이프라인

4.1 완전한 CI/CD 파이프라인 예시

# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '20'
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  # ─── CI 단계 ───────────────────────────────────────────

  lint:
    name: Lint & Format Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npm run lint
      - run: npm run format:check

  type-check:
    name: TypeScript Type Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npm run type-check

  test-unit:
    name: Unit Tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npm run test:unit -- --coverage
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          flags: unit

  test-integration:
    name: Integration Tests
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: testpassword
          POSTGRES_DB: testdb
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
      redis:
        image: redis:7
        ports:
          - 6379:6379
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npm run test:integration
        env:
          DATABASE_URL: postgresql://postgres:testpassword@localhost:5432/testdb
          REDIS_URL: redis://localhost:6379

  security-scan:
    name: Security Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          format: 'sarif'
          output: 'trivy-results.sarif'
      - name: Upload Trivy scan results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'
      - name: npm audit
        run: npm audit --audit-level=high

  mutation-test:
    name: Mutation Testing
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npx stryker run
      - name: Comment mutation score on PR
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const report = JSON.parse(fs.readFileSync('reports/mutation/mutation.json'));
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `Mutation Score: ${report.metrics.mutationScore.toFixed(1)}%`
            });

  # ─── CD 단계 (main 브랜치만) ─────────────────────────

  build-image:
    name: Build & Push Docker Image
    runs-on: ubuntu-latest
    needs: [lint, type-check, test-unit, test-integration, security-scan]
    if: github.ref == 'refs/heads/main'
    outputs:
      image-digest: ${{ steps.build.outputs.digest }}
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - name: Log in to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest

  deploy-staging:
    name: Deploy to Staging
    runs-on: ubuntu-latest
    needs: [build-image]
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Kubernetes Staging
        run: |
          kubectl set image deployment/app \
            app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build-image.outputs.image-digest }} \
            --namespace=staging
          kubectl rollout status deployment/app --namespace=staging

  deploy-production:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: [deploy-staging]
    environment:
      name: production
      url: https://myapp.com
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Production
        run: |
          kubectl set image deployment/app \
            app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build-image.outputs.image-digest }} \
            --namespace=production
          kubectl rollout status deployment/app --namespace=production

5. Skills 파일: 팀 공유 AI 워크플로우

5.1 Skills 파일이란?

Skills 파일(.claude/commands/ 디렉토리)은 팀이 공유하는 재사용 가능한 AI 워크플로우입니다. 슬래시 커맨드(/commit, /pr-description 등)로 실행합니다.

디렉토리 구조:

.claude/
  commands/
    commit.md
    pr-description.md
    test.md
    review.md
    docs.md
    refactor.md
    security-check.md
    changelog.md

5.2 주요 Skills 파일 예시

/commit — 커밋 메시지 자동 생성:

# commit

스테이징된 변경사항을 분석하여 Conventional Commits 규격의 커밋 메시지를 생성합니다.

## 규칙

- feat/fix/docs/style/refactor/test/chore/perf 타입 사용
- scope는 영향 받는 모듈/컴포넌트 (선택사항)
- 제목: 50자 이하, 현재형, 첫 글자 소문자
- 본문: 무엇을, 왜 변경했는지 설명
- BREAKING CHANGE 있으면 footer에 명시

## 출력 형식

type(scope): description

  • 변경 사항 1
  • 변경 사항 2

Closes #이슈번호 (해당 시)

/pr-description — PR 설명 자동 생성:

# pr-description

현재 브랜치의 변경사항을 분석하여 PR 설명을 생성합니다.

## 출력 형식

### 변경 사항 요약

[1-3줄 요약]

### 작업 내용

- [ ] 구현 항목 1
- [ ] 구현 항목 2

### 테스트 방법

1. 단계별 테스트 방법

### 스크린샷 (UI 변경 시)

[여기에 스크린샷 추가]

### 관련 이슈

Closes #이슈번호

### 체크리스트

- [ ] 단위 테스트 작성 완료
- [ ] 통합 테스트 통과
- [ ] CLAUDE.md 규칙 준수
- [ ] 문서 업데이트 (필요 시)

/test — 테스트 케이스 자동 생성:

# test

선택된 파일 또는 함수에 대한 포괄적인 테스트를 생성합니다.

## 포함 내용

1. 단위 테스트 (Jest/Vitest)
   - 정상 케이스
   - 엣지 케이스 (경계값, null, undefined)
   - 에러 케이스
2. 목(Mock) 설정
3. 속성 기반 테스트 (복잡한 비즈니스 로직)

## 규칙

- CLAUDE.md의 테스트 커버리지 목표 준수
- AAA 패턴 (Arrange/Act/Assert) 사용
- 테스트 설명은 한국어로 작성
- 비동기 테스트에 async/await 사용

/review — 코드 리뷰 수행:

# review

현재 변경사항 또는 지정된 파일에 대한 심층 코드 리뷰를 수행합니다.

## 리뷰 체크리스트

### 코드 품질

- [ ] SOLID 원칙 준수
- [ ] DRY 원칙 (중복 코드 없음)
- [ ] 함수/클래스 단일 책임
- [ ] 명명 규칙 (CLAUDE.md 기준)

### 보안

- [ ] SQL 인젝션 위험
- [ ] XSS 취약점
- [ ] 민감 정보 노출 (시크릿, PII)
- [ ] 인증/인가 검증

### 성능

- [ ] N+1 쿼리 문제
- [ ] 불필요한 재렌더링
- [ ] 메모리 누수 위험

### 테스트

- [ ] 테스트 커버리지 충분
- [ ] 엣지 케이스 커버

## 출력 형식

각 이슈: [Critical/Major/Minor] 설명 + 개선 코드 예시

/refactor — 리팩토링 제안:

# refactor

선택된 코드의 리팩토링 제안을 생성합니다.

## 분석 기준

1. Extract Method: 긴 함수를 의미 있는 함수로 분리
2. Extract Class: 단일 책임 원칙 위반 클래스 분리
3. Replace Conditional with Polymorphism: if/else 체인 제거
4. Introduce Parameter Object: 파라미터가 3개 이상인 함수
5. Remove Duplicate Code: 중복 로직 공통화

## 출력 형식

- 원본 코드 문제점 설명
- 리팩토링된 코드
- 변경 이유
- 추가 고려사항

/docs — 문서 자동 생성:

# docs

선택된 코드의 문서를 생성합니다.

## 생성 항목

1. JSDoc/TSDoc 주석
2. README.md (모듈 또는 함수 설명)
3. API 문서 (OpenAPI/Swagger 형식)

## 규칙

- 한국어로 작성 (영어 기술 용어는 그대로)
- 예시 코드 포함
- 파라미터 타입과 의미 설명
- 반환값 설명
- 예외 상황 문서화

6. 정적 분석: ESLint, Prettier, SonarQube

6.1 ESLint 설정

// eslint.config.js (ESLint v9 flat config)
import js from '@eslint/js'
import typescript from '@typescript-eslint/eslint-plugin'
import tsParser from '@typescript-eslint/parser'
import prettier from 'eslint-config-prettier'
import importPlugin from 'eslint-plugin-import'
import sonarjs from 'eslint-plugin-sonarjs'

export default [
  js.configs.recommended,
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        project: './tsconfig.json',
      },
    },
    plugins: {
      '@typescript-eslint': typescript,
      import: importPlugin,
      sonarjs: sonarjs,
    },
    rules: {
      // TypeScript 규칙
      '@typescript-eslint/no-explicit-any': 'error',
      '@typescript-eslint/strict-null-checks': 'error',
      '@typescript-eslint/no-unused-vars': 'error',
      '@typescript-eslint/explicit-function-return-type': 'warn',

      // 복잡도 제한
      complexity: ['error', 10],
      'max-lines-per-function': ['warn', 30],
      'max-depth': ['error', 3],

      // SonarJS 코드 품질
      'sonarjs/no-duplicate-string': 'warn',
      'sonarjs/cognitive-complexity': ['error', 15],
      'sonarjs/no-identical-functions': 'error',

      // import 정렬
      'import/order': [
        'error',
        {
          groups: ['builtin', 'external', 'internal', 'parent', 'sibling'],
          'newlines-between': 'always',
        },
      ],
    },
  },
  prettier,
]

6.2 Prettier 설정

{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "bracketSpacing": true,
  "arrowParens": "avoid",
  "endOfLine": "lf"
}

6.3 SonarQube 통합

# .github/workflows/sonarqube.yml
name: SonarQube Analysis

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  sonar:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run test:unit -- --coverage
      - name: SonarQube Scan
        uses: sonarsource/sonarqube-scan-action@master
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
        with:
          args: >
            -Dsonar.projectKey=my-project
            -Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
            -Dsonar.qualitygate.wait=true

sonar-project.properties:

sonar.projectKey=my-ecommerce-platform
sonar.sources=src
sonar.tests=src
sonar.test.inclusions=**/*.spec.ts,**/*.test.ts
sonar.coverage.exclusions=**/*.spec.ts,**/*.test.ts,**/index.ts

# Quality Gate 기준
sonar.qualitygate.conditions=\
  new_coverage<80,\
  new_duplicated_lines_density>3,\
  new_blocker_violations>0,\
  new_critical_violations>0

7. 충돌 방지 전략

7.1 피처 플래그로 충돌 최소화

피처 플래그는 미완성 코드를 메인 브랜치에 안전하게 머지할 수 있게 해주는 강력한 도구입니다.

// src/config/feature-flags.ts
import { z } from 'zod'

const featureFlagSchema = z.object({
  RECOMMENDATION_V2: z.boolean().default(false),
  WEBSOCKET_REAL_TIME: z.boolean().default(false),
  NEW_CHECKOUT_FLOW: z.boolean().default(false),
  AI_SEARCH: z.boolean().default(false),
})

function loadFeatureFlags() {
  return featureFlagSchema.parse({
    RECOMMENDATION_V2: process.env.FEATURE_RECOMMENDATION_V2 === 'true',
    WEBSOCKET_REAL_TIME: process.env.FEATURE_WEBSOCKET === 'true',
    NEW_CHECKOUT_FLOW: process.env.FEATURE_NEW_CHECKOUT === 'true',
    AI_SEARCH: process.env.FEATURE_AI_SEARCH === 'true',
  })
}

export const FEATURES = loadFeatureFlags()

7.2 모듈러 아키텍처로 충돌 최소화

팀원들이 서로 다른 모듈을 담당하도록 명확히 경계를 나누면 머지 충돌을 크게 줄일 수 있습니다.

src/
  modules/
    user/          # 팀원 A 담당
      domain/
      application/
      infrastructure/
      presentation/
    product/       # 팀원 B 담당
    order/         # 팀원 C 담당
    recommendation/ # 팀원 D 담당
  shared/          # 공용 코드 (변경 최소화)
    utils/
    types/
    errors/

7.3 충돌 발생 시 AI 활용

머지 충돌이 발생했습니다.  변경사항을 분석하고 올바른 머지 방법을 제안해줘:

<<<<<<< HEAD (내 변경사항)
[코드 붙여넣기]
=======
[상대방 코드 붙여넣기]
>>>>>>> feature/recommendation

양쪽 변경의 의도를 파악하고 두 변경을 모두 보존하는 머지 결과를 생성해줘.

8. AI 기술 부채 관리

8.1 AI가 생성한 코드의 기술 부채 패턴

Vibe 코딩으로 빠르게 개발하면 기술 부채가 축적될 수 있습니다.

일반적인 AI 생성 코드의 기술 부채:

  • 과도한 추상화 (필요 없는 인터페이스/레이어)
  • 불필요한 의존성 추가
  • 테스트하기 어려운 결합도 높은 코드
  • 컨텍스트 없이 생성된 일관성 없는 에러 처리
  • 중복 로직 (AI가 다른 파일의 로직을 모르고 재생성)

8.2 기술 부채 정기 리뷰

# 기술 부채 리뷰 프롬프트 (Sprint 종료 시)

다음 코드베이스를 분석하고 기술 부채를 식별해줘:
[변경된 파일 목록]

분석 항목:

1. 중복 코드 (DRY 위반)
2. 과도한 복잡도 (순환 복잡도 10 이상)
3. 불필요한 추상화 레이어
4. 일관성 없는 에러 처리
5. 테스트 커버리지 낮은 영역

각 항목에 대해:

- 위치 (파일, 라인)
- 심각도 (Critical/Major/Minor)
- 리팩토링 예상 시간
- 권장 접근 방법

8.3 Tech Debt Sprint

# 기술 부채 관리를 위한 Sprint 할당량
# 매 Sprint의 20%는 기술 부채 해결에 할당

# GitHub Issues 레이블 전략
labels:
  - name: tech-debt
    color: '#e4e669'
    description: 기술 부채 이슈
  - name: ai-generated
    color: '#7c3aed'
    description: AI가 생성한 코드 리뷰 필요
  - name: needs-refactor
    color: '#f97316'
    description: 리팩토링 필요

퀴즈로 배우기

Q1: Trunk-Based Development(TBD)가 GitFlow보다 Vibe 코딩 팀에 유리한 이유는?

정답: TBD는 브랜치 수명이 짧아(최대 2일) AI 생성 코드가 빠르게 통합되고, 머지 충돌이 최소화되며, 지속적 통합이 가능합니다.

설명: GitFlow에서는 feature 브랜치가 수일수주간 유지되는데, AI가 빠르게 코드를 생성하면 브랜치 수명이 더 길어져 머지 충돌이 빈번해집니다. TBD는 하루 12회 main에 머지하므로, AI가 생성한 코드가 빠르게 통합되고 팀 전체가 최신 코드를 유지합니다. 피처 플래그를 사용하면 미완성 기능도 안전하게 머지할 수 있습니다.

Q2: Conventional Commits에서 BREAKING CHANGE는 어떻게 표현하며 버전에 어떤 영향을 주나요?

정답: 커밋 메시지 footer에 BREAKING CHANGE: 설명을 추가하거나 타입 뒤에 느낌표(!)를 붙입니다. Semantic Versioning에서 Major 버전이 증가합니다.

설명: 예시: feat!: remove legacy API endpoint 또는 footer에 BREAKING CHANGE: /api/v1/users 엔드포인트 제거됨, /api/v2/users 사용. Semantic Versioning(SemVer)에서 하위 호환성을 파괴하는 변경은 Major 버전(1.0.0 → 2.0.0)을 증가시킵니다. 자동 Changelog 도구(standard-version, release-please)가 이를 감지해 자동으로 버전을 업데이트합니다.

Q3: Skills 파일(/commit, /review 등)의 주요 장점 3가지는?

정답: 팀 전체의 AI 워크플로우 일관성 유지, 재사용 가능한 프롬프트로 반복 작업 자동화, 팀 규칙(코딩 컨벤션, 품질 기준)이 AI에게 자동으로 적용됩니다.

설명: Skills 파일이 없으면 팀원마다 다른 프롬프트를 사용해 AI 출력의 품질과 스타일이 일관되지 않습니다. Skills 파일을 버전 관리(Git)하면 팀 AI 워크플로우도 코드처럼 관리할 수 있습니다. 예를 들어 /commit 커맨드는 항상 Conventional Commits 형식으로 메시지를 생성하고, /review는 팀의 보안 체크리스트를 자동으로 적용합니다.

Q4: SonarQube Quality Gate에서 핵심 지표 4가지는?

정답: 새 코드 커버리지(80% 이상), 중복 코드 비율(3% 이하), Blocker 이슈(0개), Critical 이슈(0개)입니다.

설명: SonarQube Quality Gate는 PR 머지 전에 코드 품질 기준을 자동으로 검사합니다. 새 코드 커버리지는 추가된 코드의 테스트 비율입니다. 중복 코드는 DRY 원칙 위반을 감지합니다. Blocker/Critical 이슈는 보안 취약점이나 버그를 발견합니다. CI/CD 파이프라인에 SonarQube를 통합하면 코드 품질이 일정 기준 이하인 PR은 자동으로 머지가 차단됩니다.

Q5: 피처 플래그(Feature Flag)를 사용하는 주요 이유 3가지는?

정답: 미완성 코드를 안전하게 메인 브랜치에 통합(TBD 지원), 특정 사용자/환경에게만 점진적 배포, A/B 테스트 및 빠른 롤백 가능입니다.

설명: 피처 플래그 없이 TBD를 사용하면 미완성 기능이 프로덕션에 노출됩니다. 피처 플래그를 환경 변수로 관리하면 같은 코드베이스로 개발, 스테이징, 프로덕션에서 다른 기능 세트를 실행할 수 있습니다. Vibe 코딩 환경에서는 AI가 빠르게 기능을 추가하므로, 피처 플래그로 완성된 기능만 점진적으로 활성화하는 전략이 중요합니다.

Q6: AI가 생성한 코드에서 자주 발생하는 기술 부채 패턴 3가지는?

정답: 불필요한 추상화(과도한 인터페이스/레이어), 중복 로직(다른 파일 컨텍스트 모름), 일관성 없는 에러 처리입니다.

설명: AI는 컨텍스트 창 내의 정보만 알기 때문에, 이미 다른 파일에 존재하는 유틸리티 함수를 재생성하는 경우가 많습니다. 또한 각각의 AI 세션에서 다른 에러 처리 패턴을 사용해 코드 일관성이 낮아집니다. CLAUDE.md에 금지 패턴을 명시하고, 정기적인 기술 부채 리뷰 Sprint를 통해 AI 생성 코드의 품질을 관리해야 합니다.


정리

Vibe 코딩 팀 협업의 성공은 세 가지 핵심 축에 달려 있습니다:

1. Git 전략: Trunk-Based Development로 짧은 수명의 브랜치와 빈번한 통합을 유지합니다. 피처 플래그로 미완성 코드를 안전하게 관리하고, Conventional Commits로 자동화된 릴리즈를 구현합니다.

2. CI/CD 자동화: GitHub Actions로 lint, type-check, 단위/통합 테스트, 보안 스캔, 도커 빌드, 배포를 완전 자동화합니다. 모든 PR은 CI를 통과해야만 머지될 수 있습니다.

3. 코드 품질: ESLint + Prettier + SonarQube로 코드 품질 기준을 강제하고, Skills 파일로 팀의 AI 워크플로우를 표준화합니다. 정기적인 기술 부채 리뷰로 AI 생성 코드의 품질을 유지합니다.

이 세 축이 잘 구축된 팀은 AI의 속도를 팀 전체의 생산성으로 전환할 수 있습니다.

Vibe Coding Team Collaboration Guide: CI/CD, Code Quality & Conflict-Free Contribution

Vibe Coding Team Collaboration Guide: CI/CD, Code Quality & Conflict-Free Contribution

AI-powered Vibe Coding dramatically improves individual productivity, but introduces new challenges in team settings. AI-generated code may conflict with teammates' code, inconsistent styles can mix together, and CI/CD pipelines may struggle to keep pace with the speed of AI code generation. This guide comprehensively covers Git strategies, CI/CD pipelines, code quality management, and Skills file usage to help Vibe Coding teams collaborate efficiently.


1. Git Branching Strategy: Trunk-Based Development vs GitFlow

1.1 Why GitFlow Doesn't Fit Vibe Coding Teams

GitFlow uses a complex branch structure including release branches, develop branches, feature branches, and hotfix branches. This structure is inefficient in AI-assisted development.

GitFlow problems in Vibe Coding environments:

  • The faster AI generates code, the longer feature branches live, causing merge hell
  • Merge conflicts when integrating develop into main cause loss of AI context
  • High overhead managing release branches

1.2 Trunk-Based Development (TBD)

TBD is a strategy where all developers commit to the main branch in short cycles (at least once per day). It is ideal for Vibe Coding teams.

Core TBD principles:

  • Branch lifespan: 2 days maximum (use feature flags to merge directly to main)
  • Frequent integration: Push to main 2-3 times per day
  • Full automation: CI must pass for every merge
  • Small PRs: Under 400 lines recommended

TBD Branch Strategy:

main (always releasable)
├── feature/us-123-recommendation-api (lifespan: 1-2 days)
├── feature/us-124-websocket-updates (lifespan: 1-2 days)
└── fix/recommendation-null-check (lifespan: 4 hours)

Hiding unfinished code with feature flags:

// src/config/feature-flags.ts
export const FEATURE_FLAGS = {
  RECOMMENDATION_V2: process.env.FEATURE_RECOMMENDATION_V2 === 'true',
  WEBSOCKET_REAL_TIME: process.env.FEATURE_WEBSOCKET === 'true',
} as const;

// Usage in component
function HomePage() {
  return (
    <div>
      {FEATURE_FLAGS.RECOMMENDATION_V2 && <RecommendationSection />}
      <ProductList />
    </div>
  );
}

1.3 Git Rules for Vibe Coding Teams

# Recommended workflow
git checkout -b feature/us-123-recommendation-api
# Develop with Claude (multiple small commits)
git commit -m "feat(recommendation): add purchase history query"
git commit -m "test(recommendation): add unit tests for recommendation service"
git commit -m "feat(recommendation): add recommendation API endpoint"
# Create PR → CI passes → Code review → Merge

2. Conventional Commits + Automated Changelog

2.1 Conventional Commits Specification

Conventional Commits is a specification that gives structural meaning to commit messages. It is especially important in AI-assisted development.

Format:

type(scope): description

[optional body]

[optional footer(s)]

Type List:

TypeMeaningVersion Impact
featNew featureMinor version bump
fixBug fixPatch version bump
docsDocumentation onlyNone
styleFormatting, semicolonsNone
refactorRefactoringNone
testAdd/modify testsNone
choreBuild config, packagesNone
perfPerformance improvementPatch version bump
BREAKING CHANGEBreaks backward compatibilityMajor version bump

Example:

feat(recommendation): add purchase history based product recommendations

- Implement collaborative filtering algorithm
- Add RecommendationService with top-10 product selection
- Exclude already purchased products from recommendations

Closes #123

2.2 Automated Changelog Generation

# Install conventional-changelog
npm install --save-dev @commitlint/cli @commitlint/config-conventional
npm install --save-dev conventional-changelog-cli

# .commitlintrc.json
{
  "extends": ["@commitlint/config-conventional"]
}

# package.json scripts
{
  "scripts": {
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
    "release": "standard-version"
  }
}

Auto-generated CHANGELOG example:

# Changelog

## [1.3.0] - 2026-03-17

### Features

- **recommendation:** add purchase history based product recommendations

### Bug Fixes

- **cart:** fix quantity update when adding duplicate items

### Performance

- **recommendation:** add Redis caching for recommendation results

3. PR Strategy: Small PRs, AI-Assisted Code Review, Branch Protection

3.1 The Principle of Small PRs

In Vibe Coding environments, AI rapidly generates code and it is tempting to create large PRs. Resist this temptation.

PR Size Guidelines:

  • Ideal: under 200 lines
  • Maximum: 400 lines (exceptional)
  • Never: PRs over 1000 lines

How to split large PRs:

  1. Vertical split: Split by layer (DB layer PR → Service layer PR → API PR)
  2. Horizontal split: Use feature flags, separate tests from implementation
  3. Refactoring + feature split: Refactoring in a separate PR

3.2 Automated AI-Assisted Code Review

Automated review with Claude in GitHub Actions:

# .github/workflows/ai-code-review.yml
name: AI Code Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  ai-review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Get PR diff
        id: diff
        run: |
          git diff origin/main...HEAD > pr_diff.txt
          echo "diff_size=$(wc -l < pr_diff.txt)" >> $GITHUB_OUTPUT

      - name: AI Review with Claude API
        if: steps.diff.outputs.diff_size < 1000
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          node scripts/ai-review.js

3.3 Branch Protection Rules

GitHub Branch Protection Rules setup:

# Set via GitHub CLI
gh api repos/OWNER/REPO/branches/main/protection \
--method PUT \
--field required_status_checks='{"strict":true,"contexts":["ci/build","ci/test","ci/lint"]}' \
--field enforce_admins=true \
--field required_pull_request_reviews='{"required_approving_review_count":1,"dismiss_stale_reviews":true}' \
--field restrictions=null

Required status checks:

  • ci/build: Build succeeds
  • ci/test: Tests pass (80%+ coverage)
  • ci/lint: ESLint, Prettier pass
  • ci/security: Security vulnerability scan

CODEOWNERS setup:

# .github/CODEOWNERS
# Core architecture files
/src/core/ @senior-dev @tech-lead
/src/domain/ @domain-expert

# Security related
/src/auth/ @security-team
*.env* @security-team

# CI/CD config
/.github/ @devops-team
/docker/ @devops-team

4. GitHub Actions CI/CD Pipeline

4.1 Complete CI/CD Pipeline Example

# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '20'
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  # ─── CI Stage ────────────────────────────────────────

  lint:
    name: Lint & Format Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npm run lint
      - run: npm run format:check

  type-check:
    name: TypeScript Type Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npm run type-check

  test-unit:
    name: Unit Tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npm run test:unit -- --coverage
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          flags: unit

  test-integration:
    name: Integration Tests
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: testpassword
          POSTGRES_DB: testdb
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
      redis:
        image: redis:7
        ports:
          - 6379:6379
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npm run test:integration
        env:
          DATABASE_URL: postgresql://postgres:testpassword@localhost:5432/testdb
          REDIS_URL: redis://localhost:6379

  security-scan:
    name: Security Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          format: 'sarif'
          output: 'trivy-results.sarif'
      - name: Upload Trivy scan results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'
      - name: npm audit
        run: npm audit --audit-level=high

  mutation-test:
    name: Mutation Testing
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npx stryker run
      - name: Comment mutation score on PR
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const report = JSON.parse(fs.readFileSync('reports/mutation/mutation.json'));
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `Mutation Score: ${report.metrics.mutationScore.toFixed(1)}%`
            });

  # ─── CD Stage (main branch only) ──────────────────

  build-image:
    name: Build & Push Docker Image
    runs-on: ubuntu-latest
    needs: [lint, type-check, test-unit, test-integration, security-scan]
    if: github.ref == 'refs/heads/main'
    outputs:
      image-digest: ${{ steps.build.outputs.digest }}
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - name: Log in to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest

  deploy-staging:
    name: Deploy to Staging
    runs-on: ubuntu-latest
    needs: [build-image]
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Kubernetes Staging
        run: |
          kubectl set image deployment/app \
            app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build-image.outputs.image-digest }} \
            --namespace=staging
          kubectl rollout status deployment/app --namespace=staging

  deploy-production:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: [deploy-staging]
    environment:
      name: production
      url: https://myapp.com
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Production
        run: |
          kubectl set image deployment/app \
            app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build-image.outputs.image-digest }} \
            --namespace=production
          kubectl rollout status deployment/app --namespace=production

5. Skills Files: Shared Team AI Workflows

5.1 What Are Skills Files?

Skills files (in the .claude/commands/ directory) are reusable AI workflows shared by the team. They are executed with slash commands like /commit and /pr-description.

Directory structure:

.claude/
  commands/
    commit.md
    pr-description.md
    test.md
    review.md
    docs.md
    refactor.md
    security-check.md
    changelog.md

5.2 Key Skills File Examples

/commit — Automatic commit message generation:

# commit

Analyzes staged changes and generates a commit message following the Conventional Commits specification.

## Rules

- Use feat/fix/docs/style/refactor/test/chore/perf types
- scope is the affected module/component (optional)
- Subject: under 50 chars, present tense, lowercase first letter
- Body: explain what and why was changed
- Add BREAKING CHANGE in footer if applicable

## Output format

type(scope): description

  • Change 1
  • Change 2

Closes #issue-number (if applicable)

/pr-description — Automatic PR description generation:

# pr-description

Analyzes changes in the current branch and generates a PR description.

## Output format

### Summary of Changes

[1-3 line summary]

### Work Done

- [ ] Implementation item 1
- [ ] Implementation item 2

### How to Test

1. Step-by-step testing instructions

### Screenshots (if UI changes)

[Add screenshots here]

### Related Issues

Closes #issue-number

### Checklist

- [ ] Unit tests written
- [ ] Integration tests passing
- [ ] CLAUDE.md rules followed
- [ ] Documentation updated (if needed)

/test — Automatic test case generation:

# test

Generates comprehensive tests for the selected file or function.

## Includes

1. Unit tests (Jest/Vitest)
   - Happy path cases
   - Edge cases (boundary values, null, undefined)
   - Error cases
2. Mock setup
3. Property-based tests (for complex business logic)

## Rules

- Follow test coverage goals in CLAUDE.md
- Use AAA pattern (Arrange/Act/Assert)
- Use async/await for async tests

/review — Perform code review:

# review

Performs an in-depth code review on current changes or specified files.

## Review Checklist

### Code Quality

- [ ] SOLID principles compliance
- [ ] DRY principle (no duplicate code)
- [ ] Single responsibility for functions/classes
- [ ] Naming conventions (per CLAUDE.md)

### Security

- [ ] SQL injection risk
- [ ] XSS vulnerabilities
- [ ] Sensitive data exposure (secrets, PII)
- [ ] Authentication/authorization validation

### Performance

- [ ] N+1 query problems
- [ ] Unnecessary re-renders
- [ ] Memory leak risks

### Testing

- [ ] Sufficient test coverage
- [ ] Edge case coverage

## Output Format

For each issue: [Critical/Major/Minor] description + improved code example

/refactor — Refactoring suggestions:

# refactor

Generates refactoring suggestions for selected code.

## Analysis Criteria

1. Extract Method: Split long functions into meaningful functions
2. Extract Class: Separate classes violating Single Responsibility
3. Replace Conditional with Polymorphism: Remove if/else chains
4. Introduce Parameter Object: Functions with 3+ parameters
5. Remove Duplicate Code: Consolidate duplicated logic

## Output Format

- Explanation of problems in original code
- Refactored code
- Reason for change
- Additional considerations

/docs — Automatic documentation generation:

# docs

Generates documentation for selected code.

## Generated Items

1. JSDoc/TSDoc comments
2. README.md (module or function description)
3. API documentation (OpenAPI/Swagger format)

## Rules

- Include code examples
- Explain parameter types and meanings
- Describe return values
- Document exception cases

6. Static Analysis: ESLint, Prettier, SonarQube

6.1 ESLint Configuration

// eslint.config.js (ESLint v9 flat config)
import js from '@eslint/js'
import typescript from '@typescript-eslint/eslint-plugin'
import tsParser from '@typescript-eslint/parser'
import prettier from 'eslint-config-prettier'
import importPlugin from 'eslint-plugin-import'
import sonarjs from 'eslint-plugin-sonarjs'

export default [
  js.configs.recommended,
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        project: './tsconfig.json',
      },
    },
    plugins: {
      '@typescript-eslint': typescript,
      import: importPlugin,
      sonarjs: sonarjs,
    },
    rules: {
      // TypeScript rules
      '@typescript-eslint/no-explicit-any': 'error',
      '@typescript-eslint/strict-null-checks': 'error',
      '@typescript-eslint/no-unused-vars': 'error',
      '@typescript-eslint/explicit-function-return-type': 'warn',

      // Complexity limits
      complexity: ['error', 10],
      'max-lines-per-function': ['warn', 30],
      'max-depth': ['error', 3],

      // SonarJS code quality
      'sonarjs/no-duplicate-string': 'warn',
      'sonarjs/cognitive-complexity': ['error', 15],
      'sonarjs/no-identical-functions': 'error',

      // Import ordering
      'import/order': [
        'error',
        {
          groups: ['builtin', 'external', 'internal', 'parent', 'sibling'],
          'newlines-between': 'always',
        },
      ],
    },
  },
  prettier,
]

6.2 Prettier Configuration

{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "bracketSpacing": true,
  "arrowParens": "avoid",
  "endOfLine": "lf"
}

6.3 SonarQube Integration

# .github/workflows/sonarqube.yml
name: SonarQube Analysis

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  sonar:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run test:unit -- --coverage
      - name: SonarQube Scan
        uses: sonarsource/sonarqube-scan-action@master
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
        with:
          args: >
            -Dsonar.projectKey=my-project
            -Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
            -Dsonar.qualitygate.wait=true

sonar-project.properties:

sonar.projectKey=my-ecommerce-platform
sonar.sources=src
sonar.tests=src
sonar.test.inclusions=**/*.spec.ts,**/*.test.ts
sonar.coverage.exclusions=**/*.spec.ts,**/*.test.ts,**/index.ts

7. Conflict Prevention Strategies

7.1 Minimizing Conflicts with Feature Flags

Feature flags are a powerful tool for safely merging unfinished code into the main branch.

// src/config/feature-flags.ts
import { z } from 'zod'

const featureFlagSchema = z.object({
  RECOMMENDATION_V2: z.boolean().default(false),
  WEBSOCKET_REAL_TIME: z.boolean().default(false),
  NEW_CHECKOUT_FLOW: z.boolean().default(false),
  AI_SEARCH: z.boolean().default(false),
})

function loadFeatureFlags() {
  return featureFlagSchema.parse({
    RECOMMENDATION_V2: process.env.FEATURE_RECOMMENDATION_V2 === 'true',
    WEBSOCKET_REAL_TIME: process.env.FEATURE_WEBSOCKET === 'true',
    NEW_CHECKOUT_FLOW: process.env.FEATURE_NEW_CHECKOUT === 'true',
    AI_SEARCH: process.env.FEATURE_AI_SEARCH === 'true',
  })
}

export const FEATURES = loadFeatureFlags()

7.2 Minimizing Conflicts with Modular Architecture

Clearly dividing boundaries so team members work on different modules can greatly reduce merge conflicts.

src/
  modules/
    user/          # Team member A owns
      domain/
      application/
      infrastructure/
      presentation/
    product/       # Team member B owns
    order/         # Team member C owns
    recommendation/ # Team member D owns
  shared/          # Shared code (minimize changes)
    utils/
    types/
    errors/

7.3 Using AI to Resolve Conflicts

A merge conflict occurred. Analyze both changes and suggest the correct merge:

<<<<<<< HEAD (my changes)
[paste code]
=======
[paste their code]
>>>>>>> feature/recommendation

Identify the intent of both changes and generate a merged result that preserves both.

8. Technical Debt Management with AI

8.1 Technical Debt Patterns in AI-Generated Code

Rapid development with Vibe Coding can accumulate technical debt.

Common technical debt in AI-generated code:

  • Over-abstraction (unnecessary interfaces/layers)
  • Unnecessary dependency additions
  • Tightly coupled code that's hard to test
  • Inconsistent error handling generated without context
  • Duplicate logic (AI regenerates logic unaware of other files)

8.2 Regular Technical Debt Reviews

# Technical Debt Review Prompt (at Sprint end)

Analyze the following codebase and identify technical debt:
[list of changed files]

Analysis items:

1. Duplicate code (DRY violations)
2. Excessive complexity (cyclomatic complexity over 10)
3. Unnecessary abstraction layers
4. Inconsistent error handling
5. Areas with low test coverage

For each item:

- Location (file, line)
- Severity (Critical/Major/Minor)
- Estimated refactoring time
- Recommended approach

8.3 Tech Debt Sprint Allocation

# Allocate 20% of every Sprint to resolving technical debt

# GitHub Issues label strategy
labels:
  - name: tech-debt
    color: '#e4e669'
    description: Technical debt issue
  - name: ai-generated
    color: '#7c3aed'
    description: AI-generated code needs review
  - name: needs-refactor
    color: '#f97316'
    description: Needs refactoring

Quiz

Q1: Why is Trunk-Based Development (TBD) more advantageous than GitFlow for Vibe Coding teams?

Answer: TBD has short branch lifespans (2 days max), enabling rapid integration of AI-generated code, minimizing merge conflicts, and enabling continuous integration.

Explanation: In GitFlow, feature branches can live for days to weeks. When AI rapidly generates code, branches live even longer, causing frequent merge conflicts. TBD merges to main 1-2 times per day, so AI-generated code is rapidly integrated and the whole team stays on the latest codebase. Feature flags allow safely merging even incomplete features.

Q2: How is BREAKING CHANGE expressed in Conventional Commits and what version impact does it have?

Answer: Add BREAKING CHANGE: description in the commit message footer, or append an exclamation mark (!) after the type. This increments the Major version in Semantic Versioning.

Explanation: Example: feat!: remove legacy API endpoint or in footer: BREAKING CHANGE: /api/v1/users endpoint removed, use /api/v2/users. In Semantic Versioning (SemVer), changes that break backward compatibility increment the Major version (1.0.0 → 2.0.0). Automated changelog tools (standard-version, release-please) detect this and automatically update versions.

Q3: What are the 3 main benefits of Skills files (/commit, /review, etc.)?

Answer: Maintains consistent AI workflows across the entire team, automates repetitive work with reusable prompts, and automatically applies team rules (coding conventions, quality standards) to AI.

Explanation: Without Skills files, each team member uses different prompts, resulting in inconsistent quality and style in AI output. Version-controlling (Git) Skills files allows managing team AI workflows just like code. For example, the /commit command always generates messages in Conventional Commits format, and /review automatically applies the team's security checklist.

Q4: What are the 4 core metrics in SonarQube Quality Gate?

Answer: New code coverage (80%+), duplicate code ratio (3% or less), Blocker issues (0), Critical issues (0).

Explanation: SonarQube Quality Gate automatically checks code quality standards before PR merges. New code coverage is the test ratio for added code. Duplicate code detects DRY principle violations. Blocker/Critical issues find security vulnerabilities or bugs. Integrating SonarQube into CI/CD pipelines automatically blocks merging PRs below the quality threshold.

Q5: What are the 3 main reasons to use feature flags?

Answer: Safely integrating unfinished code into the main branch (TBD support), gradual rollout to specific users/environments, and enabling A/B testing and rapid rollback.

Explanation: Without feature flags, using TBD would expose unfinished features in production. Managing feature flags as environment variables allows running different feature sets in development, staging, and production from the same codebase. In Vibe Coding environments where AI rapidly adds features, the strategy of gradually activating only completed features with feature flags is critical.

Q6: What are 3 common technical debt patterns in AI-generated code?

Answer: Unnecessary abstraction (excessive interfaces/layers), duplicate logic (AI unaware of other files' context), and inconsistent error handling.

Explanation: Because AI only knows information within its context window, it often regenerates utility functions that already exist in other files. Also, different error handling patterns are used across different AI sessions, reducing code consistency. Technical debt must be managed by specifying forbidden patterns in CLAUDE.md and through regular technical debt review Sprints.


Summary

Success in Vibe Coding team collaboration rests on three core pillars:

1. Git Strategy: Maintain short-lived branches and frequent integration with Trunk-Based Development. Safely manage unfinished code with feature flags, and implement automated releases with Conventional Commits.

2. CI/CD Automation: Fully automate lint, type-check, unit/integration tests, security scans, Docker builds, and deployments with GitHub Actions. Every PR must pass CI before it can be merged.

3. Code Quality: Enforce code quality standards with ESLint + Prettier + SonarQube, and standardize team AI workflows with Skills files. Maintain the quality of AI-generated code through regular technical debt reviews.

Teams with these three pillars well-established can convert AI's speed into team-wide productivity gains.