FEInterview Prep

Netlify

어떤 버그든 고치는 방법

*'클로드에게 고쳐달라'* 가 안 통할 때 진짜 도구는 재현 → 좁히기 → 모든 걸 제거하기 의 잘 정의된 재귀(well-founded recursion). 댄 아브라모프의 디버깅 매뉴얼.

2025-11-17·7분 읽기
커리어AI & 도구
원문 보기 ↗

핵심 요약

Step 0: 일단 AI 에게 시켜본다. 통하면 끝, 안 통하면 재현이 부족한 신호. Step 1: 재현을 찾는다 — 어떤 절차어떤 기대어떤 실제 를 보는지를 명확히. 실패율이 높으면 불확실 요인 제거. Step 2: 재현을 좁히고/대체 한다. 단, 이전 재현새 재현 이 같은 버그를 잡는지 항상 검증 — 새 재현으로 버그가 없는 정상 케이스 도 재현되는지 확인하면 안전. Step 3: 다른 모든 것을 제거. (1) 재현 실행 → 버그 확인 → (2) 한 조각 제거 → (3) 재현 재실행 → 버그 있으면 커밋, 없으면 마지막 커밋으로 리셋 + 더 작은 조각 시도. 항상 버그가 살아있는 체크포인트 를 유지. Step 4: 더 줄일 수 없는 코드까지 도달하면 원인이 외부 라이브러리내 코드 든 명확해진다. 본 글의 사례에서는 React Router 의 ScrollRestoration 의 알려진 버그가 원인이었다.

디버깅을 '직관으로 원인을 찍는 일' 이 아니라 '재현(repro) 을 가진 채 — 매번 더 작아지는 — 코드 영역으로 좁혀가는 잘 정의된 재귀' 로 본다. 핵심은 항상 버그가 살아있는 체크포인트를 유지 하면서 한 단위씩 제거. 새 가설 검증으로 버그 없는 케이스 만 남으면 길을 잃는다.

AI 코딩이 보편화되면서 수정 시도는 빨라졌지만 잘못된 수정도 빨라졌다. 본 글은 그 함정을 이렇게 짚는다.

  • 재현이 모호하면 AI 도, 사람도 옳은 일을 한 척 하는 코드를 만든다 — 검증 기준이 없으니까
  • 화면 흔들림 같은 시각적 증상 은 AI 가 직접 보지 못해 — 측정 가능한 재현 (스크롤 위치 비교 등) 으로 바꿔야 함
  • 새 가설을 시도하다가 원래 재현을 잃으면 몇 시간을 엉뚱한 문제 에 쓴다
  • 다른 모든 걸 제거 까지 가야 외부 라이브러리 버그 vs 내 코드 버그를 가릴 수 있다

AI 시대에도 디버깅의 규율 은 줄어들지 않는다 — 오히려 더 중요해진다.

학습 포인트

면접 답변으로 연결할 학습 포인트입니다.

재현 없이는 *고치는 척* 만 가능하다

AI 에게 고쳐달라 한 번에 안 되면, 그건 보통 모델 능력 문제가 아니라 재현이 부재 하다는 신호다.

좋은 재현:
  1. 절차: "버튼 클릭 → 1초 대기 → 다시 클릭"
  2. 기대: "화면이 아래로 스크롤"
  3. 실제: "스크롤 위치가 0 → 100 → 0 으로 흔들림"
  4. 빈도: 매번

약한 재현:
  - "가끔 깨짐" → 30% 확률이면 같은 검증을 여러 번 돌려야
  - "느낌이 이상함" → 측정 가능한 메트릭으로 변환

'각 단계가 측정 가능한가' 가 좋은 재현의 핵심.

repro테스트절차/기대/실제재현 빈도
자주 하는 오해

'증상이 보이니 재현 충분'. AI/도구가 그 증상을 직접 관찰할 수 없다면 측정 가능한 형태로 바꿔야 한다.

재현 *교체* 는 위험 — 두 케이스가 같은 버그인지 확인

원래 재현(스크롤 흔들림) 을 측정 가능한 재현(클릭 후 스크롤 위치 변화 없음) 으로 바꿀 때, 단순히 새 케이스가 실패하는지만 보면 전혀 다른 문제 를 잡을 수 있다.

