Claude Code Plugins

Community-maintained marketplace

Feedback

impact-analyzer

@monicajeon28/GMcruise
0
0

**IMPACT ANALYZER v1.0** - '영향도', '영향 범위', '변경 영향', '리팩토링 영향', '이거 바꾸면', '어디에 영향', '위험도' 요청 시 자동 발동. codebase-graph 기반 변경 전파 분석. 직접/간접 영향, 위험도 점수, 테스트 범위 제안. 코드 수정 전 필수 분석.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name impact-analyzer
description **IMPACT ANALYZER v1.0** - '영향도', '영향 범위', '변경 영향', '리팩토링 영향', '이거 바꾸면', '어디에 영향', '위험도' 요청 시 자동 발동. codebase-graph 기반 변경 전파 분석. 직접/간접 영향, 위험도 점수, 테스트 범위 제안. 코드 수정 전 필수 분석.
allowed-tools Read, Glob, Grep

Impact Analyzer Skill v1.0

변경 영향도 분석기 - 코드 수정 전 영향 범위를 정확히 파악하여 안전한 변경 보장

핵심 컨셉

Problem:
  Without_Analysis: "함수 수정 → 예상치 못한 곳에서 에러 → 롤백"
  Reality: "한 줄 변경이 100개 파일에 영향을 줄 수 있음"

Solution:
  Impact_Analysis:
    - "변경 대상의 역의존성 트리 추적"
    - "직접/간접 영향 범위 계산"
    - "위험도 점수 산출"
    - "테스트 범위 자동 제안"

Key_Metrics:
  Direct_Impact: "직접 호출하는 함수들"
  Indirect_Impact: "연쇄적으로 영향받는 범위"
  Risk_Score: "변경 위험도 (0-100)"
  Test_Coverage: "영향 범위 대비 테스트 커버리지"

자동 발동 조건

Auto_Trigger_Conditions:
  Before_Edit:
    - "Edit 도구 사용 전 자동 분석 제안"
    - "공유 코드(shared, utils) 수정 시"
    - "핵심 모듈(auth, api) 수정 시"

  Keywords_KO:
    - "영향도 분석, 영향 범위"
    - "이거 바꾸면 어디 영향?"
    - "변경 영향, 수정 영향"
    - "리팩토링 영향, 리팩토링 범위"
    - "위험도, 얼마나 위험"
    - "테스트 범위, 테스트해야 할 곳"

  Keywords_EN:
    - "impact analysis, impact scope"
    - "what will this affect"
    - "change impact, modification impact"
    - "refactoring scope, refactoring impact"
    - "risk assessment, risk score"
    - "test scope, what to test"

  High_Risk_Patterns:
    - "export 변경/삭제"
    - "함수 시그니처 변경"
    - "타입 정의 변경"
    - "API 엔드포인트 변경"
    - "shared 모듈 변경"

영향도 분석 알고리즘

interface ImpactAnalysisRequest {
  target: string;                 // 변경 대상 노드 ID
  changeType: ChangeType;         // 변경 유형
  depth?: number;                 // 분석 깊이 (기본 3)
}

type ChangeType =
  | 'signature'      // 시그니처 변경 (파라미터, 반환타입)
  | 'implementation' // 구현 변경 (로직)
  | 'rename'         // 이름 변경
  | 'delete'         // 삭제
  | 'move'           // 이동
  | 'type'           // 타입 변경
  ;

interface ImpactResult {
  target: GraphNode;              // 변경 대상
  changeType: ChangeType;
  directImpact: ImpactNode[];     // 직접 영향
  indirectImpact: ImpactNode[];   // 간접 영향
  totalAffected: number;          // 총 영향받는 노드 수
  riskScore: number;              // 위험도 (0-100)
  riskLevel: 'low' | 'medium' | 'high' | 'critical';
  testSuggestions: TestSuggestion[];  // 테스트 제안
  warnings: string[];             // 경고 메시지
}

interface ImpactNode {
  node: GraphNode;
  depth: number;                  // 영향 깊이 (1=직접, 2+=간접)
  impactType: 'caller' | 'type-user' | 'importer' | 'extender';
  confidence: number;             // 영향 확실성 (0-1)
  reason: string;                 // 영향 이유
}

영향 범위 계산

class ImpactAnalyzer {
  private graph: CodebaseGraph;

  constructor(graph: CodebaseGraph) {
    this.graph = graph;
  }

