AI 코딩 도구

AI로 디버깅: Claude Code로 근본 원인 찾기 (2026)

2026년 8월 20일10분 읽기

AI로 디버깅한다는 것은 Claude Code 같은 어시스턴트를 코드를 읽고 실패의 경로를 추적하는 "조사관"으로 다루는 것이에요. 단순히 빠른 "패치"를 내놓는 도구가 아니고요. 핵심 규칙은 증상에 패치를 붙이지 말고 먼저 근본 원인을 찾는 것이에요. 예외가 발생하는 지점이 실제 버그가 사는 곳인 경우는 드물어요. 6단계 워크플로: (1) 버그를 재현하고 전체 스택 트레이스를 확보하기, (2) 충분한 컨텍스트를 읽히기, (3) AI에게 "먼저 조사하고, 편집하지 말라"를 강제하기, (4) 근본 원인 가설을 검증하기, (5) 재현 테스트와 함께 가장 작고 안전한 수정을 적용하기, (6) 실패 패턴을 CLAUDE.md에 기록하기.

Jasmine, 매일 Claude Code로 디버깅하는 개발자.

AI로 디버깅한다는 건 무엇인가요?

AI로 디버깅한다는 건 AI 에이전트(여기서는 Claude Code)를 사용해 코드를 읽고, 로그를 읽고, 실행 경로를 따라가며 버그의 근본 원인을 조사하는 것이지, 단지 고칠 스니펫을 제안하게 하는 게 아니에요. 차이는 당신이 부여하는 역할에 있어요. "이 버그 좀 고쳐줘"라고 부탁하는 게 아니라, AI에게 조사관의 일을 맡기는 거예요. "왜 망가졌는지 밝혀내"라고요.

대부분의 가이드가 건너뛰는 가장 중요한 점은 증상근본 원인의 구분이에요. 스택 트레이스는 프로그램이 어디서 무너졌는지만 보여줄 뿐, 예외를 던지는 곳은 보통 버그가 있는 곳이 아니에요. 뷰 계층에서 터지는 NullPointerException이, 필터 조건이 빠져서 null을 반환한 리포지토리 쿼리까지 세 파일 떨어진 곳으로 거슬러 올라갈 수 있어요. 마지막 에러 줄만 붙여넣고 수정을 요청하면, AI는 "증상에 패치"를 해요. 크래시가 난 바로 그 자리에 null 체크를 추가하는 거죠. 에러는 화면에서 사라지지만, 잘못된 데이터는 그 아래에서 계속 흘러가고, 결국 다른 어딘가에서 또 터져요.

제대로 된 AI 디버깅은 AI가 증상에서 원천으로 거슬러 올라가 가설을 세우고, 코드 속 증거와 대조해 검증한 뒤에야 비로소 수정을 제안하게 해요. 이건 추측이 아니라 조사예요. 이 접근이 더 큰 그림에서 어디에 들어맞는지 보려면 AI를 활용한 vibe coding 워크플로를 읽어보세요.

왜 Claude Code는 근본 원인을 잘 찾나요?

근본 원인 분석에서 Claude Code의 강점은 채팅창에 붙여넣은 스니펫이 아니라 코드베이스 전체를 다루는 데서 나와요. Anthropic의 Claude Code 문서(2026년 8월 접속)에 따르면, 이 에이전트는 스스로 파일을 읽고, 리포지토리를 검색하고, 명령을 실행할 수 있어요. 즉, 좁은 하나의 뷰에 갇히지 않고 컨트롤러에서 서비스로, 리포지토리로 여러 파일을 가로질러 버그를 추적할 수 있다는 뜻이에요.

구체적으로, 원인을 쫓을 때 Claude Code가 잘하는 게 세 가지 있어요.

  • 계층을 가로질러 실행 경로를 추적해요. 스택 트레이스를 주면 그 트레이스에 있는 파일을 스스로 열고, 함수들이 어떻게 서로 호출하는지 읽고, 데이터가 지나간 경로를 재구성해요. 원래라면 탭을 오가며 손으로 해야 할 일이죠.
  • 미묘하고 여러 계층에 걸친 버그를 잡아내요. 실수로 변경된 변수, 잘못된 순서로 실행되는 비동기 조건, DB 스키마와 코드 속 모델의 불일치 같은 것들을, Claude Code는 양쪽 끝을 다 읽기 때문에 나란히 맞춰볼 수 있어요.
  • 격리된 컨텍스트에서 조사해요. 버그 추적을 별도의 세션이나 subagent에 맡기면, 메인 대화가 수십 줄의 로그에 파묻히지 않아요.

