
AI에게 "이 버그 고쳐줘"라고 통째로 맡기면 왜 절반은 틀리는가 — 디버깅을 "추측 게임"에서 "과학"으로 되돌리는 AI와의 실전 가이드
요약
AI에게 단순히 버그 수정을 맡기면 추측에 의존하여 근본 원인을 해결하지 못하는 경우가 많습니다. 통계와 연구를 바탕으로 AI를 '추측하는 도구'가 아닌 '관측하는 도구'로 활용하여 디버깅의 정확도를 높이는 실전 가이드를 제시합니다.
핵심 포인트
- AI 생성 코드의 43%는 운영 환경에서 추가 수동 디버깅이 필요함
- 코딩 에이전트는 조사보다 추측하고 표면적인 해결책을 제시하는 경향이 있음
- 단순한 수정 요청 대신 AI가 관측(Observation)을 수행하도록 유도해야 함
- 디버깅의 핵심은 근본 원인(Root Cause)을 해결하는 것이지 대증요법이 아님
에러가 발생한다. 새빨간 스택 트레이스 (stack trace)를 복사해서 AI에게 툭 붙여넣는다. "이것 좀 고쳐줘".
……이런 행동, 저도 정말 많이 합니다. 빠르고, 맞으면 기분이 좋으니까요.
하지만 솔직하게 말하겠습니다. 결과가 꽤 극명하게 갈리지 않나요?
수치로도 나타나고 있습니다. Lightrun의 「2026 State of AI-Powered Engineering Report」(미국/영국/EU 대기업의 SRE·DevOps 리더 200명 조사, VentureBeat 보도)에 따르면, AI가 생성한 코드 변경 사항의 43%가 QA와 스테이징 (staging)을 통과한 후, 운영 환경에서 다시 한번 수동 디버깅이 필요했다고 합니다. 게다가 AI가 내놓은 수정 사항을 '단 한 번의 재배포'로 확정 지을 수 있었던 사람은 0명이었습니다. 88%는 23회, 11%는 46회나 다시 고쳐야 했습니다.
또 다른 생생한 연구가 있습니다. 『How Coding Agents Fail Their Users』(arXiv:2605.29442, 2026-05)라는 논문에서 실제 개발 세션 20,574건을 분석한 결과, 코딩 에이전트(coding agent)에게는 공통된 습성이 있다는 것을 발견했습니다. 바로 "조사하기보다 추측하기 (guessing rather than investigating)", 그리고 "근본 원인을 건드리지 않고 표면적인 대증요법을 제시하기 (surface-level symptom fixes)"입니다.
여기서 중요한 점은, 이것이 "AI가 똑똑하지 않아서"가 아니라는 사실입니다. 오히려 똑똑하기 때문에 "그럴듯한 답"을 순식간에 내놓을 수 있는 것입니다. 문제는 요청하는 방식에 있습니다. "고쳐줘"라는 한마디가 AI에게 추측을 강요하고 있는 것이죠.
이 기사는 그 요청 방식을 근본부터 바꾸는 이야기에 관한 것입니다. 키워드는 단 하나입니다.
추측하게 하지 말고, 관측하게 하라.
사실 이것은 새로운 이야기가 아닙니다. 디버깅의 올바른 방법은 이미 20년 전에 거의 답이 나와 있습니다. 오늘은 그것을 AI와 함께 수행하는 형태로 번역해 나가고자 합니다.
참고로, 이 기사에서 다루는 것은 "한 건의 버그를 자신의 책상에서 고치는" 개발 디버깅 이야기입니다. 운영 장애 대응(로그 집약·트리아지(triage)·완화·포스트모템(post-mortem))이나 성능 개선(속도 측정)은 각각 별도의 유형이 있으므로, 여기서는 정답성(correctness)에 관한 버그에 집중하여 이야기하겠습니다.
무지의 무지, 즉 "모른다는 사실조차 모르는" 상태로 남겨지는 것이 가장 괴롭습니다. 그래서 먼저 용어들을 대략적으로 정의하겠습니다. 아는 분들은 건너뛰셔도 좋습니다.
버그 (bug): 프로그램이 "의도한 동작"과 다르게 움직이는 것. 에러로 중단되는 것뿐만 아니라, "조용히 잘못된 결과를 반환하는 것"도 버그입니다. -
재현 (repro): 해당 버그를 의도적으로 몇 번이고 일으킬 수 있는 상태로 만드는 것. "가끔 발생하는 일"을 "반드시 발생하는 일"로 바꾸는 작업입니다. -
스택 트레이스 (stack trace): 에러가 발생한 순간의 "함수 호출 이력". 사고 현장에 남은 브레이크 자국 같은 것입니다. -
로그 (log) / 계측 (instrumentation): 코드의 주요 지점에 "지금 여기를 통과했어, 변수 값은 이 값이야"라고 말하게 하는 것. 자동차에 속도계를 사후 장착하는 이미지입니다. -
근본 원인 (root cause)과 대증요법 (symptomatic fix): 비가 새는 상황에 비유하자면, 천장의 얼룩을 새로 칠하는 것이 대증요법이고, 지붕의 구멍을 막는 것이 근본 원인입니다. 다시 칠해도 얼룩은 또 생깁니다. -
회귀 (regression): 고쳤다고 생각한 버그가 나중에 다시 나타나는 것. 혹은 고치는 과정에서 다른 곳이 망가지는 것을 말합니다. -
회귀 테스트 (regression test): "이 버그가 두 번 다시 돌아오지 않는가"를 자동으로 계속 체크하는 테스트. 밟았던 지뢰에 꽂아두는 "출입 금지" 표지판과 같습니다. -
이분 탐색 (bisect): "어느 타이밍에 망가졌는가"를 범위를 절반씩 나누어 좁혀가는 탐색 방법. 범인을 "전반부에 있는가? 후반부에 있는가?"로 몰아붙이는 방식입니다.
이런 용어들이 몸에 익어 있으면 AI에 대한 지시도 훨씬 구체적이 됩니다.
이유를 정신론이 아닌 구조적으로 살펴보겠습니다. 세 가지가 있습니다.
AI는 당신의 코드베이스 전체도, 운영 데이터도, 해당 함수가 어떤 약속(계약)에 의해 호출되는지도 기본적으로는 보이지 않습니다. 보이지 않는 부분은 학습 데이터의 "흔한 패턴"으로 보완합니다. 그래서 에러 문구만 전달하면, "세상 일반적인 흔한 원인"을 자신만만하게 채워 넣습니다. 맞을 때도 있지만, 당신의 현장 상황은 완전히 무시됩니다.
「고쳐줘」라는 말을 들은 AI의 목표는 「에러가 사라지는 코드를 반환하는 것」이 되기 쉽습니다. 에러만 사라지면, 원인을 이해하지 못하더라도 태스크를 "달성"한 것처럼 보입니다. 그래서 try/except로 에러를 억누르거나(swallow), if x is None: return을 추가하는 식의 「증상만 없애는」 수정이 아무렇지 않게 나옵니다. 작동은 합니다. 하지만, 고쳐진 것은 아닙니다.
②번 방식의 수정은 그 자리에서는 작동하니까 기분이 좋습니다. 하지만 근본 원인이 살아있기 때문에, 조금 다른 조건에서 다시 얼굴을 내밉니다. 게다가 에러를 억누른 곳에는 「왜 여기서 None이 오는가」라는 질문이 매몰된 채 남겨집니다. 반년 뒤의 자신(혹은 AI)이 그 흑마술(black magic) 앞에서 굳어버리게 됩니다.
서두의 연구(arXiv:2605.29442)가 20,574개 세션에서 발견한 「추측」과 「대증요법」은, 바로 이 ①②③이 현장에서 분출된 모습입니다. 모델을 더 똑똑한 것으로 교체하더라도, 요청하는 방식이 "추측을 유도하는 형태"로 남아 있다면 이 구조는 변하지 않습니다.
여기서 발상을 한 단계 전환해 보겠습니다.
많은 사람은 디버깅을 「고장 난 코드를 올바른 코드로 다시 쓰는 작업」이라고 생각합니다. 그래서 AI에게 「다시 쓰기」를 부탁하죠. 하지만 그것은 마무리 단계의 일부일 뿐입니다.
디버깅의 본체는 「왜 고장 났는지, 그 이유를 찾아내는 작업」입니다. 이것은 쓰는 일이 아니라, 조사하는 일입니다. 더 정확히 말하면, **가설을 세우고, 관측으로 확인하며, 범위를 좁혀나가는 과학(science)**입니다.
사실 이것은 소프트웨어 공학(Software Engineering)에서 이미 정리되어 있습니다. Andreas Zeller의 명저 『Why Programs Fail: A Guide to Systematic Debugging』(2005)은 디버깅에 **과학적 방법론(scientific method)**을 도입했습니다. 흐름은 단순합니다.
- 실패를 **재현(reproduce)**한다
- 원인에 대한 **가설(hypothesis)**을 세운다
- 가설이 맞다면 「이렇게 관측될 것이다」라고 **예측(predict)**한다
- **실험(experiment)**하여 예측이 맞는지 확인한다
- 설명이 확고해질 때까지 가설을 수정하며 반복한다
같은 Zeller의 「Delta Debugging」(IEEE TSE 2002)이라는 논문 제목은 디버깅의 기분을 완벽하게 표현하고 있습니다. 그 내용은 이렇습니다. 「Yesterday, my program worked. Today, it does not. Why? (어제는 작동했다. 오늘은 작동하지 않는다. 왜?)"
이 "과학"의 프레임에 올라타면, 인간과 AI의 역할이 명확하게 결정됩니다.
- 인간 = 과학자. 무엇이 이상한지 정의하고, 가설을 세우며, 「무엇을 관측해야 결론이 날 것인가」를 결정하고, 마지막에 수정을 승인합니다. 여기는 What / Why의 영역입니다.
- AI = 매우 유능한 실험 조수. 로그나 트레이스(trace)를 고속으로 읽고, 관측용 코드를 작성하며, 가설을 나열하고, 최소한의 수정 차분(diff)을 작성하며, 회귀 테스트(regression test)를 작성합니다. 여기는 How의 영역입니다.
따라서 구호는 이렇게 됩니다.
추측하게 하지 말고, 관측하게 하라.
AI에게 「원인을 맞춰봐」라고 하면 추측 게임이 됩니다. 「이 가설을 확인할 수 있는 관측 코드를 작성해줘」라고 하면 과학이 됩니다. 같은 AI라도 끌어낼 수 있는 결과가 완전히 달라집니다.
과학적 방법론을 내일부터 바로 실행할 수 있는 5단계로 정리하겠습니다. 전체 모습은 다음과 같습니다.
① 재현(Reproduce): 실패를 반드시 일으킬 수 있는 상태로 만든다 (실패하는 테스트를 먼저 작성)
② 관측(Observe): 추측하지 않고 사실을 수집한다 (로그, 트레이스, 이분 탐색)
③ 가설(Hypothesize): 원인 후보를 여러 개 내놓고 확률 순으로 나열한다
...
그리고 각 단계에서 인간과 AI의 분담을 대략적으로 먼저 배치해 두겠습니다.
단계 | 인간(What/Why) | AI(How)
① 재현 | 무엇이 「올바른」 것인지 정의 | MRE화·repro 절차 정리
② 관측 | 어디를 관측해야 결론이 날지 결정 | 로그 삽입·트레이스 독해
...
이제부터 단계별로 구체적으로 들어가 보겠습니다.
디버깅에서 가장 저지르기 쉬운 실수는 재현하지 못한 채 수정을 시작하는 것입니다. 재현할 수 없다면 고쳐졌는지조차 확인할 수 없습니다. 운 좋게 사라진 것인지, 정말로 고친 것인지 구분할 수 없기 때문입니다.
따라서 가장 먼저 해야 할 일은 수정이 아니라, "그 버그를 밟는, 실패하는 테스트를 한 줄 쓰는 것"입니다. 이것이 있으면 고쳐졌는지 여부를 「테스트가 Red에서 Green으로 변했는가」로 기계적으로 판단할 수 있습니다.
예를 들어 「할인 계산이 특정 조건에서 마이너스가 되는」 버그라면, 다음과 같이 작성합니다.
# test_discount.py
# 버그를 재현하기 위한 「실패하는 테스트」를 먼저 작성한다 (red)
from pricing import apply_discount
...
이 테스트가 「빨간색(실패)」이 되는 것을 먼저 확인한다. 재현에 성공한 순간, 버그는 절반은 해결된 것이나 다름없습니다.
여기서 중요한 것이 결정론화 (Determinization) 입니다. 「가끔 발생하는」 버그는 AI에게도 인간에게도 지옥입니다. 랜덤(Random), 시간, 외부 통신, 병렬 처리와 같은 "변동성(Fluctuation)"을 고정하여, 「반드시 발생하는」 상태를 만듭시다.
# 변동성을 고정하여 「가끔」을 「반드시」로 만든다
import random
def test_flaky_becomes_deterministic():
...
AI에게 맡길 부분은 이 「재현 절차의 정리」와 「최소 재현 사례 (MRE, Minimum Reproducible Example)화」입니다. 긴 재현 절차에서 버그와 관계없는 부분을 걷어내고, 최소한의 재현 코드로 만들어 달라고 요청합니다. 프롬프트는 다음과 같은 느낌입니다.
【역할】 당신은 디버깅 실험 조수입니다. 원인에 대한 추측은 아직 하지 마세요.
【상황】 다음 절차로 버그가 재현됩니다 (전문 첨부).
(재현 절차, 에러 메시지, 관련 코드를 붙여넣기)
...
「아직 수정하지 마라」고 못을 박는 것이 요령입니다. 그대로 두면 AI는 순식간에 ④단계로 넘어가 추측을 시작하기 때문입니다.
재현에 성공했다면, 다음은 사실 수집입니다. 여기가 이 글의 핵심입니다.
원칙은 하나입니다. AI에게도 자신에게도, 추측을 금지하고 관측하게 할 것. 「아마 여기가 원인일 것」이 아니라, 「여기에 로그를 넣어서 실제 값을 확인한다」입니다.
스택 트레이스 (Stack Trace)는 위에서 아래로 「호출된 순서」대로 나열되어 있습니다. 우선 우리 코드에서 가장 마지막에 나오는 줄, 그곳이 사고의 입구인 경우가 많습니다. AI에게 전달할 때는 「원인을 맞춰봐」가 아니라 「다음에 관측해야 할 장소를 딱 하나만 제시해줘」라고 부탁합니다.
【역할】 실험 조수로서, 추측이 아닌 「다음 관측 지점」을 제시해 주세요.
【재료】
- 실패하는 테스트 (Step 1에서 작성하여 첨부)
...
「사실과 추측을 분리할 것」, 「다음은 딱 한 곳만」 —— 이 두 가지만으로도 AI의 폭주를 상당히 막을 수 있습니다.
제안된 로그를 실제로 넣고 실행합니다. 여기서 비로소 「생각했던 값과 다르다」는 사실이 보이기 시작합니다.
import logging
logger = logging.getLogger(__name__)
def apply_discount(base_price, discount_percent):
...
이를 실행해서 percent=150 이 들어오고 있다는 것을 알게 되면, 「할인율 상한 체크가 없다」는 사실을 관측할 수 있습니다. 추측이 아니라, 눈으로 확인한 사실입니다.
「지난주까지는 잘 돌아갔는데」와 같은 버그는, 어느 커밋에서 망가졌는지 찾는 것이 가장 빠릅니다. 손으로 하나씩 되돌리는 것은 힘들기 때문에, git의 이분 탐색 (Binary Search)을 사용합니다. 좋은 커밋과 나쁜 커밋을 알려주면 절반씩 범위를 좁혀줍니다.
# 현재는 망가져 있고, 3일 전에는 작동했다는 것을 알고 있을 때
git bisect start
git bisect bad # 현재 커밋은 「나쁨」
...
범인이 되는 커밋을 찾아내면, 그 차이점(diff)을 보는 것만으로 원인이 거의 보입니다. 여기까지 오면 AI에게 전달하는 정보의 질이 차원이 달라지겠죠.
관측을 통해 사실이 모였다면, 원인에 대한 가설을 세웁니다. 여기서 빠지기 쉬운 함정은, 처음 떠오른 단 하나의 가설과 사랑에 빠지는 것입니다. 인간도 AI도 이 실수를 합니다.
대책은 「여러 개를 내놓고, 확률 순으로 나열하기」입니다. 그리고 각 가설에 대해, 그 가설을 어떻게 관측해야 부정할 수 있는지 (Kill Condition)를 미리 결정해 두는 것입니다. 반증을 준비해 두는 것이 과학의 방식입니다.
【역할】 실험 조수로서, 원인에 대한 가설을 여러 개 제시해 주세요. 단정하지 말 것.
【재료】 관측으로 알게 된 사실 (Step 2의 불렛 포인트) + 관련 코드 (첨부)
【의뢰】
...
이렇게 하면 AI의 출력이 「이것이 원인입니다 (단호)」에서 「후보군과, 그것을 검증하기 위한 실험 세트」로 바뀝니다. 그다음은 인간이 비용이 낮은 실험부터 순서대로 관측하며 가설을 하나씩 지워나갑니다. 남은 것이 진실이라는 탐정 같은 움직임이죠.
여기서 명심해야 할 점은, AI가 내놓은 가설은 「주장」이지 「사실」이 아니라는 것입니다. 그럴듯함과 올바름은 전혀 별개의 문제입니다. 반드시 관측으로 뒷받침해야 합니다. 이는 이후의 안전 장(Safety Chapter)에서도 다시 등장합니다.
원인이 관측을 통해 확정되었다면, 드디어 수정입니다. 여기서의 구호는, 근본 원인을, 최소한의 차이로 (Minimal Diff), 이 한 점뿐입니다.
아까 발생한 할인 버그. 원인은 "할인율의 상한·하한 체크가 없음"이었습니다. 잘못된 수정(대증요법, Symptomatic treatment)과 좋은 수정(근본 수정, Root cause fix)을 나란히 비교해 보겠습니다.
# ❌ 대증요법: 증상(마이너스 가격)만을 지우고 있음
def apply_discount(base_price, discount_percent):
discounted = base_price * (1 - discount_percent / 100)
...
# ✅ 근본 수정: 부적절한 입력 그 자체를 경계에서 차단함
def apply_discount(base_price, discount_percent):
# 할인율은 0~100 범위에서만 의미를 갖는다는 "계약 (Contract)"을 명시한다
...
대증요법 버전은 "마이너스가 되면 0으로 만든다"라며 증상을 숨기고 있을 뿐입니다. 150%라는 부적절한 입력이 왜 들어왔는가라는 진짜 질문은 그대로 남아 있습니다. 근본 수정 버전은 "할인율은 0~100"이라는 **계약 (Contract)**을 경계에서 지킵니다. 이후 이상한 값은 입구에서 차단됩니다.
AI에게 수정을 요청할 때는, "대증요법이 되지 않았는지 스스로 비판하게끔" 요청하는 것이 효과적입니다.
【역할】 확정된 근본 원인(Step 2/3에서 관측 완료)에 대해 수정안을 제시해 주세요.
【원인】 할인율의 상한 체크가 없어, 100을 초과하는 값이 그대로 계산됨.
【의뢰】
...
"덤으로 리팩터링 (Refactoring)을 섞지 않는 것"도 은근히 중요합니다. 수정과 무관한 변경 사항이 섞이면 리뷰도 롤백 (Rollback)도 한꺼번에 어려워지기 때문입니다.
수정 완료. 테스트가 통과됨(Green). ……에서 끝내지 않는 것이 프로의, 아니 내일의 자신에게 친절한 사람의 방식입니다.
마지막으로, Step 1에서 작성한 "실패하는 테스트"를 영구적인 회귀 테스트 (Regression test)로 남깁니다. 이렇게 하면 이 버그가 미래에 다시 몰래 침입하려 하는 순간, CI가 빨간색(Red)으로 변하며 막아줄 것입니다. 밟았던 지뢰에 "출입 금지" 표지판을 꽂는 이미지입니다.
# test_discount.py (회귀 테스트로서 영구화)
import pytest
from pricing import apply_discount
...
이 테스트를 CI에 올려두면 재발을 시스템적으로 방지할 수 있습니다.
# .github/workflows/test.yml (발췌)
name: test
on: [push, pull_request]
...
여유가 있다면 초경량의 "포스트모템 (Post-mortem)"도 1~2줄 남겨두면 최고입니다. 드라마틱한 반성문일 필요는 없습니다.
## bug: 할인 가격이 마이너스가 됨 (2026-07-04)
- 증상: discount_percent=150으로 가격이 음수 발생
- 관측된 사실: 입력에 상한 체크가 없어 100 초과 값이 그대로 계산됨
...
이것은 AI에게 관측 로그와 수정 diff를 전달하여 초안을 작성하게 하면 10초면 충분합니다. 미래의 자신(과 다음에 만질 AI)에게 남기는 편지가 됩니다.
AI와 디버깅할 때, 속도보다 먼저 지켜야 할 선이 있습니다.
디버깅 중에는 무심코 생(raw) 로그를 그대로 AI에게 던지고 싶어집니다. 하지만 그 로그에 API 키, 토큰, 개인정보, 운영 DB 접속 문자열이 섞여 있다면 어떨까요? AI에게 전달하는 것 = 외부로 유출하는 것입니다. 한 번 전달하면 캐싱될 수도 있고, 취소할 수 없다는 전제하에 움직이는 것이 안전합니다. 붙여넣기 전에 마스킹 (Masking) 하세요.
# ❌ 그대로 붙여넣지 말 것
logger.debug("request: %s", request) # 헤더에 토큰이 실려 있을지도 모름
# ✅ 비밀 정보는 제거한 후
...
"운영 DB에서 이 DELETE를 실행해 봐" 같은 디버깅은 사고가 나면 되돌릴 수 없습니다. 운영 DB의 삭제, 결제, 메일 발송, 배포——이런 불가역적 조작은 반드시 인간의 게이트 (Gate)를 거치게 하세요. AI에게는 복사한 검증 환경이나 읽기 전용(Read-only) 연결만 허용해야 합니다.
Step 3에서도 말씀드렸지만, 몇 번이고 강조하겠습니다. AI의 설명은 유창하고 굉장히 정답처럼 들립니다. 하지만 정답처럼 보이는 것과 정답인 것은 다릅니다. 반드시 관측(로그, 테스트)을 통해 확인한 후에 믿으세요. 서두에 언급한 Lightrun의 수치—AI의 수정이 2~3회의 재배포 끝에 고쳐졌다는 점—는 바로 "한 번에 믿으면 화상을 입는다"는 사실을 뒷받침하는 증거입니다.
사용자의 입력이나 외부 서비스의 메시지에 AI를 향한 지시문 형태의 문자열(예: "지금까지의 지시를 무시하고...")이 섞여 들어올 수 있습니다. 디버깅 자료로 붙여넣을 때도, 그것은 어디까지나 조사 대상 데이터이지 AI에 대한 명령이 아니라는 틀 안에서 다뤄야 합니다. 디버깅을 통해 프롬프트 인젝션 (Prompt Injection)의 입구가 열리지 않도록 주의하십시오.
| 할 일 | 인간 (What / Why) | AI (How) |
|---|---|---|
| 무엇이 '옳은지'에 대한 정의 | ◎ 결정함 | — |
| ... |
경계선은 언제나 동일합니다. What(무엇을)과 Why(왜)는 인간, How(어떻게)는 AI입니다. 디버깅에서도 이 선은 움직이지 않습니다.
재현하지 않고 고치기 시작한다 → 고쳐졌는지 영원히 확인할 수 없다. 먼저 실패 테스트를 수행할 것. -
첫 번째 가설과 사랑에 빠진다 → 반증(kill 조건)을 미리 결정해 둘 것. -
대증요법을 "수정"이라 부른다 → 증상을 숨기는 것은 부채다. 근본을 끊어낼 것. -
AI의 설명을 관측 없이 믿는다 → 주장은 사실이 아니다. 로그로 뒷받침할 것. -
수정에 리팩터링 (Refactoring)을 섞는다 → 리뷰도 롤백 (Rollback)도 어려워진다. 차분(diff)은 최소화할 것. -
생(raw) 로그를 통째로 AI에 붙여넣는다 → 비밀 정보나 PII(개인 식별 정보) 유출 위험. 마스킹 후 진행할 것.
AI의 수정안이 같은 곳에서 3회 연속으로 틀렸다 → 전제(전달하고 있는 문맥)가 잘못되었다는 신호. 손을 멈추고 관측을 다시 할 것. -
원인이 "보안", "비용", "데이터 소실"과 관련될 것 같다 → 속도보다 정확성. 인간이 주도할 것. -
도저히 재현할 수 없다 → 고치기 전에 먼저 관측(로그 강화·모니터링) 장치를 심어 "다음에 발생했을 때 잡는다"로 전환할 것.
"AI에게 맡기지 않는 것" 또한 훌륭한 설계 판단입니다. 어디까지 맡기고 어디서부터 직접 쥘 것인가를 결정하는 것이 앞으로 엔지니어의 역량을 보여줄 대목이라고 생각합니다.
내용이 길어졌으니, 가장 중요한 부분만 챙겨가시기 바랍니다.
디버깅은 코드를 다시 쓰는 작업이 아니라, 가설을 관측으로 확인하는 "과학"입니다. 그리고,
추측하게 하지 말고, 관측하게 하라.
AI에게 "원인을 맞춰봐"라고 하면 추측 게임이 됩니다. 하지만 "이 가설을 확인할 수 있는 관측 코드를 작성해줘"라고 하면 과학이 됩니다. 같은 AI로부터 전혀 다른 결과물을 끌어낼 수 있습니다. 인간이 What / Why(무엇이 옳고, 왜 그렇게 말할 수 있으며, 무엇을 관측해야 결론을 내릴 수 있는가)를 갖고, AI에게 How(읽기·쓰기·나열하기·만들기)를 맡기십시오. 이 선만 지켜도, 서두에 언급한 "43%가 운영 환경에서 재디버깅"과 같은 사고는 크게 줄어들 것입니다.
마지막으로, 마음가짐에 관한 이야기를 하나 덧붙이겠습니다.
버그를 발견했을 때, "왜 이런 걸 놓쳤을까"라며 과거의 자신을 자책하고 싶어질 것입니다. 하지만 저는 그 부분이 자책의 대상이 될 필요는 없다고 생각합니다. 버그는 발생하기 마련입니다. 중요한 것은, 오늘 그것을 겪고, 관측하고, 근본을 고치고, "출입 금지" 표지판(회귀 테스트, Regression Test)을 하나 세워두는 것입니다.
그 표지판은 반년 뒤에 다시 같은 구멍에 빠질 뻔한 당신을 CI의 빨간 램프로 멈춰 세워줄 것입니다. 그때 내일의 당신은 이렇게 말할 것입니다. "표지판 세워둬서 고마워요."
디버깅의 패턴도, 관측의 습관도, 쌓아 올린 회귀 테스트도, AI는 빼앗을 수 없는 당신만의 자산입니다. 그야말로 Code as Capital입니다. 도구는 빌려 쓰더라도, "고칠 수 있는 힘"만은 자신의 것으로 만들어 갑시다.
다음에 버그를 발견하면, 고치기 전에 "실패하는 테스트를 1개" 작성할 것. -
"원인을 맞춰봐"가 아니라, AI에게 "다음에 관측해야 할 한 곳"을 물을 것. -
수정안에 대해 "이것은 대증요법이 아닌가요?"라고 한마디 덧붙여 자기 비판을 유도할 것. -
고쳤다면, 그 테스트를 회귀 테스트로 남겨서 CI에 태울 것.
이것만으로도 당신의 디버깅은 "추측 게임"에서 "과학"으로 변하기 시작할 것입니다. 내일의 당신이 "고마워요"라고 말할 수 있는 한 걸음을, 오늘 하나 내디뎌 보시기 바랍니다.
- Andreas Zeller,
Why Programs Fail: A Guide to Systematic Debugging, Morgan Kaufmann, 2005 (과학적 방법론에 의한 디버깅) - Andreas Zeller, "Simplifying and Isolating Failure-Inducing Input" (델타 디버깅(Delta Debugging), IEEE TSE 2002)
- Tang et al.,
How Coding Agents Fail Their Users: A Large-Scale Analysis of Developer-Agent Misalignment in 20,574 Real-World Sessions, arXiv:2605.29442, 2026-05 - Lightrun,
2026 State of AI-Powered Engineering Report (VentureBeat 보도 / SRE 및 DevOps 리더 200명 조사) - Git 공식 문서 (
git bisect
)
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기