나 혼자 산다. 바이브코딩과 함께

나 혼자 산다. 바이브코딩과 함께. 15장

djai 2026. 4. 5. 12:09
반응형

15. 디버깅도 바이브로오류를 두려워하지 않는 법

Part 5: 바이브 코딩 고급편

15.1 에러 메시지는 적이 아니다

프로그래밍을 하다 보면 에러 메시지를 만나게 됩니다. 많은 초보자들은 에러 메시지를 보면 불안감을 느낍니다. 하지만 에러 메시지는 실제로 당신의 친구입니다. 에러 메시지는 무엇이 잘못되었는지 정확히 알려주는 유일한 선물입니다. 에러 메시지 없이는 당신의 프로그램이 무엇이 잘못되었는지 알 수 없을 것입니다.

에러 메시지는 세 가지 정보를 제공합니다. 첫째, 무엇이 잘못되었는가입니다. 예를 들어 'Uncaught TypeError: Cannot read property of undefined'라는 메시지는 어떤 변수가 존재하지 않는다는 의미입니다. 둘째, 어디에서 잘못되었는가입니다. 대부분의 에러 메시지는 파일명과 줄 번호를 포함합니다. 셋째, 대략 왜 그런 일이 발생했는가입니다. 에러 메시지는 종종 힌트를 제공합니다.

에러 메시지를 읽을 때는 느낌이 아니라 정보를 추출해야 합니다. 전체 메시지를 읽으세요. 많은 개발자가 첫 줄만 읽고 포기합니다. 하지만 에러 메시지는 보통 길고, 뒤에 더 유용한 정보가 있습니다. 특히 스택 트레이스(stack trace)는 에러가 발생한 경로를 보여줍니다. 어느 함수에서 어느 함수를 호출했고, 최종적으로 어디서 에러가 발생했는지 추적할 수 있습니다.

에러 메시지를 보면 감정적으로 반응하지 마세요. 에러는 프로그래밍의 정상적인 부분입니다. 모든 개발자, 심지어 가장 숙련된 개발자도 매일 에러를 만납니다. 차이는 에러를 얼마나 빨리 해결하느냐입니다. 당신이 초보자일 때는 에러 해결이 더 걸릴 것입니다. 그것은 정상입니다. 계속하면 더 빨라질 것입니다.

  에러 메시지 읽는 법

  1) 감정적 반응하지 않기. 2) 전체 메시지 읽기. 3) 파일명과 줄 번호 찾기. 4) 스택 트레이스 따라가기. 5) AI에게 물어보기 전에 먼저 이해해보기.

 

15.2 AI에게 오류 해결 요청하는 프롬프트 공식

AI에게 에러를 해결해달라고 요청할 때는 특정 공식이 있습니다. 첫 번째는 에러 메시지 전체를 복사-붙여넣기하는 것입니다. 간단히 설명하지 마세요. 정확한 에러 메시지를 AI에게 제시해야 합니다. 두 번째는 관련 코드를 제시하는 것입니다. 에러가 발생한 부분의 코드를 보여주세요. 세 번째는 당신이 무엇을 하려고 했는지 설명하는 것입니다.

효과적인 프롬프트는 다음과 같은 형태입니다: '다음 에러가 발생했어: [에러 메시지]. 이 코드를 실행했을 때 나타나: [관련 코드]. 나는 [목적]을 하려고 했어.' 이렇게 하면 AI는 정확히 무엇이 문제인지 파악할 수 있습니다.

또 다른 효과적인 방법은 재현 가능한 최소 예제(Minimal Reproducible Example, MRE)를 제시하는 것입니다. 전체 프로젝트를 보여주지 말고, 에러를 유발하는 가장 간단한 코드만 보여주세요. 이렇게 하면 AI가 더 빨리 문제를 파악할 수 있습니다.

에러가 해결되면, AI의 해결책이 왜 작동하는지 이해하려고 노력하세요. 단순히 코드를 복사-붙여넣지 마세요. AI의 설명을 읽고, 이해가 안 되면 더 물어보세요. 이렇게 해야 같은 에러가 다시 발생했을 때 스스로 해결할 수 있습니다.

  에러 해결 프롬프트 템플릿

  다음 에러가 발생했어: [에러 메시지 전체 복사]. 이 코드에서 나타나: [관련 코드]. 나는 [하려던 작업]을 하려고 했는데 실패했어. 뭐가 잘못된 거야?

 