  /**
   * 영향도 분석 실행
   */
  analyze(request: ImpactAnalysisRequest): ImpactResult {
    const target = this.graph.findNode(request.target);
    if (!target) {
      throw new Error(`Node not found: ${request.target}`);
    }

    // 1. 직접 영향 수집
    const directImpact = this.collectDirectImpact(target, request.changeType);

    // 2. 간접 영향 수집 (재귀)
    const indirectImpact = this.collectIndirectImpact(
      directImpact,
      request.depth || 3
    );

    // 3. 위험도 계산
    const riskScore = this.calculateRiskScore(target, directImpact, indirectImpact, request.changeType);

    // 4. 테스트 제안 생성
    const testSuggestions = this.generateTestSuggestions(target, directImpact, indirectImpact);

    // 5. 경고 생성
    const warnings = this.generateWarnings(target, directImpact, request.changeType);

    return {
      target,
      changeType: request.changeType,
      directImpact,
      indirectImpact,
      totalAffected: directImpact.length + indirectImpact.length,
      riskScore,
      riskLevel: this.getRiskLevel(riskScore),
      testSuggestions,
      warnings,
    };
  }

  /**
   * 직접 영향 수집
   */
  private collectDirectImpact(target: GraphNode, changeType: ChangeType): ImpactNode[] {
    const impacts: ImpactNode[] = [];

    // 1. 이 노드를 호출하는 함수들
    const callers = this.graph.getIncomingEdges(target.id, 'calls');
    for (const edge of callers) {
      const caller = this.graph.findNode(edge.source);
      if (caller) {
        impacts.push({
          node: caller,
          depth: 1,
          impactType: 'caller',
          confidence: changeType === 'signature' ? 1.0 : 0.7,
          reason: `Calls ${target.name}`,
        });
      }
    }

    // 2. 이 타입을 사용하는 곳
    if (target.type === 'type' || target.type === 'class') {
      const typeUsers = this.graph.getIncomingEdges(target.id, 'uses');
      for (const edge of typeUsers) {
        const user = this.graph.findNode(edge.source);
        if (user) {
          impacts.push({
            node: user,
            depth: 1,
            impactType: 'type-user',
            confidence: changeType === 'type' ? 1.0 : 0.5,
            reason: `Uses type ${target.name}`,
          });
        }
      }
    }

    // 3. 이 모듈을 import하는 파일들
    const importers = this.graph.getIncomingEdges(target.id, 'imports');
    for (const edge of importers) {
      const importer = this.graph.findNode(edge.source);
      if (importer && !impacts.some(i => i.node.id === importer.id)) {
        impacts.push({
          node: importer,
          depth: 1,
          impactType: 'importer',
          confidence: changeType === 'rename' || changeType === 'delete' ? 1.0 : 0.3,
          reason: `Imports from ${target.path}`,
        });
      }
    }

    // 4. 이 클래스를 상속하는 클래스들
    if (target.type === 'class') {
      const extenders = this.graph.getIncomingEdges(target.id, 'extends');
      for (const edge of extenders) {
        const extender = this.graph.findNode(edge.source);
        if (extender) {
          impacts.push({
            node: extender,
            depth: 1,
            impactType: 'extender',
            confidence: 1.0,
            reason: `Extends ${target.name}`,
          });
        }
      }
    }

    return impacts;
  }

  /**
   * 간접 영향 수집 (BFS)
   */
  private collectIndirectImpact(directImpact: ImpactNode[], maxDepth: number): ImpactNode[] {
    const indirect: ImpactNode[] = [];
    const visited = new Set<string>(directImpact.map(i => i.node.id));
    const queue: ImpactNode[] = [...directImpact];

    while (queue.length > 0) {
      const current = queue.shift()!;

      if (current.depth >= maxDepth) continue;

      // 현재 노드의 호출자들 수집
      const callers = this.graph.getIncomingEdges(current.node.id, 'calls');

      for (const edge of callers) {
        if (visited.has(edge.source)) continue;

        const caller = this.graph.findNode(edge.source);
        if (!caller) continue;

        visited.add(caller.id);

        const impactNode: ImpactNode = {
          node: caller,
          depth: current.depth + 1,
          impactType: 'caller',
          confidence: current.confidence * 0.7, // 깊이에 따라 감소
          reason: `Indirect via ${current.node.name}`,
        };

        indirect.push(impactNode);
        queue.push(impactNode);
      }
    }

    return indirect;
  }