게다가 Claude Code는 명령을 실행할 수 있어서 조사 루프를 스스로 닫을 수 있어요. 변경을 시도하고, 재현 테스트를 다시 돌리고, 결과를 읽고, 새 증거를 바탕으로 가설을 조정하는 거죠. 텍스트로만 답하는 어시스턴트와는 큰 차이예요. 그저 추측하는 대신 검증할 수 있으니까요.

공정하게 말하자면, "코드베이스 전체를 읽을 수 있다"가 "항상 옳다"를 뜻하진 않아요. 특히 컨텍스트가 얕거나 트레이스가 잘려 있을 때, Claude Code는 그럴듯하지만 틀린 원인을 제안할 수 있어요. 진짜 힘은 코드로 가설을 증명하게 강제할 때 비로소 드러나요. 아래 섹션에서 그 방법을 보여드릴게요.

AI로 디버깅하기 전에 준비할 것

AI 디버깅 세션이 실패하는 건 보통 AI가 "나빠서"가 아니라 입력이 얕았기 때문이에요. 세션을 열기 전에 이 체크리스트를 훑어보세요.

  • 버그를 재현할 수 있어야 해요. 버그를 안정적으로 나타나게 하는 명령, 테스트, 또는 특정 클릭 순서가 필요해요. "가끔만 일어나는" 버그는 훨씬 어려우니, 먼저 일관되게 터지게 하는 방법을 찾으세요.
  • 전체 스택 트레이스나 완전한 로그가 있어야 해요. 마지막 한 줄이 아니라 호출 프레임이 담긴 트레이스 전체 말이에요. 이게 AI가 거슬러 올라갈 지도예요.
  • 테스트/명령 실행을 허용하세요. Claude Code가 테스트 스위트나 재현 명령을 실행하게 해서 추측 대신 스스로 검증하게 하세요. 아직 설정하지 않았다면 Claude Code 설치 가이드를 참고하세요.
  • 기대하는 동작을 알고 있어야 해요. "X를 반환해야 하는데 Y가 나오고 있다"라고 적어 두세요. 올바른 기준점이 없으면 비교할 대상이 없어요.

Claude Code로 근본 원인을 찾는 6단계

이건 제가 몇 번이고 반복하는 워크플로예요. "AI에게 버그를 고쳐달라"와의 차이는 코드에 손대기 전에 두는 가설 검증 단계에 있어요.

1단계: 버그를 재현하고 전체 스택 트레이스를 확보하기

버그를 유발하는 명령을 실행하고 마지막 한 줄이 아니라 전체 트레이스를 복사하세요. 프레임이 많을수록 AI의 단서도 늘어나요. 버그가 UI를 통해서만 나타난다면, 터미널에서 안정적으로 터지도록 작은 재현 스크립트를 작성하세요. 더 빠르고, 수정 후 다시 실행할 안정적인 기준점을 AI에게 줄 수 있어요. 버그를 유발하는 입력값(페이로드, 파라미터)도 포함해 AI가 데이터를 추측하지 않게 하세요.

npm test -- users.spec.ts
# or run the reproduction script directly
node scripts/reproduce-bug.js

2단계: 전체 컨텍스트를 읽히기

전체 스택 트레이스를 Claude Code에 붙여넣고 관련 파일을 가리키세요. 어떤 파일인지 AI가 추측하게 두지 말고 길을 보여주세요. 기대 동작과 실제 동작의 설명("합계는 양수여야 하는데 음수가 나온다")을 포함하면 AI에게 기준점이 생겨요. 버그가 데이터와 관련 있다면 샘플 레코드나 스키마를 붙여넣으세요. AI가 코드와 실제 데이터를 맞춰볼 수 있으면 탐색 범위가 훨씬 빨리 좁혀져요.

Here is the full stack trace (pasted verbatim). The bug shows up when
calling POST /orders. Relevant files: src/orders/order.service.ts,
src/orders/order.repository.ts, src/payments/payment.client.ts.
Don't change anything yet - read first.

3단계: "먼저 조사하고, 편집하지 말라"

