O

systematic-debugging

작성자 obra

어떤 수정도 하기 전에 반드시 근본 원인을 파고들도록 강제하는 4단계 디버깅 워크플로와, 플래키 테스트·검증·테스트 오염을 다루는 실질적인 도구들을 제공합니다.

Stars0
즐겨찾기0
댓글0
카테고리Debugging
설치 명령어
npx skills add https://github.com/obra/superpowers --skill systematic-debugging
개요

개요

systematic-debugging이란?

systematic-debugging 스킬은 어떤 기술적 문제에도 적용할 수 있는, 구조화된 4단계 디버깅 프로세스입니다. 테스트 실패, 프로덕션 버그, 플래키 테스트, 성능 문제, 빌드 에러, 통합 실패 등 다양한 이슈에 사용할 수 있습니다.

"빠른 한 번의 수정"이나 첫 번째 에러 라인의 코드를 바로 고치려 하기보다는, 먼저 근본 원인을 찾아낸 뒤 지속 가능한 수정을 설계하고 검증하도록 강제합니다. 실제 코드베이스에서 추출한 실전 패턴과 스크립트가 함께 제공되며, TypeScript 기반 조건형 대기(helper)와 테스트 오염원을 찾는 Bash 스크립트를 포함합니다.

핵심 원칙과 철의 법칙

systematic-debugging의 핵심은 단순합니다.

  • 핵심 원칙: 수정 전에 반드시 근본 원인을 찾는다. 증상만을 고치는 수정은 실패다.

  • 철의 법칙 (Iron Law):

    NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
    

조사 단계가 끝나지 않았다면, 어떤 수정도 제안하거나 적용하지 않습니다. 시간 압박, 추측, "이번 한 번만" 같은 합리화를 막도록 설계되었습니다.

이 스킬이 필요한 사람

systematic-debugging은 다음과 같은 사람을 대상으로 합니다.

  • 신뢰할 수 있고 재현 가능한 수정을 원하는 JavaScript/TypeScript 개발자
  • 플래키 동작, 랜덤 타임아웃, 오염된 테스트 상태를 다루는 테스트·QA 엔지니어
  • 간헐적인 빌드/통합 실패를 진단하는 CI/CD 및 도구 엔지니어
  • 디버깅 작업에 공통의 엄격한 프로세스를 도입하고 싶은 테크 리드 및 코드 리뷰어

빠른 땜질보다는, 근본 원인 분석의 품질을 더 중시하는 팀에 특히 잘 맞습니다.

어떤 문제를 해결하나요?

다음과 같은 상황에서 systematic-debugging 스킬을 활용하세요.

  • "수정" 후에도 계속 재발하는 테스트 실패를 조사해야 할 때
  • 임의의 타임아웃이나 레이스 컨디션에 의존하는 플래키 테스트를 추적할 때
  • 에러를 단순히 숨기지 말고 예상치 못한 동작의 원인을 이해해야 할 때
  • 느리거나 타이밍에 민감한 흐름에서 성능 문제를 진단할 때
  • CI나 부하 환경에서만 발생하는 빌드/통합 실패를 디버깅할 때
  • 어떤 테스트가 상태를 오염시키거나 원치 않는 파일/디렉터리를 남기는지 찾아야 할 때

저장소에는 다음과 같은 자료도 포함되어 있습니다.

  • TypeScript에서 setTimeout/sleep 대신 견고한 조건 기반 대기를 구현하는 condition-based-waiting.md, condition-based-waiting-example.ts
  • 여러 계층에서의 검증을 통해 특정 버그가 구조적으로 불가능해지도록 만드는 defense-in-depth.md
  • 원치 않는 파일이나 상태를 만들어내는 테스트를 찾는 Bash 헬퍼 find-polluter.sh
  • 에러를 호출 체인을 따라 추적해 진짜 기원을 찾는 root-cause-tracing.md

systematic-debugging이 잘 맞는 경우

systematic-debugging은 다음과 같은 상황에서 특히 효과적입니다.

  • 시간 압박을 받고 있어, 추측 기반 수정을 하고 싶은 유혹이 들 때
  • 여러 번 시도했는데도 같은 이슈가 계속 다시 나타날 때
  • 자신 또는 팀을 위한 반복 가능한 디버깅 워크플로를 만들고 싶을 때
  • 플래키 테스트 스위트를 안정화하거나 오염된 테스트 환경을 정리해야 할 때