15.3 콘솔과 로그: 프로그램의 속마음

console.log()는 프로그래머의 가장 중요한 도구 중 하나입니다. 이것을 사용하면 프로그램이 어느 시점에 있는지, 변수에 어떤 값이 들어있는지 알 수 있습니다. 데이터가 예상과 다를 때, console.log()를 사용해서 변수의 값을 확인하세요.

console.log() 사용법은 매우 간단합니다. 'console.log(변수);'라고 하면 그 변수의 값을 콘솔에 출력합니다. 여러 값을 동시에 출력할 수도 있습니다. 'console.log("userAge:", userAge, "userName:", userName);' 이렇게 하면, 어떤 값이 어떤 변수인지 명확하게 알 수 있습니다.

브라우저의 개발자 도구(Developer Tools)에서 콘솔 탭을 열 수 있습니다. 대부분의 브라우저에서는 F12 또는 우클릭 -> '검사'로 열 수 있습니다. 콘솔 탭에서 console.log() 결과를 볼 수 있습니다. 또한 콘솔에서 직접 JavaScript 코드를 실행할 수 있습니다. 이것은 매우 유용한 기능입니다.

console.log() 외에도 다른 콘솔 메서드가 있습니다. console.error()는 에러 메시지를 빨간색으로 표시합니다. console.warn()은 경고를 노란색으로 표시합니다. console.table()은 배열이나 객체를 표 형식으로 표시합니다. 이런 메서드들을 사용하면 디버깅이 더 쉬워집니다.

로그를 정리하는 것도 중요합니다. 프로덕션 환경(사용자가 사용하는 실제 환경)에서는 불필요한 console.log()를 모두 제거해야 합니다. console.log()가 많으면 성능에도 영향을 미치고, 사용자에게 혼란을 줄 수 있습니다. 개발할 때는 자유롭게 console.log()를 사용하되, 배포하기 전에 정리하세요.

  디버깅 팁

  console.log()의 좋은 습관: 1) 값뿐만 아니라 레이블도 함께 출력하기. 2) 중요한 지점에만 로그 남기기. 3) 배열이나 객체는 console.table()로 보기. 4) 프로덕션에 배포하기 전에 불필요한 로그 제거하기.

 

15.4 자주 발생하는 오류 유형과 해결 패턴

undefined 관련 에러

가장 흔한 에러 중 하나는 'Cannot read property of undefined' 또는 'Cannot access property of undefined'입니다. 이것은 존재하지 않는 변수의 속성에 접근하려고 했다는 의미입니다. 예를 들어 'user.name'에 접근했는데 user undefined라면 이 에러가 발생합니다.

이 에러를 해결하는 방법은 변수가 실제로 존재하는지 먼저 확인하는 것입니다. 'if (user && user.name) { ... }'라고 하면, user가 존재할 때만 name에 접근합니다. 또 다른 방법은 옵셔널 체이닝(optional chaining)을 사용하는 것입니다. 'user?.name'이라고 하면, user가 없으면 undefined를 반환하고 에러를 발생시키지 않습니다.

변수 타입 관련 에러

'Cannot read property ... of number' 같은 에러는 변수의 타입이 예상과 다를 때 발생합니다. 예를 들어 배열의 메서드를 숫자에 사용하려고 하면 에러가 발생합니다. JavaScript는 동적 타입 언어라서 이런 에러가 자주 발생합니다.

해결 방법은 변수의 타입을 먼저 확인하는 것입니다. 'typeof' 키워드로 타입을 확인할 수 있습니다. 'if (typeof data === "string") { ... }'라고 하면, data가 문자열일 때만 진행합니다. 또는 'Array.isArray()'로 배열 여부를 확인할 수 있습니다.

API와 네트워크 관련 에러

API 호출 중에 에러가 발생할 수 있습니다. 네트워크가 끊어졌을 수도, API 서버에 문제가 있을 수도 있습니다. 또는 API 키가 잘못되었을 수도 있습니다. 이런 에러를 처리하지 않으면 프로그램이 멈춥니다.