이게 결정적인 지시예요. AI를 "패치" 모드에서 "조사" 모드로 전환하게 강제하는 거죠. 어떤 변경을 제안하기 전에 코드를 읽고, 흐름을 설명하고, 의심스러운 지점을 짚게 하세요. 이 단계가 없으면 AI는 처음 눈에 띈 수상한 줄을 고치려 들어요. 가능성이 높은 순으로 가설 2~3개를, 각각 증거가 되는 코드 한 줄과 함께 나열하게 하세요. 그러면 AI가 실제 코드에 근거 없이 추측하고 있을 때 곧바로 드러나요.

4단계: 근본 원인 가설을 검증하기

AI가 원인을 내놓아도 곧바로 믿지 마세요. 5 Whys(바닥에 닿을 때까지 "왜"를 반복해 묻기) 방법을 사용하고, 각 단계마다 코드 속 구체적인 증거를 요구하세요. 까다로운 리그레션이라면, 버그를 유입시킨 커밋을 짚어내기 위해 git bisect를 설정하도록 AI에게 요청하세요.

Why is `total` negative? Show me the exact line that assigns that value,
and where the input value comes from. Prove it with code, don't speculate.

5단계: 재현 테스트와 함께 가장 작고 안전한 수정을 적용하기

근본 원인이 명확해지고 증거로 뒷받침되면, 실제 원인을 다루는 가장 작은 수정을 요청하세요. 묶음 리팩터링도, "온 김에" 하는 정리도 없이요. 수정이 작을수록 diff는 리뷰하기 쉽고, 새 버그를 낳을 가능성도 줄어요. 동시에 버그를 재현하는 테스트를 작성하세요. 그 테스트는 수정 전에 실패하고 수정 후에 통과해야 해요. 진짜 근본 원인을 짚었지 그저 운이 좋았던 게 아니라는 객관적인 증거죠. 한 걸음 더 나아가 테스트가 수정을 이끌게 하고 싶다면, AI와 함께하는 TDD 가이드를 보세요.

6단계: 실패 패턴을 기록하기

수정 후에는 프로젝트의 CLAUDE.md 파일에 그 패턴을 적어 두세요. 예를 들어 "tenantId가 없으면 리포지토리가 null을 반환한다. 항상 테넌트 필터를 확인할 것"처럼요. 다음번에 AI는 그 메모를 읽고 같은 함정을 피해요. 이렇게 모든 디버깅 세션을 코드베이스의 지속적인 자산으로 바꾸는 거예요.

실제 디버깅 세션: 스택 트레이스에서 근본 원인까지

이건 최근의 실제 사례로, "어디서 실패하는가"가 "버그가 있는 곳"이 아님을 보여줘요. POST /orders API가 이따금 음수 합계를 반환했어요. 스택 트레이스는 크래시가 나지 않고, 결제 계층에서 경고만 로그로 남겼어요. amount 값이 유효하지 않다고요. 첫 본능은 그 결제 클라이언트에 바로 if (amount < 0) amount = 0을 추가하는 거예요. 그게 바로 증상에 패치를 붙이는 거죠.

패치를 붙이는 대신, 저는 전체 로그를 붙여넣고 조사를 강제했어요. Claude Code는 결제 클라이언트에서 주문 서비스로, 주문 리포지토리로 거슬러 읽어가며 이렇게 짚었어요. 만료된 할인 코드가 리포지토리에서 걸러지지 않아, 오래된 할인 항목이 부호가 뒤집힌 채 장바구니에 여전히 추가되고 있었다고요. 근본 원인은 경고가 로그된 곳에서 두 계층 떨어진 리포지토리 계층에 있었어요. 가장 작은 수정은 할인 쿼리에 expired = false 필터를 추가하는 것이었지, 결제 클라이언트에서 값을 클램프하는 게 아니었어요.

솔직히 한 가지 덧붙이자면, 첫 실행에서 Claude Code는 하마터면 잘못된 길로 갈 뻔했어요. 서비스 계층에 원인(숫자 반올림)이 있다고 제안했고, 그게 무척 그럴듯하게 들렸거든요. 실제 데이터로 그걸 증명하게 만들고 나서야(4단계) 가설이 무너졌고, 마침내 리포지토리까지 추적해 내려갔어요. 그래서 검증 단계는 건너뛸 수 없어요.

