초보자를 위한 AI 생성 코드 디버깅 방법

발행: (2026년 6월 11일 AM 02:58 GMT+9)
13 분 소요
원문: Dev.to

Source: Dev.to

30초 만에 Claude로 기능을 생성했습니다. 컴파일도 되고, 배포도 했죠. 그런데 프로덕션에서 뭔가가 깨졌습니다.
이제 오류 트레이스백을 바라보며 끔찍한 사실을 깨닫게 됩니다. “코드가 실제로 뭘 하는지 전혀 모르겠어.”

이 현상을 **‘바이브 코딩(vibe coding)’**이라고 부릅니다. AI 시대에 코딩을 배우는 사람들의 대표적인 함정이죠. 즉시 동작하는 코드를 만들 수 있지만, 문제가 생기면 완전히 길을 잃게 됩니다. 이해하지 못하는 코드를 디버깅할 수는 없으니까요.

본능적으로 오류를 Claude나 ChatGPT에 붙여넣고 제안된 코드를 바로 실행하고 싶어집니다. 하지만 그건 잘못된 선택입니다. 패치를 또 다른 패치로 겹쳐가며 코드베이스가 유지보수 불가능해질 때까지 이어지는 악순환에 빠지게 됩니다. 다른 접근법이 필요합니다.

전통적인 디버깅은 **‘내가 코드를 썼다’**는 전제에 기반합니다. 무엇을 하려 했는지 기억하고, 제어 흐름을 이해하며, 머리 속으로 실행 경로를 추적할 수 있죠.

AI가 만든 코드는 이 전제가 모두 깨집니다. 마치 누군가가 만든 코드를 읽는 듯, 왜 존재하는지에 대한 정신 모델이 없습니다. 설계 선택조차 파악하지 못합니다.

연구자들이 **‘추측에 의한 디버깅(debugging by guessing)’**이라고 부르는 현상이 여기서 발생합니다. 코드가 실패하고 오류 메시지를 보면 바로 LLM에 붙여넣어 제안된 패치를 적용합니다. 가끔은 통하지만, 대부분은 다른 곳에 새로운 오류를 낳습니다.

LLM은 **‘국부적인 해결’**에 최적화돼 있을 뿐, **‘전역적인 이해’**를 제공하지 못합니다. 증상을 고치면서 원인을 무시하고, 여러 차례 반복하면 중복 검사, 잡아먹힌 예외, 얽힌 로직이 쌓여 상황은 더욱 악화됩니다.

그 대가가 나중에 드러납니다. 시스템을 수정해야 할 때, 미묘한 버그가 나타날 때, 기존 코드와 상호작용하는 새로운 기능을 추가하려 할 때 말이죠. 그 순간 **‘이해가 필요한 마지막 10% 작업’**이 불가능해집니다.

AI가 만든 코드가 실패하자마자 떠오르는 유혹은 똑같습니다. 오류를 복사하고 Claude에 붙여넣어 수정을 실행하는 것.

그걸 억제하세요.

이 워크플로우는 **‘생산적인 고통(productive struggle)’**을 회피하게 만듭니다. 문제와 마주해 스스로 해결하려는 인지적 마찰을 없애면 학습 자체가 단축됩니다.

Anthropic 연구에 따르면, AI를 이용해 코드를 생성한 개발자는 수동으로 코딩한 사람보다 이해도 테스트 점수가 17% 낮다고 합니다. 생산성은 느끼고, 기능을 빠르게 배포하지만, 유지보수할 수 없는 코드베이스를 만들게 됩니다.

역동성을 뒤집어 보세요. AI에게 코드를 고치라고 하지 말고, 왜 실패하는지 스스로 이해하도록 도와달라고 요청합니다.

이것을 **소크라테스식 디버깅(Socratic debugging)**이라고 부릅니다. 오류를 붙여넣고 해결책을 받아들이는 대신, AI를 **‘스스로 진단하도록 유도하는 사고 파트너’**로 활용하는 것이죠.

실제 적용 방법은 다음과 같습니다. 코드가 실패했을 때 오류를 붙여넣지 말고, 정확한 프롬프트를 작성합니다.

I'm getting this error. Don't write any code. Instead, ask me clarifying questions to help me locate the bug myself.

이제 AI는 튜터가 됩니다. 코드가 해야 할 일을 물어보고, 여러분의 정신 모델을 점검하며, 실패 지점을 좁혀갑니다. 여러분은 생각하고, AI는 추론을 스캐폴딩(scaffolding) 합니다.

또 다른 강력한 방법: 디버깅에 들어가기 전에 AI에게 **‘코드가 무엇을 하는지 설명해 달라’**고 요청합니다.

Read this generated block of code and describe its execution path in plain English. Do not write any code.

AI가 로직을 말로 풀어내면, 실제 동작과 여러분이 생각한 동작 사이의 차이를 쉽게 발견할 수 있습니다.

또는 ‘엣지 케이스’를 찾아 달라고 물어보세요.

Identify potential edge cases and failure modes that could break this function. Do not write code.

이렇게 하면 코드를 방어적으로 생각하게 되고, “잘 동작한다”는 가정을 버릴 수 있습니다.