해결 방법은 try-catch 문을 사용하는 것입니다. 'try { // API 호출 } catch (error) { // 에러 처리 }'라고 하면, 에러가 발생해도 프로그램이 멈추지 않습니다. 그리고 에러 객체를 사용해서 무엇이 잘못되었는지 파악할 수 있습니다.

타임아웃 에러

작업이 너무 오래 걸리면 타임아웃 에러가 발생할 수 있습니다. 특히 큰 파일을 처리하거나, 느린 인터넷에서 데이터를 다운로드할 때입니다. 이것은 보통 시간 제한이 있는 작업에서 발생합니다.

해결 방법은 타임아웃 시간을 늘리거나, 작업을 더 효율적으로 만드는 것입니다. 예를 들어 대용량 파일을 처리할 때는 한 번에 처리하지 말고, 조각 단위로 처리하는 방법이 있습니다.

  에러 해결 체크리스트

  1) 에러 메시지를 정확히 읽었는가? 2) 에러가 발생한 줄을 확인했는가? 3) 변수가 존재하는가? 4) 변수의 타입이 맞는가? 5) 에러 처리가 있는가?

 

15.5 무한 루프에 빠졌을 때

무한 루프는 프로그래머들이 자주 만나는 악몽입니다. 루프가 멈추지 않으면 프로그램이 먹통이 됩니다. 무한 루프의 원인은 보통 루프 탈출 조건이 절대 참이 되지 않기 때문입니다.

예를 들어 'while (true) { console.log(i); }'라는 코드를 보면, 이것은 명백한 무한 루프입니다. i가 증가하지 않으므로 루프가 절대 끝나지 않습니다. 무한 루프는 의도적으로 만들어질 수도 있지만(이벤트 리스너 등), 대부분의 경우 버그입니다.

무한 루프를 방지하려면 먼저 루프 조건을 명확히 해야 합니다. 루프가 언제 끝나야 하는지 확실히 하세요. 반복 변수가 실제로 변하는지 확인하세요. 'i++' 같은 증가 또는 감소 연산이 있는지 확인하세요.

만약 무한 루프에 빠졌다면, 프로그램을 강제로 종료해야 합니다. 브라우저에서는 새로고침을 누르거나, 개발자 도구를 닫으면 됩니다. Node.js에서는 Ctrl+C를 누르면 됩니다. 그 후에 코드를 확인해서 루프 조건을 수정하세요.

AI에게 도움을 요청할 때는 루프 코드 전체를 보여주고, '이 루프가 언제 끝나야 하는가'를 명확히 설명하세요. AI는 루프 조건의 문제를 빨리 찾을 수 있을 것입니다.

  무한 루프 체크리스트

  1) 루프 조건이 명확한가? 2) 루프 변수가 증가 또는 감소하는가? 3) 언젠가는 루프 조건이 거짓이 되는가? 4) break 문이 있는가? 5) 의도적인 무한 루프인가?

 

15.6 디버깅의 체계적 접근법

에러를 만났을 때 절대 하면 안 될 일은 무작정 코드를 바꾸는 것입니다. 이렇게 하면 더 많은 문제가 생깁니다. 대신 체계적으로 접근해야 합니다.

단계 1: 문제 재현

먼저 문제를 다시 발생시켜야 합니다. 언제 에러가 발생하는가? 특정 입력일 때만 발생하는가? 항상 발생하는가? 문제를 명확히 이해하지 못하면 해결할 수 없습니다.

단계 2: 범위 좁히기

에러가 어디서 발생하는지 파악해야 합니다. 전체 프로그램이 아니라 특정 함수일 가능성이 높습니다. console.log()를 사용해서 프로그램의 흐름을 따라가세요. 어느 지점부터 잘못되는지 찾으세요.

단계 3: 가설 세우기

무엇이 문제인지 가설을 세우세요. '변수 x null이라서 그런 것 같아', '이 함수가 호출되지 않는 것 같아' 같은 가설입니다.

단계 4: 가설 검증

