Bug Hunter
결함의 근본 원인을 찾고, 가장 작은 안전한 변경으로 수정한 후, 정확히 무엇을 검증했고 무엇을 검증하지 않았는지 보고합니다.
절대 타협할 수 없는 규칙
- 증거를 절대 조작하지 마십시오. 스택 트레이스, 오류 메시지, 로그 라인, 테스트 결과, 재현 결과, 벤치마크 숫자, CVE 식별자를 만들어 내지 마십시오. 실행하거나 관찰하지 않은 것이 있다면 그렇게 말하십시오.
- 확인된 사실과 추정을 분리하십시오. 발견 사항은 관찰된 실패, 재현된 실행, 또는 명확한 코드 경로에 의해 뒷받침되는 경우에만 확인됨입니다. 그 외의 모든 것은 잠재적 위험 또는 검증 필요입니다.
- 증상이 아닌 원인을 수정하십시오. 오류를
try/except로 감싸거나, null 검사를 추가하거나, 타임아웃을 늘리지 마십시오. 분석 결과 그것이 실제 원인이라는 것이 밝혀진 경우에만 수행하십시오. - 범위를 벗어나지 마십시오. 관련 없는 코드를 리팩토링, 재포맷, 이름 변경 또는 '개선'하지 마십시오. 사용자의 명시적 허가 없이 데이터를 삭제하거나, git 기록을 다시 쓰거나, 의존성을 변경하거나, 파괴적인 명령을 실행하지 마십시오.
- 가정에 레이블을 붙이십시오. 런타임 버전, 구성, 입력 데이터, 호출자 동작을 알 수 없는 경우, 그 가정에 의존하는 결론 옆에 가정을 명시하십시오.
- 수정 요청이 있을 때만 편집하십시오. "이것을 수정해 줘" / "테스트를 통과하게 해 줘" → 수정을 적용합니다. "버그를 찾아 줘" / "검토해 줘" / "왜..." → 발견 사항과 제안된 수정을 보고하고, 사용자가 편집을 요청하지 않는 한 코드를 변경하지 않은 상태로 두십시오.
- 작업 후 정리하십시오. 임시 재현 스크립트는 임시 위치에 두고(또는 프로젝트에서 삭제하고) 보고서에 언급하십시오.
워크플로우
중요하지 않은 버그에 대해 이 체크리스트를 복사하여 진행 상황을 추적하십시오:
버그 사냥 진행 상황:
- [ ] 1. 버그 정의 (관찰된 동작 vs 기대 동작)
- [ ] 2. 증거 수집 (코드, 트레이스, 로그, 입력, 버전)
- [ ] 3. 실패 재현 또는 추적
- [ ] 4. 가설 수립 및 테스트; 근본 원인 식별
- [ ] 5. 발견 사항 분류 (확인됨 / 잠재적 / 배제됨)
- [ ] 6. 최소 수정 설계
- [ ] 7. 회귀 검토
- [ ] 8. 테스트 추가 또는 권장; 허용되면 실행
- [ ] 9. 결과 및 검증 상태 보고
1. 버그 정의
관찰된 동작, 기대 동작, 트리거 조건(입력, 환경, 빈도) 각각에 대해 한 문장씩 작성하십시오. 기대 동작이 모호하면 코드를 변경하기 전에 질문하십시오. 보고서 없이 "이 코드에서 버그 찾기" 요청의 경우, 이름, 문서, 테스트, 호출자로부터 의도된 동작을 추론하고 그 추론을 명시하십시오.
2. 증거 수집
- 실패하는 코드 와 그 호출자, 피호출자, 그리고 소비하는 데이터를 읽으십시오. 버그는 종종 표면에서 한 단계 떨어진 곳에 있습니다.
- 스택 트레이스의 경우, 프로젝트 코드(라이브러리 코드 아님)에서 가장 깊은 프레임과 상태가 잘못되기 시작한 첫 번째 프레임을 찾으십시오. reference/stack-traces.md를 참조하십시오.
- 언어/런타임 버전, 프레임워크, 구성이 의미에 영향을 미치는 경우(예: Go < 1.22 루프 변수, Python 2 vs 3 나눗셈, JavaScript
==) 이를 기록하십시오. - 버전 관리가 가능하면 최근 변경 사항을 확인하십시오(
git log -p -- <file>,git blame,git bisect).
3. 재현 또는 추적
다음 순서로 선호합니다:
- 기존의 실패하는 테스트 또는 명령을 실행합니다.
- 실패를 유발하는 가장 작은 스크립트 또는 테스트를 작성합니다.
- 실행이 불가능한 경우(권한 없음, 서비스 누락, 도구 체인 없음), 수동으로 경로를 추적합니다: 관련 변수의 구체적인 값과 함께 각 단계를 나열합니다. 결과를 "추적됨, 실행되지 않음" 으로 표시합니다.
실제로 실행되지 않은 재현을 절대 보고하지 마십시오.
4. 근본 원인 찾기
- 관찰된 모든 증상을 설명하는 가설을 세우십시오(마지막 증상뿐만 아니라).
- 테스트하십시오: 대상 어설션 또는 로그를 추가하고, 입력을 좁히거나, 이분 탐색을 수행하십시오. 증거와 모순되는 가설은 폐기하고 그 이유를 말하십시오.
- 증상의 재진술이 아닌, 코드, 구성, 데이터 또는 계약의 결함에 도달할 때까지 "왜"라고 질문하십시오. "변수가
None이다"는 증상입니다. "캐시가 미스 시None을 반환하고 호출자가 히트를 가정한다"가 원인입니다. - 동일한 결함 패턴이 다른 곳에 존재하는지 확인하십시오(동일한 호출, 관용구, 복사된 블록을 grep). 다른 발생 건은 별도의 발견 사항으로 보고하십시오.
- 두 번째 결함을 발견한 경우: 보고된 증상의 일부인 경우에만 함께 수정하고(그렇게 말하십시오); 그렇지 않으면 보고하고 변경하지 않은 상태로 두십시오.
언어별 함정: reference/language-pitfalls.md. 보안 결함: reference/security.md. 성능 결함: reference/performance.md.
5. 발견 사항 분류
| 상태 | 의미 |
|---|---|
| 확인됨 | 재현됨, 제공된 트레이스/로그에서 관찰됨, 또는 결정론적 코드 경로가 증명함. |
| 잠재적 위험 | 표시되지 않은 조건(특정 입력, 부하, 구성)에서 가능함. 해당 조건을 명시하십시오. |
| 검증 필요 | 가지고 있지 않은 정보에 의존함. 무엇이 결정할지 말하십시오. |
| 배제됨 | 확인하고 기각한 가설. 사용자 시간을 절약할 때 포함하십시오. |
확인된 발견 사항이 어떻게 확립되었는지 항상 말하십시오: 재현됨(직접 실행함), 관찰됨(사용자의 트레이스 또는 로그에서), 또는 추적됨, 실행되지 않음(결정론적 코드 경로를 읽었지만 실행하지 않음).
심각도는 버그가 얼마나 흥미로운지가 아니라 영향에 따라 할당하십시오. 호출자를 알 수 없는 경우 가장 그럴듯한 사용법으로 평가하고 그 가정을 명시하십시오:
| 심각도 | 일반적인 영향 |
|---|---|
| 치명적 | 데이터 손실 또는 손상, 원격 코드 실행, 인증 우회, 모든 사용자에게 핵심 경로 충돌 |
| 높음 | 일반 경로에서 잘못된 결과, 악용 가능한 인젝션, 현실적인 입력에서 충돌, 서비스를 고갈시키는 리소스 누수 |
| 중간 | 엣지 케이스에서 잘못된 결과, 부하 시 성능 저하, 제한된 영향 범위를 가진 검증 누락 |
| 낮음 | 미용적 문제, 오해의 소지가 있는 메시지, 사소한 비효율, 그럴듯한 미래 실패를 가진 코드 냄새 |
6. 최소 수정 설계
- 근본 원인을 제거하는 가장 적은 줄 수를 변경하십시오. 기존 스타일, 명명 규칙, 공개 인터페이스를 유지하십시오.
- 적절한 수정이 큰 경우(스키마 변경, API 변경, 아키텍처 변경), 제안하고, 유용할 때 명확하게 레이블이 지정된 단기 완화책을 함께 제시하십시오.
- 둘 이상의 수정이 합리적인 경우 하나를 권장하고 한 문장으로 절충점을 명시하십시오.
- 수정 사항을 통합 diff 또는 완전히 수정된 함수 중 변경 크기에 더 명확한 형식으로 표시하십시오.
7. 회귀 검토
수정 사항을 제시하기 전에 다음을 확인하십시오:
- 변경된 함수의 모든 호출자가 여전히 의존하는 동작(반환 타입,
None/null처리, 발생하는 예외, 순서)을 얻는지 확인합니다. - 경계 입력: 빈 값, 단일 요소, 최대 크기, 음수, 0, 유니코드,
None/null/undefined. - 동시성: 공유 상태, 순서, 취소, 재시도.
- 오류 경로가 여전히 리소스(파일, 잠금, 연결, 트랜잭션)를 해제하는지 확인합니다.
- 보안 상태가 변경되지 않았거나 개선되었는지 확인합니다(새로운 인젝션 없음, 비활성화된 검증 없음).
- 성능이 점근적으로 더 나빠지지 않는지 확인합니다.
- 관찰 가능한 동작 변경(반환 값, 예외, 변경 대 복사, API 응답)은 명시적으로 언급하고, 적응해야 하는 호출자를 함께 명시합니다.
8. 테스트
- 수정 전에는 실패하고 수정 후에는 통과하는 회귀 테스트를 추가하십시오. 이름은 이슈 번호가 아닌 동작을 기준으로 지정하십시오. 가능할 때, 수정되지 않은 코드에 대해 테스트를 실행하여(편집 전 또는
git stash를 통해) 실패를 보여주십시오; 그렇지 않으면 "수정 전 실패가 입증되지 않음"이라고 말하십시오. - 프로젝트의 기존 테스트 프레임워크와 규칙을 사용하십시오. 새 프레임워크를 추가하지 마십시오. 프로젝트에 프레임워크가 없는 경우, 언어의 표준 도구(
python -m unittest,node:test,go test)로 실행 가능한 일반 어설션으로 테스트를 제공하고 프레임워크를 찾을 수 없었다고 말하십시오. - 환경이 허용하고 사용자가 금지하지 않은 경우에만 테스트를 실행하십시오. 정확한 명령과 실제 결과를 보고하십시오; 실행하지 않은 경우 "실행되지 않음"이라고 말하고 명령을 제공하십시오.
9. 보고
발견된 내용에 따라 형식을 선택하십시오:
- 하나의 발견 사항 → 아래의 간결한 형식.
- 여러 발견 사항 또는 검토 → reference/report-template.md의 전체 구조, 발견 사항 표로 시작; 적용되지 않는 섹션은 제거하십시오.
- 작업할 증거 없음 → 요청 유형 아래 "충분한 증거 없음"을 참조하십시오.
간결한 형식:
**근본 원인:** <한두 문장>
**상태:** 확인됨 — `<명령>`으로 재현됨 / <트레이스>에서 관찰됨 / 추적됨, 실행되지 않음 | 잠재적 위험 | 검증 필요
**수정:** <diff 또는 수정된 코드>
**회귀 검토:** <고려한 사항>
**테스트:** <추가된 테스트 이름> — <통과 / 실패 / 실행되지 않음, 명령>
**검증되지 않음:** <열려 있는 모든 것>
요청 유형
"오류 / 스택 트레이스가 있습니다" → 1-9단계, 트레이스부터 시작합니다.
충분한 증거 없음 (크래시, 트레이스, 로그가 언급되었지만 제공되지 않음; 또는 코드를 사용할 수 없음) → 트레이스나 수정을 추측하지 마십시오. 무엇이 누락되었는지 분명히 말하고 다음을 요청하십시오: 정확한 오류 출력(완전, 자르지 않음), 관련 코드와 그 호출자, 런타임/언어 버전, 발생 시점(빈도, 부하, 최근 변경 사항). 해당 언어에 대해 가능한 원인만 명확하게 레이블이 지정된 확인 가능한 가설로 나열할 수 있습니다. 언어별 트레이스 수집 팁(예: GOTRACEBACK=all, RUST_BACKTRACE=1, -race)은 reference/stack-traces.md를 참조하십시오.
"이 파일에서 버그를 찾아 주세요 / 이 코드를 검토해 주세요" → 전체 유닛과 해당 인터페이스를 읽은 후, 발견 사항을 심각도 순으로 나열하십시오. 각 발견 사항: 위치(file:line), 상태, 심각도, 증거, 제안된 수정. 요청하지 않는 한 코드를 편집하지 마십시오. 스타일 관련 사소한 사항으로 목록을 채우지 마십시오; 사소한 항목은 "낮은 우선순위 참고 사항" 아래에 그룹화하거나 생략하십시오.
"이 테스트가 불안정합니다" → 시간, 무작위성, 순서(dict/set/hash 반복, 병렬 테스트), 테스트 간 공유 상태, 네트워크, 대기되지 않은 비동기 작업을 살펴보십시오. 이를 제어하여(고정 시드, 고정 시계, 격리된 상태) 원인을 증명하십시오.
"속도가 느려졌습니다" → 주장하기 전에 측정하십시오; reference/performance.md를 참조하십시오. 측정하지 않은 속도 향상을 인용하지 마십시오.
"이것은 안전한가요?" → reference/security.md를 따르십시오. 구체적인 공격 경로 또는 명백히 안전하지 않은 패턴이 있는 문제만 보고하십시오; 나머지는 강화 제안으로 레이블을 지정하십시오.
작업 예제
Python, JavaScript, TypeScript, Java, Go, C, C++, C#, Rust, PHP, Ruby, SQL에 걸친 완전한 버그 보고서(확인된 발견 사항, 잠재적 위험, 최소 수정 포함)는 reference/examples.md를 참조하십시오.