핵심은 **‘AI가 코드를 쓰는 것을 제한’**하는 것입니다. 그러면 AI는 **‘생각 도구’**가 되고, 코드 생성기가 아니라 사고 파트너가 됩니다.

AI에게 무언가를 생성하도록 요청하기 전에 구조를 잡아두세요.

  • 복잡한 기능을 작고 격리된 모듈로 나누고, 파일과 폴더 경계를 명확히 합니다.
  • 인터페이스를 고정하기 위해 계약 테스트(contract tests) 를 작성해 입력·출력을 고정합니다.
  • 그런 다음 AI에게 명령합니다.
Work only in this file. Do not modify other files. Do not create new helper functions.

이렇게 하면 AI가 여러 파일에 중복 코드를 만들거나, 한 영역의 변경이 다른 곳에 은밀히 영향을 주는 일을 방지하고, 아키텍처적 통제를 유지할 수 있습니다.

이 방식을 컴포넌트화된 사고(componentized thinking) 라고 부르며, AI가 만든 코드를 유지보수 가능하게 만드는 핵심 전략입니다.

LLM과의 대화가 길어지면 컨텍스트 창(token context window) 이 포화됩니다. 모델은 초기 메시지를 압축하고, 폴더 구조를 잊고, 변수명을 바꾸며, 존재하지 않았던 함수를 환각합니다.

이때는 새로운 채팅을 시작하는 것이 생산적입니다.

새로운 대화를 시작하기 전에, AI에게 현재 진행 상황을 마크다운 파일에 정리하도록 시키세요. 무엇이 작동하고, 무엇이 미해결이며, 어떤 시도를 했는지 적어두고, 그 요약을 새 세션에 붙여넣습니다.

더 나아가 레포지토리 자체에 체계적인 문서를 유지하세요.

  • vision.md : 핵심 기능과 사용자 흐름을 설명
  • ConnectionGuide.txt : 포트, DB URI, API 엔드포인트 등 모든 연결 정보를 기록

새로운 채팅을 시작할 때는 이 파일들을 가리키게 하면, 모든 것을 다시 설명할 필요가 없습니다.

핵심 진실: AI는 사고를 안내할 수 있지만, 실행 중인 코드를 직접 볼 수는 없습니다.

LLM은 정적 코드만 분석합니다. 런타임 상태를 관찰하지 못하므로, 실제 실행 오류를 디버깅할 때는 불완전한 정보만 가지고 작업하게 됩니다. 따라서 실제 도구가 필요합니다.

Python을 사용한다면 Python TutorThonny 같은 도구로 한 줄씩 실행 흐름을 살펴보고 변수와 콜 스택을 확인하세요. 시각적인 실행 경로는 코드를 읽는 것보다 훨씬 명확합니다.

시스템 수준 문제라면 직접 진단 명령을 실행합니다. 파일 동기화가 멈췄다면 lsof 로 파일 디스크립터를 확인하고, ps 로 프로세스를 살피며, netstat 로 네트워크 연결을 점검합니다. AI에게 진단 계획을 제안받고, 실제 명령을 직접 실행해 결과를 검증하세요.

전략적 AI + 전술적 실제 도구 조합이 단독 사용보다 훨씬 강력합니다.

학생 학습에 관한 연구에서도 흥미로운 결과가 나옵니다. 학생들에게 **‘코드를 다른 사람에게 설명해야 한다’**는 과제를 주면, 학습 방식이 달라진다는 것입니다.

대학 CS 강좌에서 AI 접근을 자유롭게 한 학생들이 구술 인터뷰에서 코드를 방어하도록 요구받을 때, 성과가 크게 향상되었습니다. 이유는 ‘방어’를 준비하면서 실제로 코드를 이해하게 되기 때문입니다. 코드를 공부하고, 테스트하고, 설명을 준비하게 됩니다.

이러한 책임 메커니즘은 실제 사람 없이도 스스로 만들 수 있습니다. 코드를 커밋하기 전에 짧은 설명을 적어보세요.

  • 이 코드는 무엇을 하는가?
  • 왜 이 문제가 해결되는가?
  • 어떤 상황에서 깨질 수 있는가?

이 질문에 명확히 답하지 못한다면, 아직 충분히 이해하지 못한 것입니다.

이 훈련은 코드를 스키핑(skiing)하지 않고 직접 마주하도록 강제합니다.

AI는 디버깅에 정말 유용합니다. 진단 접근법을 제시하고, 실패 원인을 설명하며, 테스트 케이스를 생성해 줍니다. 하지만 성공적인 개발자는 AI를 ‘사고 파트너’ 로 활용합니다.

  • 코드베
0 조회
Back to Blog

관련 글

더 보기 »

Eidentic 소개

Today we're releasing Eidentic, an open-source TypeScript SDK for building AI agents with self-improving memory and the production fundamentals built in — not b...

Typescript의 타입

Introdução Tipos são uma forma de definir a “forma” ou o contrato dos dados que estamos usando no código. Pensando em Javascript puro, ele é dinâmico: você pode...