기록할 가치가 있는 교훈은 이거예요. 경고가 로그되는 곳은 결과가 표면에 드러나는 곳이지, 원인이 태어나는 곳이 아니에요. 만약 그날 결제 클라이언트에 바로 패치를 붙였다면, 청구 합계는 맞아 보였겠지만 만료된 할인 레코드는 여전히 장바구니에 잘못 남아 나중에 매출 보고서를 왜곡했을 거예요. 원래 로그 한 줄보다 훨씬 비싼, 조용한 버그죠.

/debug와 subagent로 컨텍스트를 격리하기

디버깅 세션은 많은 "소음"을 만들어요. 수십 줄의 로그, 수많은 파일 읽기. 기능을 만드는 대화에 그걸 섞으면 메인 컨텍스트가 희석되고 답변 품질이 떨어져요. 해법은 조사를 격리하는 거예요.

Claude Code에서는 커스텀 슬래시 명령을 정의하고 전용 subagent에 작업을 넘길 수 있어요. 위 6단계 워크플로(먼저 조사, 근본 원인 증명, 가장 작은 수정 제안)를 담은 프롬프트로 프로젝트 고유의 /debug 명령을 만들어 필요할 때 호출할 수 있어요. 또는 버그 추적 전체를 전용 디버그 subagent에 넘기면, 별도 컨텍스트에서 동작하며 간결한 결론을 돌려주니 메인 세션은 깨끗하게 유지돼요.

이중의 이점이 있어요. 컨텍스트가 로그로 오염되지 않고, 버그마다 프롬프트를 다시 타이핑하는 대신 표준 워크플로 하나를 재사용할 수 있어요. 실용적인 팁: 조사 중에는 디버그 subagent를 읽기 전용으로 두고, 근본 원인 결론을 승인한 뒤에야 편집 권한을 여세요. 그래야 "조사" 부분과 "수정" 부분이 3단계의 정신에 맞게 뚜렷이 분리되고, 실제 변경을 일으키는 버튼을 누르는 건 늘 당신 자신이 돼요.

효과적인 디버깅 프롬프트(복사해서 바로 사용)

이건 제가 재사용하는 프롬프트 모음이에요. 복사해서 대괄호 부분을 바꾸고 Claude Code에 붙여넣으세요.

# 1. Investigate first, don't edit
Read [the files] and explain the flow that leads to the error in this
stack trace: [paste full trace]. DO NOT change anything. Just list 2-3
root-cause hypotheses, ranked by likelihood, each with a line of code
as evidence.

# 2. Trace the root cause
Walk backward from where the error fires to its source. For each step,
answer "why" (5 Whys) and quote the exact line of code that proves it.
Stop when you reach a cause you can no longer ask "why" about.

# 3. Propose the smallest safe fix
The root cause is confirmed to be [X]. Propose the SMALLEST change that
fixes this exact cause. No bundled refactor. Include 1 test that
reproduces the bug.

# 4. Explain why the bug happened
Summarize in 3 sentences: what the bug is, where the root cause is, and
why this fix is safe - so I can note it in CLAUDE.md.

AI로 디버깅할 때 흔한 실수

  • 첫 수정을 믿어 버리기. 첫 제안은 대개 증상에 패치를 붙여요. 항상 "이게 근본 원인인가, 아니면 에러가 터지는 곳일 뿐인가?"라고 물으세요.
  • 트레이스를 일부만 붙여넣기. 마지막 에러 줄만 주면 지도가 끊겨서 AI가 추측할 수밖에 없고, 그래서 틀려요.
  • 원인이 명확해지기 전에 AI가 고치게 두기. 눈감고 하는 수정은 버그를 가리거나 다른 어딘가에 새 버그를 낳을 수 있어요.
  • AI가 원인을 환각할 가능성을 무시하기. AI는 매우 자신 있게 들리지만 틀린 추론의 사슬을 만들 수 있어요. 바로 그래서 코드로 증명하게 하는 거예요.
  • 재현 테스트를 작성하지 않기. 안전망 없이 수정을 내보내면, 버그는 몇 스프린트 뒤에 아무도 모르게 돌아와요.

이 중 많은 부분이 Claude Code의 흔한 오류와 겹쳐요. 걸려 넘어지지 않으려면 읽어 둘 가치가 있어요. 보안 관련 버그는 전용 Claude Code 보안 감사 워크플로로 따로 떼어 내세요.

미리 만들어진 근본 원인 skill로 디버깅 속도를 높이기(AgentKit)