다음과 같은 경우에는 덜 적합할 수 있습니다.

  • 조사 없이 한 번만 빠르게 코드 생성이나 리팩터링을 하고 싶을 때
  • 여기서 다루는 기술 영역 밖을 디버깅하는 경우 (예: 비기술적 프로세스 문제)
  • 단계적인 프로세스를 따를 생각이 없고, 즉흥적인 실험을 선호할 때

목표가 "지금 빨리 막고, 나중에 다시 손본다"라면 이 프로세스는 다소 엄격하게 느껴질 수 있습니다. 반대로 "한 번에 제대로 고친다"가 목표라면, systematic-debugging은 그에 맞추어 설계되어 있습니다.

사용 방법

설치 및 설정

systematic-debugging 스킬을 호환되는 에이전트나 툴 환경에 설치하려면 다음 npx 명령을 사용합니다.

npx skills add https://github.com/obra/superpowers --skill systematic-debugging

이 명령은 obra/superpowers 리포지토리의 skills/systematic-debugging 아래에 있는 스킬 정의와 관련 문서·스크립트를 가져옵니다.

설치 후에는:

  1. 에이전트 또는 스킬 UI에서 systematic-debugging 스킬을 엽니다.
  2. 작업 공간이 프로젝트 리포지토리, 테스트 실행 명령, 로그에 접근할 수 있는지 확인합니다.
  3. 다음 번들 문서와 스크립트를 볼 수 있는지 확인합니다.
    • SKILL.md
    • condition-based-waiting.md
    • defense-in-depth.md
    • root-cause-tracing.md
    • find-polluter.sh

알아두어야 할 파일과 구성 요소

설치 여부를 판단하거나 일상적으로 사용할 때 특히 중요한 파일은 다음과 같습니다.

  • SKILL.md – 전체 4단계 체계적 디버깅 프로세스, 규칙, 안티 패턴을 정의합니다. 이 스킬의 핵심입니다.
  • condition-based-waiting.md – 테스트에서 임의의 타임아웃 대신 조건 기반 대기 방식으로 전환하는 방법을 설명합니다.
  • condition-based-waiting-example.tsThreadManager와 이벤트 타입을 대상으로 조건 기반 대기를 구현하는 waitForEvent 같은 TypeScript 유틸리티를 제공합니다.
  • defense-in-depth.md – 엔트리 포인트, 비즈니스 로직, 환경 가드, 로깅 등 여러 계층의 검증을 통해 특정 유형의 버그를 원천 차단하는 방법을 보여줍니다.
  • find-polluter.sh – 어떤 경로(상태 오염)를 생성한 테스트 파일을 찾기 위해 테스트를 순차적으로 실행하는 Bash 스크립트입니다.
  • root-cause-tracing.md – 스택 트레이스에서 시작해 버그를 원래 트리거 지점까지 추적한 뒤, defense-in-depth와 결합해 해결하는 과정을 다룹니다.
  • CREATION-LOG.md – 이 프레임워크가 어떻게 추출·강화되었는지 설명하는 메타 로그로, 설계 의도를 이해하는 데는 유용하지만, 일상 사용에는 필수는 아닙니다.

JavaScript/TypeScript 개발자는 TypeScript 예제와 Bash 스크립트를 직접 프로젝트에 맞게 변형해 사용할 수 있습니다.

4단계 워크플로 실행하기

systematic-debugging 프로세스는 SKILL.md에 설명된 4개의 필수 단계로 구성되어 있습니다. 각 단계를 완료한 뒤에만 다음 단계로 넘어갈 수 있습니다.

1단계 – 근본 원인 조사

코드, 설정, 테스트를 수정하기 전에 다음을 수행합니다.

  • 에러 메시지와 로그를 꼼꼼히 읽습니다.
    • 스택 트레이스나 경고를 대충 넘기지 않습니다.
    • 라인 번호, 파일 경로, 에러 코드를 기록합니다.
  • 이슈를 안정적으로 재현합니다.
    • 최소한의, 신뢰할 수 있는 재현 명령을 만듭니다.
    • 필요한 입력값과 환경 요소를 기록합니다.

이 단계에서는 수정안을 제안하거나 구현하지 않습니다. 정확히 무엇이, 어디서, 어떤 조건에서 실패하는지 이해하는 것이 목표입니다.

2단계 – 패턴 분석

재현이 안정적으로 가능해졌다면:

  • 입력, 설정, 환경 등 한 번에 한 요소씩 바꿔가며 결과가 어떻게 달라지는지 확인합니다.
  • 정상 동작과 실패 동작이 갈리는 경계 조건을 찾습니다.
  • 로그, 어서션, 임시 계측(instrumentation)을 활용해 실패 경로를 좁혀 나갑니다.