  /**
   * 위험도 점수 계산
   */
  private calculateRiskScore(
    target: GraphNode,
    direct: ImpactNode[],
    indirect: ImpactNode[],
    changeType: ChangeType
  ): number {
    let score = 0;

    // 1. 변경 유형 기본 점수
    const changeTypeScores: Record<ChangeType, number> = {
      implementation: 20,
      signature: 50,
      type: 60,
      rename: 40,
      move: 45,
      delete: 80,
    };
    score += changeTypeScores[changeType];

    // 2. 직접 영향 수 (각 +3점, 최대 30점)
    score += Math.min(direct.length * 3, 30);

    // 3. 간접 영향 수 (각 +1점, 최대 20점)
    score += Math.min(indirect.length, 20);

    // 4. 대상 특성 보정
    if (target.isExported) score += 10;           // export된 것
    if (target.path.includes('shared')) score += 15; // shared 모듈
    if (target.path.includes('api')) score += 10;    // API 관련
    if (target.path.includes('auth')) score += 15;   // 인증 관련
    if (target.type === 'type') score += 10;         // 타입 정의

    // 5. 테스트 커버리지 보정
    const hasTests = this.hasTestCoverage(target);
    if (!hasTests) score += 10; // 테스트 없으면 위험

    return Math.min(score, 100);
  }

  /**
   * 위험 수준 결정
   */
  private getRiskLevel(score: number): 'low' | 'medium' | 'high' | 'critical' {
    if (score < 30) return 'low';
    if (score < 50) return 'medium';
    if (score < 75) return 'high';
    return 'critical';
  }

  /**
   * 테스트 제안 생성
   */
  private generateTestSuggestions(
    target: GraphNode,
    direct: ImpactNode[],
    indirect: ImpactNode[]
  ): TestSuggestion[] {
    const suggestions: TestSuggestion[] = [];

    // 1. 대상 테스트
    suggestions.push({
      target: target.id,
      priority: 'critical',
      reason: 'Direct change target',
      testType: 'unit',
    });

    // 2. 직접 영향 테스트
    for (const impact of direct.slice(0, 10)) { // 상위 10개
      suggestions.push({
        target: impact.node.id,
        priority: impact.confidence > 0.8 ? 'high' : 'medium',
        reason: impact.reason,
        testType: impact.impactType === 'caller' ? 'integration' : 'unit',
      });
    }

    // 3. 고확신 간접 영향 테스트
    const highConfidenceIndirect = indirect.filter(i => i.confidence > 0.5);
    for (const impact of highConfidenceIndirect.slice(0, 5)) {
      suggestions.push({
        target: impact.node.id,
        priority: 'low',
        reason: `${impact.reason} (indirect)`,
        testType: 'integration',
      });
    }

    return suggestions;
  }

  /**
   * 경고 생성
   */
  private generateWarnings(
    target: GraphNode,
    direct: ImpactNode[],
    changeType: ChangeType
  ): string[] {
    const warnings: string[] = [];

    // 1. 높은 영향 범위
    if (direct.length > 20) {
      warnings.push(`HIGH IMPACT: This change affects ${direct.length} direct callers`);
    }

    // 2. export 삭제/변경
    if (target.isExported && (changeType === 'delete' || changeType === 'rename')) {
      warnings.push(`BREAKING: Modifying exported symbol may break external consumers`);
    }

    // 3. 핵심 모듈 변경
    if (target.path.includes('shared') || target.path.includes('core')) {
      warnings.push(`CORE MODULE: Changes to shared/core modules require extra caution`);
    }

    // 4. 테스트 부족
    if (!this.hasTestCoverage(target)) {
      warnings.push(`NO TESTS: Target has no test coverage - add tests before changing`);
    }

    // 5. 순환 참조 관련
    const cycles = this.graph.detectCircularDependencies();
    if (cycles.some(c => c.includes(target.id))) {
      warnings.push(`CIRCULAR: Target is part of circular dependency - changes may cascade unpredictably`);
    }

    return warnings;
  }

  private hasTestCoverage(node: GraphNode): boolean {
    // 테스트 파일 존재 확인
    const testPatterns = [
      node.path.replace('.ts', '.test.ts'),
      node.path.replace('.ts', '.spec.ts'),
      node.path.replace('/src/', '/test/'),
    ];

    return testPatterns.some(pattern =>
      this.graph.findNode(pattern) !== null
    );
  }
}

위험도 점수 기준