6단계 워크플로를 매번 다시 타이핑하고 싶지 않다면, AgentKit Engineer Kit에는 바로 이 사고방식을 담은 체계적인 디버그 skill이 들어 있어요. 패치로 곧장 뛰어드는 대신, 수정을 제안하기 전에 근본 원인의 증명을 강제해요. Claude Code보다 "더 똑똑한" 건 아니에요. 그저 조사의 규율을 표준화해 검증 단계를 잊지 않게 해주는 거죠. Engineer Kit의 가격은 $99예요(사이트에 반복 요금 언급은 없어요). 이 글의 워크플로가 당신의 방식과 맞는다면, Claude Code용 Engineer Kit 확인하기 — 20% 할인, 지금 $79.20로 바로 사용을 시작할 수 있어요.

자주 묻는 질문(FAQ)

AI가 스스로 근본 원인을 고치나요?

자동으로는 아니에요. 전체 스택 트레이스를 주고, 올바른 파일을 가리키고, 고치기 전에 조사하게 강제하면 AI는 올바른 원인을 추적할 수 있어요. 검증 단계를 건너뛰면 대개 근본이 아니라 증상에 패치를 붙여요.

스택 트레이스는 AI에게 얼마나 붙여넣어야 하나요?

마지막 한 줄이 아니라 트레이스 전체를 붙여넣으세요. 위쪽 호출 프레임이 AI가 원천까지 거슬러 올라가는 지도예요. 실패 순간 주변의 로그와 그것을 재현하는 명령도 함께 넣으세요.

AI로 디버깅하는 것과 ChatGPT를 쓰는 건 어떻게 다른가요?

ChatGPT는 보통 채팅창에 붙여넣은 스니펫만 읽어요. Claude Code는 프로젝트 안에서 동작하는 에이전트예요. 스스로 파일을 열고, 리포지토리를 검색하고, 테스트를 실행하죠. 그래서 좁은 컨텍스트에서 추측하는 대신 여러 파일을 가로질러 버그를 추적할 수 있어요.

Claude Code는 Windows에서 디버깅할 수 있나요?

네. ak CLI와 Claude Code는 Windows, macOS, Linux에서 네이티브로 동작해요. 이 글의 6단계 워크플로는 운영체제에 의존하지 않아요. 바뀌는 건 버그를 재현하는 명령이 당신의 스택에 따라 달라지는 것뿐이에요.

AI가 고치다가 제 코드를 망가뜨릴 수 있나요?

원인이 명확해지기 전에 AI가 고치게 두면 그런 위험이 있어요. 가장 작은 수정을 요청하고, 받아들이기 전에 diff를 꼼꼼히 리뷰하고, 안전망으로 재현 테스트를 늘 유지하면 위험을 줄일 수 있어요.

여러 파일에 걸친 버그에는 어떤 도구가 가장 좋나요?

계층을 넘나드는 버그(컨트롤러에서 서비스로, 리포지토리로)에는 Claude Code처럼 코드베이스 전체를 읽을 수 있는 에이전트가 필요해요. 붙여넣은 스니펫만 받는 도구는 파일 사이의 조각들을 잇는 데 애를 먹어요.

결론과 다음 단계

한 줄 요약: 근본 원인을 먼저 찾고, 수정은 그다음. AI로 디버깅하는 힘은 빠른 패치를 요청하는 데 있지 않고, Claude Code를 조사관으로 바꾸는 데 있어요. 조사하게 하고, 가설을 증명하게 하고, 그런 뒤에야 테스트와 함께 가장 작은 수정을 적용하는 거죠. 수정 후에는 AI에게 코드를 리뷰하게 하고, 리그레션을 막기 위해 테스트를 먼저 쓰는 TDD 방식을 고려해 볼 가치가 있어요. 이 규율을 바로 쓸 수 있는 워크플로로 표준화하고 싶다면, AgentKit을 시도해 보세요(링크로 20% 할인).

J

Jasmine

작성자 · Jasmine Daily

Jasmine Daily를 써 내려가는 사람 - 생각과 경험, 그리고 하루하루의 순간을 적어 두어요. 솔직하고, 서두르지 않고, 완벽하지 않게.

Jasmine Daily

아직 읽을 이야기가 더 있어요.

이 글이 마음에 닿았다면, 일기의 다른 페이지들도 몇 장 넘겨 보세요.

다음 읽을거리

관련 글