2단계가 끝날 즈음에는 단순한 에러 메시지를 넘어, 문제의 형태와 그것을 트리거하는 조건을 이해하고 있어야 합니다.

3단계 – 가설 수립과 설계

이제 가설을 세울 수 있습니다.

  • 근본 원인이 무엇이라고 생각하는지 명확히 서술합니다. (데이터 플로우, 누락된 검증, 타이밍 문제, 잘못된 경로 등)
  • 그 근본 원인을 해결할 단일하고 집중된 변경 사항을 설계합니다.
  • 앞서 만든 재현 절차를 활용해 가설을 어떻게 검증할지 계획합니다.

가설이 틀린 것으로 드러나면, 새로운 추측성 수정을 덧붙이지 말고 다시 조사/분석 단계로 돌아갑니다.

4단계 – 구현과 검증

명확한 가설이 세워진 이후에만 코드나 설정을 수정합니다.

  • 근본 원인을 직접 겨냥하는 최소한의 변경만 적용합니다.
  • 최소 재현 절차를 실행한 뒤, 더 넓은 테스트 스위트를 돌립니다.
  • 다음 문서를 참고해 보완합니다.
    • 여러 계층에 검증을 추가하는 defense-in-depth.md
    • 진짜 근원을 수정하고 있는지 확인하는 root-cause-tracing.md
  • 부하 환경, CI, 2단계에서 확인한 엣지 케이스 등에서도 수정이 견고하게 동작하는지 확인합니다.

수정이 기대한 대로 동작하지 않는다면, 변경을 더 쌓지 말고 앞선 단계로 돌아갑니다.

프로젝트에서 디버깅 유틸리티 사용하기

플래키 테스트를 위한 조건 기반 대기 (JavaScript/TypeScript)

setTimeout이나 sleep에 의존하는 플래키 테스트는 머신이 느리거나 빠르거나 부하가 걸린 상태에서 쉽게 깨집니다. condition-based-waiting.mdcondition-based-waiting-example.ts는 "시간 추측" 대신, 원하는 조건이 충족될 때까지 기다리는 패턴을 제시합니다.

일반적인 마이그레이션 예시는 다음과 같습니다.

// ❌ Before: guessing timing
await new Promise(r => setTimeout(r, 50));
const result = getResult();
expect(result).toBeDefined();

// ✅ After: waiting for condition
await waitFor(() => getResult() !== undefined);
const result = getResult();
expect(result).toBeDefined();

제공되는 condition-based-waiting-example.ts에는 다음과 같은 헬퍼가 포함되어 있습니다.

export function waitForEvent(
  threadManager: ThreadManager,
  threadId: string,
  eventType: LaceEventType,
  timeoutMs = 5000
): Promise<LaceEvent> { /* ... */ }

이 패턴을 자신의 테스트 인프라에 맞게 적용하려면:

  1. 유틸리티를 프로젝트의 테스트 헬퍼로 복사하거나 재구현합니다.
  2. 임의의 setTimeout/sleep 호출을 조건 기반 대기로 교체합니다.
  3. 테스트 스위트를 다시 실행해 플래키 현상이 줄어드는지 확인합니다.

이는 무작정 타임아웃을 늘리는 대신 근본 원인을 제거한다는 systematic-debugging의 목표를 직접적으로 지원합니다.

find-polluter.sh로 오염된 테스트 찾기

테스트가 불필요한 파일이나 디렉터리를 남기거나, 전역 상태를 오염시키는 경우 find-polluter.sh는 그 원인이 되는 테스트를 찾아내는 데 도움을 줍니다.

사용법 (프로젝트 루트에서, 인자를 상황에 맞게 조정):

./find-polluter.sh <file_or_dir_to_check> <test_pattern>

# Example
./find-polluter.sh '.git' 'src/**/*.test.ts'

이 스크립트는 다음을 수행합니다.

  • 패턴에 매칭되는 테스트 파일을 찾습니다.
  • 각 테스트를 npm test <file>로 하나씩 실행합니다.
  • 각 실행 후 대상 파일 또는 디렉터리가 존재하는지 확인합니다.
  • 해당 경로를 처음 생성한 테스트를 찾아, 다시 실행하고 조사할 수 있는 명령과 함께 보고합니다.

이는 상태 오염을 재현하고 분리하는 안정적인 방법을 제공하므로, systematic-debugging의 1단계와 2단계에 자연스럽게 통합됩니다.

defense-in-depth 검증 적용하기