검증 절차:
  1. 새 재현으로 버그 확인 → 실패해야 함
  2. 원래 알려진 *수정 후보* (네트워크 호출 주석)를 적용
  3. 새 재현이 *정상 동작* 으로 돌아오는지 확인
  4. 다시 수정 되돌리기 → 새 재현이 다시 실패
  5. 두 번째 사이클까지 일관되면 같은 버그로 가정 가능

원래 재현과 연동된 정상 케이스가 새 재현에서도 정상 으로 보여야, 같은 문제일 가능성이 높다.

repro 교체정상 동작 확인위험 검증관련성
자주 하는 오해

새 재현이 그럴듯해 보인다 는 이유로 유사 증상 을 진짜 원인으로 단정하는 것.

*잘 정의된 재귀* 처럼 좁혀가기

디버깅의 제거 단계 는 다음 규칙을 지켜야 한다.

function narrow(repro):
  while True:
    if not repro.hasBug(): rollback()  # ← 핵심
    code = removeOnePiece(repro.code)
    if repro(code).hasBug():
      commit()
    else:
      rollback()                       # ← 마지막 커밋으로
      tryDifferentSmallerPiece()

항상 버그가 살아있는 체크포인트 를 유지하면서 한 단위씩 제거. AI 에게 지시 할 때도 이 규율을 명시해야 한다 — 본 글의 클로드는 자기 가설을 검증하느라 버그 없는 케이스만 만들고 길을 잃었다.

bisectionwell-founded recursion체크포인트regress
자주 하는 오해

새 가설이 떠오르면 원래 재현을 떠나 시험하는 것. 시험이 실패해도 원래 재현으로 돌아오지 않으면 진척이 0.

읽는 순서

  1. 1이론

    git bisect 의 동작 원리를 정독하고, 이 글의 narrow() 의사 코드와 같은 구조임을 확인.

  2. 2구현

    팀의 최근 어려운 버그 하나에 Step 0~3 워크플로우 를 그대로 적용한 retro 를 적는다.

  3. 3실무

    PR 템플릿에 재현 절차/기대/실제 섹션을 추가해 재현 없는 PR 을 받지 않도록 강제.

  4. 4설명

    주니어 멘토링에서 'AI 가 못 고치는 버그는 어떻게 푸는가' 30분 워크숍을 진행.

면접 연결 질문

medium*재현이 30% 확률로만 발생* 하는 버그를 받았습니다. 어떻게 100% 재현으로 끌어올리시겠어요?
힌트

[감점 답변] '더 자주 시도한다'. [좋은 답변] (1) 불확실 요인 을 하나씩 고정 — 네트워크 응답을 mock 으로 캡처해 결정론화, 시간/랜덤을 시드 고정. (2) 환경 차이 를 줄임 — 같은 브라우저 버전, 클린 프로필. (3) 동시성 이 의심되면 throttle/지연을 부러 넣어 race 를 강제. 100% 못 만들면 수정 전후 30회 vs 30회 처럼 통계적 검증으로 보완.

mediumAI 에게 *디버깅 워크플로우* 를 시킬 때 가장 자주 어기는 규칙은 무엇이고, 프롬프트에서 어떻게 강제하시겠어요?
힌트

[감점 답변] '그냥 더 자세히 설명한다'. [좋은 답변] AI 는 새 가설로 자주 원래 재현을 떠난다. 프롬프트에 (1) 매 단계마다 재현 실행 → 버그 확인, (2) 버그 없으면 마지막 커밋으로 리셋, (3) 절대 새 재현을 만들지 말 것 을 명시. 본 글의 Step 3 워크플로우 를 그대로 시스템 프롬프트로 박는 것이 효과적.

자기 점검

본인의 가장 최근 버그를 떠올려 *재현 → 좁히기 → 원인* 의 단계를 5줄로 적어보세요.
repronarrowing체크포인트원인
자주 하는 오해

'직관으로 빨리 찍었다' 는 사례가 많아 보이지만, 그건 작은 버그 이거나 예전에 비슷한 걸 본 경험 의 단축일 뿐이다.