Risk_Scoring:
  Base_Scores_by_Change_Type:
    implementation: 20    # 로직만 변경
    signature: 50         # 시그니처 변경
    type: 60              # 타입 정의 변경
    rename: 40            # 이름 변경
    move: 45              # 위치 이동
    delete: 80            # 삭제

  Modifiers:
    direct_impact: "+3 per caller (max 30)"
    indirect_impact: "+1 per node (max 20)"
    is_exported: "+10"
    in_shared: "+15"
    in_api: "+10"
    in_auth: "+15"
    is_type: "+10"
    no_tests: "+10"

  Risk_Levels:
    low: "0-29 (안전한 변경)"
    medium: "30-49 (주의 필요)"
    high: "50-74 (신중한 검토 필요)"
    critical: "75-100 (위험, 충분한 테스트 필수)"

출력 템플릿

## Impact Analysis Report

### Target: {{targetName}}
- **Path**: {{targetPath}}:{{targetLine}}
- **Type**: {{targetType}}
- **Change Type**: {{changeType}}

---

### Risk Assessment
| Metric | Value |
|--------|-------|
| Risk Score | {{riskScore}}/100 |
| Risk Level | {{riskLevel}} |
| Direct Impact | {{directCount}} nodes |
| Indirect Impact | {{indirectCount}} nodes |
| Total Affected | {{totalAffected}} nodes |

---

### Direct Impact ({{directCount}} nodes)
| Node | Type | Reason | Confidence |
|------|------|--------|------------|
{{#each directImpact}}
| {{node.name}} | {{impactType}} | {{reason}} | {{confidence}}% |
{{/each}}

---

### Indirect Impact (Top 10 of {{indirectCount}})
| Node | Depth | Reason | Confidence |
|------|-------|--------|------------|
{{#each indirectImpact}}
| {{node.name}} | {{depth}} | {{reason}} | {{confidence}}% |
{{/each}}

---

### Warnings
{{#each warnings}}
- {{this}}
{{/each}}

---

### Recommended Tests
| Target | Priority | Type | Reason |
|--------|----------|------|--------|
{{#each testSuggestions}}
| {{target}} | {{priority}} | {{testType}} | {{reason}} |
{{/each}}

---

### Verdict
{{#if riskLevel === 'critical'}}
**CRITICAL**: Do NOT proceed without comprehensive test coverage and review.
{{else if riskLevel === 'high'}}
**HIGH RISK**: Proceed with caution. Ensure all suggested tests pass.
{{else if riskLevel === 'medium'}}
**MEDIUM RISK**: Safe to proceed with standard review process.
{{else}}
**LOW RISK**: Safe to proceed. Minor change with limited impact.
{{/if}}

Quick Commands

Command Action
impact <target> 기본 영향도 분석
impact signature <target> 시그니처 변경 영향도
impact delete <target> 삭제 영향도
impact rename <target> 이름 변경 영향도
impact depth <n> <target> 깊이 지정 분석
impact test <target> 테스트 제안만
impact warnings <target> 경고만

다른 스킬과의 통합

Integration:
  codebase-graph:
    type: "데이터 소스"
    usage: "그래프 쿼리, 역의존성 추적"

  smart-context:
    type: "협력"
    usage: "영향 범위 컨텍스트 생성"

  code-reviewer:
    type: "소비자"
    usage: "리뷰 시 영향도 표시"

  tdd-guardian:
    type: "소비자"
    usage: "테스트 범위 제안 수신"

  vibe-coding-orchestrator:
    type: "제공자"
    usage: "대규모 리팩토링 전 자동 분석"

문서 구조

impact-analyzer/
├── SKILL.md                      # 이 파일 (메인)
├── core/
│   ├── impact-calculation.md     # 영향도 계산 상세
│   ├── risk-scoring.md           # 위험도 점수 체계
│   └── test-suggestion.md        # 테스트 제안 알고리즘
├── algorithms/
│   ├── reverse-dependency.md     # 역의존성 추적
│   ├── propagation.md            # 영향 전파 알고리즘
│   └── confidence.md             # 확신도 계산
├── templates/
│   ├── report-template.md        # 리포트 템플릿
│   └── warning-templates.md      # 경고 메시지 템플릿
└── quick-reference/
    ├── commands.md               # 명령어 가이드
    └── risk-guide.md             # 위험도 해석 가이드

Version: 1.0.0 Quality Target: 95% Required Skill: codebase-graph Related Skills: smart-context, code-reviewer, tdd-guardian