조사 과정에서 잘못된 데이터나 잘못된 가정을 원인으로 버그가 발생했다면, defense-in-depth.md는 여러 계층에 검증을 배치할 것을 권장합니다.

  • 엔트리 포인트 검증 – API, CLI, UI 핸들러 등 경계 지점에서 명백히 잘못된 입력을 거부합니다.
  • 비즈니스 로직 검증 – 특정 연산에 대해 데이터가 의미 있는지 확인합니다.
  • 환경 가드 – 잘못된 환경이나 경로에서 위험한 작업이 수행되지 않도록 방지합니다.
  • 진단용 로깅 – 문제가 새어 나왔을 때 유용한 맥락 정보를 남깁니다.

예를 들어, workingDirectory 인자를 검증하는 코드는 다음과 같습니다.

function createProject(name: string, workingDirectory: string) {
  if (!workingDirectory || workingDirectory.trim() === '') {
    throw new Error('workingDirectory cannot be empty');
  }
  if (!existsSync(workingDirectory)) {
    throw new Error(`workingDirectory does not exist: ${workingDirectory}`);
  }
  if (!statSync(workingDirectory).isDirectory()) {
    throw new Error(`workingDirectory is not a directory: ${workingDirectory}`);
  }
  // ... proceed
}

4단계에서 수정을 구현할 때 이런 패턴을 사용하면, 다른 코드 경로를 통해 동일한 버그가 다시 나타날 가능성을 크게 줄일 수 있습니다.

이 스킬을 쓰지 않아도 되는 경우

다음과 같은 경우에는 systematic-debugging을 건너뛰거나 나중으로 미루는 것이 나을 수 있습니다.

  • 프로토타입을 만들고 있어, 버그와 일회성 코드를 의도적으로 감수하는 경우
  • (개발 중 발견된 오타처럼) 문제가 사소하고 원인이 명확해, 엄격한 4단계 프로세스를 적용할 가치가 없을 때
  • 조건 기반 대기 같은 개별 유틸리티만 필요하고, 전체 프로세스까지 도입할 필요가 없을 때

이런 경우에도 철의 법칙은 유용한 기준점이 됩니다. 추측성 수정을 몇 개나 쌓고 있는 자신을 발견한다면, 이제 systematic-debugging으로 전환할 때일 수 있습니다.

FAQ

systematic-debugging은 내 워크플로를 어떻게 바꾸나요?

에러 메시지를 보고 바로 코드를 고치는 대신, systematic-debugging은 구현에 들어가기 전에 조사, 패턴 분석, 가설 수립을 거치도록 요구합니다. 실제로는 다음과 같은 변화를 의미합니다.

  • 코드를 건드리기 전에 신뢰할 수 있는 재현 절차를 확보합니다.
  • 조건을 바꿔가며 문제 공간을 이해합니다.
  • 검증된 각 가설마다 하나의 집중된 수정만 작성합니다.

그 결과, 롤백이 줄고 숨은 회귀 버그가 적어지며, 디버깅에 드는 시간이 더 예측 가능해집니다.

systematic-debugging 스킬은 어떻게 설치하나요?

npx skills 명령을 사용합니다.

npx skills add https://github.com/obra/superpowers --skill systematic-debugging

설치 후에는 에이전트나 스킬 디렉터리에서 스킬을 연 뒤, 전체 프로세스가 담긴 SKILL.md와 패턴·예제가 들어 있는 보조 markdown 파일들을 차례로 살펴보세요.

systematic-debugging은 JavaScript와 TypeScript 디버깅을 지원하나요?

네. 프레임워크 자체는 언어에 구애받지 않지만, 리포지토리에는 JavaScript/TypeScript에 초점을 맞춘 구체적인 유틸리티가 포함되어 있습니다.

  • 테스트에서 조건 기반 대기를 구현하는 condition-based-waiting-example.ts
  • TypeScript 예제로 설명된 defense-in-depth.mdroot-cause-tracing.md의 패턴들
  • 기본적으로 npm test를 사용하며 일반적인 JS/TS 테스트 러너와 잘 맞는 find-polluter.sh

이 유틸리티들은 프로젝트 구조와 도구 체인에 맞게 자유롭게 변형해서 사용할 수 있습니다.

플래키 테스트 자동화에도 systematic-debugging을 사용할 수 있나요?