console.log() debugger를 사용해서 가설을 검증하세요. 변수가 정말 null인지 확인하세요. 함수가 호출되는지 확인하세요.

단계 5: 수정 및 테스트

가설이 맞으면 문제를 수정하세요. 수정 후에는 같은 에러가 다시 발생하지 않는지 확인하세요. 또한 다른 부분이 망가지지 않았는지도 확인하세요.

  디버깅 원칙

  1) 감정적이 되지 않기. 2) 체계적으로 접근하기. 3) 작은 부분부터 확인하기. 4) 검증 없이 수정하지 않기. 5) 수정 후 다시 테스트하기.

 

15.7 '작동은 하는데 왜 되는지 모르겠다'

때로는 코드가 작동하지만 왜 작동하는지 이해하지 못하는 경우가 있습니다. 이것은 특히 AI가 생성한 코드에서 발생하기 쉽습니다. 이 상황을 마주쳤을 때는 정직해지세요. '작동하니까 상관없다'고 넘어가면 안 됩니다.

이 경우 가장 좋은 방법은 AI에게 물어보는 것입니다. 'AI가 생성한 이 코드가 있어. 작동은 하는데 왜 이런 식으로 구현했는지 설명해줄 수 있어?'라고 요청하세요. AI는 코드를 생성한 이유를 설명할 수 있습니다.

또 다른 방법은 코드를 수정해보는 것입니다. 특정 부분을 제거하거나 바꿔보세요. 그러면 그 부분이 왜 필요한지 이해할 수 있습니다. 예를 들어 어떤 if 문을 제거했더니 프로그램이 망가진다면, if 문이 중요하다는 것을 알 수 있습니다.

또한 테스트를 만들어볼 수 있습니다. 여러 입력값으로 테스트해보세요. 어떤 입력일 때 작동하고, 어떤 입력일 때 작동하지 않는가? 이렇게 하면 코드가 어떻게 작동하는지 더 명확해집니다.

완전히 이해할 때까지 계속 파고드세요. 이것은 시간을 낭비하는 것이 아니라, 당신의 프로그래밍 실력을 쌓는 과정입니다. 당신이 지금 이해하지 못하는 패턴은 나중에 당신이 코드를 쓸 때 도움이 될 것입니다.

  이해하지 못하는 코드

  1) AI에게 설명 요청하기. 2) 코드 부분을 수정해보기. 3) 여러 입력값으로 테스트하기. 4) 온라인 자료 찾아보기. 5) 완전히 이해할 때까지 포기하지 않기.

 

15.8 이 장을 마치며

15장에서 우리는 디버깅, 즉 버그를 찾고 고치는 방법을 배웠습니다. 디버깅은 프로그래밍의 필수 부분입니다. 아무리 좋은 프로그래머도 버그를 만듭니다. 차이는 버그를 얼마나 빨리 찾고 고치느냐입니다.

에러 메시지는 당신의 적이 아니라 친구입니다. 에러 메시지는 무엇이 잘못되었는지 정확히 알려줍니다. 에러 메시지를 두려워하지 말고, 차분히 읽고 이해하세요. 그 다음 체계적으로 문제를 해결하세요.

AI도 디버깅을 도울 수 있습니다. 정확한 에러 메시지와 관련 코드, 그리고 당신의 목표를 명시하면, AI는 빠르게 문제를 찾을 수 있습니다. 하지만 AI의 해결책을 그대로 받아들이기보다는, 왜 그 해결책이 필요한지 이해하려고 노력하세요.

디버깅 능력은 연습을 통해 향상됩니다. 처음에는 간단한 버그를 고치는 데 1시간이 걸릴 수 있습니다. 하지만 계속하면, 같은 종류의 버그를 5분에 고칠 수 있을 것입니다. 당신은 점점 더 효율적인 디버거가 될 것입니다.

다음 장에서는 작은 프로젝트를 실제 서비스로 확장하는 방법을 배울 것입니다. 디버깅 능력은 이 과정에서 매우 중요할 것입니다. 프로덕션 환경에서는 버그가 실제 사용자에게 영향을 미치기 때문입니다. 그때까지 디버깅 능력을 계속 갈고닦으세요.

반응형