네. 이 사용 사례는 systematic-debugging의 핵심 강점 중 하나입니다. 다음을 함께 활용하세요.

  • 플래키 현상을 조사하고 이해하기 위한 SKILL.md의 4단계 프로세스
  • 타이밍 추측을 조건 기반 대기로 바꾸는 condition-based-waiting.md와 TypeScript 예제
  • 상태 오염이나 예상치 못한 파일 생성을 유발하는 테스트를 찾는 find-polluter.sh

이 도구들을 조합하면 불안정한 테스트를 안정적이고 결정적인 검증으로 전환할 수 있습니다.

systematic-debugging은 테스트에만 쓰나요, 프로덕션 버그에도 쓸 수 있나요?

이 프로세스는 모든 종류의 기술적 이슈에 적용할 수 있습니다.

  • 테스트 실패 및 플래키 테스트
  • 프로덕션 버그와 인시던트
  • 성능 문제
  • 빌드 및 통합 실패

예제와 유틸리티는 주로 테스트·개발 워크플로에 초점을 맞추고 있지만, 각 단계와 원칙은 프로덕션 시나리오도 포함하도록 명시적으로 설계되어 있습니다.

시간 압박이 심한데, 빠른 수정만 필요하면 어떻게 하나요?

이 스킬은 바로 그런 "빠른 한 번의 수정" 충동에 맞서기 위해 작성되었습니다. 다음과 같은 점을 강조합니다.

  • 근본 원인 조사 없이 서두르면, 되돌리기와 재작업이 늘어납니다.
  • 증상만을 고치는 수정은 종종 새로운 문제를 만들어냅니다.

실제 경험상, 긴급한 인시던트 상황에서도 1단계와 2단계를 거치는 데 몇 분 투자하는 편이 전체적으로 시간을 절약하는 경우가 많습니다.

네 단계 모두를 매번 꼭 따라야 하나요?

systematic-debugging의 의도는 단계를 건너뛰는 것이 예외가 되도록 하는 것입니다. (예를 들어, 작은 리팩터 중 실수를 바로 알아챈 경우처럼) 문제가 사소하고 완전히 이해된 상황에서는 단계를 압축할 수 있습니다. 하지만 다음과 같은 경우에는:

  • 이슈가 반복적으로 재발한다면
  • 왜 이런 일이 일어나는지 완전히 이해하지 못했다면
  • 이전 수정이 실패한 적이 있다면

…네 단계 전체를 따를 것을 강력히 권장합니다.

root-cause tracing과 defense-in-depth는 어떤 관계인가요?

root-cause-tracing.md는 눈에 보이는 에러에서 시작해 호출 체인을 따라가며 버그의 원래 트리거 지점까지 추적하는 방법을 설명합니다. 이어서 defense-in-depth.md는 다음과 같은 방식으로 비슷한 버그를 예방하는 방법을 보여줍니다.

  • 진짜 근원에서 문제를 수정합니다.
  • 여러 계층에 검증을 추가합니다.

예를 들어, 잘못된 디렉터리에서 실행된 git init이 실패했다면, tracing을 통해 어느 함수가 잘못된 경로를 전달했는지 찾고, defense-in-depth로 잘못된 경로를 더 이른 단계에서 걸러내는 검증과 가드를 추가합니다.

리포에서 코드를 복사하지 않고도 이 스킬을 활용할 수 있나요?

네. systematic-debugging의 핵심 가치는 SKILL.md에 정의된 구조화된 디버깅 프로세스 자체입니다. 다음과 같이 사용할 수 있습니다.

  • 자신의 환경에서 네 단계와 규칙을 그대로 따라갑니다.
  • 조사와 분석 패턴을 어떤 언어·스택에든 적용합니다.

TypeScript와 Bash 헬퍼는 특히 JS/TS 및 유닉스 계열 환경에서 속도를 높여주는 선택적 도구일 뿐입니다.

systematic-debugging에 포함된 내용을 모두 보려면 어디서 확인하나요?

설치 후 obra/superpowers 리포지토리의 skills/systematic-debugging 아래에서 파일/리포지토리 뷰를 열어보세요. 특히 확인할 파일은 다음과 같습니다.

  • SKILL.md
  • condition-based-waiting.md
  • condition-based-waiting-example.ts
  • defense-in-depth.md
  • root-cause-tracing.md
  • find-polluter.sh

이 파일들을 통해 전체 systematic-debugging 워크플로와, 디버깅 및 테스트 안정화를 위한 구체적인 도구들을 모두 살펴볼 수 있습니다.

평점 및 리뷰

아직 평점이 없습니다
리뷰 남기기
이 스킬의 평점과 리뷰를 남기려면 로그인하세요.
G
0/10000
최신 리뷰
저장 중...