티스토리 뷰

반응형

바이브코딩 디버깅 대표 이미지 - AI 코드가 틀렸을 때

 

1~8편에서 Claude가 만든 코드는 대부분 한 번에 돌아갔지만, 사실 그 뒤에는 수많은 실패가 있었다. 화면이 하얗게 나오거나, 모델이 새까맣거나, 교량이 넘어져 있거나, 교각이 엉뚱한 각도로 누워 있는 경우다. AI가 만든 코드는 그럴듯하지만 틀릴 수 있다.

9편에서는 바이브코딩에서 가장 중요한 기술인 디버깅을 다룬다. 코드를 직접 다 읽지 않아도, 증상을 관찰하고 F12 콘솔을 읽고 AI에게 정확히 설명하면 대부분 한두 번 만에 고쳐진다. 자주 만나는 버그 6가지를 직접 재현해 보면서 그 방법을 정리한다.

 

이번 편에서 만들 것
 

▲ 실제로 동작하는 데모. 버튼을 누르면 해당 버그가 재현되고, 콘솔 메시지·원인·AI에게 보낼 말·고친 코드가 나온다.

 

○ 버튼마다 실제 버그를 넣은 코드로 장면을 다시 만든다. 화면만 보면 원인을 알기 어렵지만, 검은 콘솔 창의 메시지와 아래 크기 진단 그래프를 보면 단서가 보인다.

○ 크기 진단 그래프는 Box3로 잰 모델 크기와 기대 크기를 비교한다. ③ mm 버그는 크기가 1000배, ⑤ Z-up 버그는 높이와 폭이 뒤바뀐 것이 바로 드러난다. (그래프 범위를 넘는 막대는 잘라서 그리고 실제 값은 숫자로 표시)

 

디버깅 5단계

○ AI에게 "안 돼, 고쳐줘"라고만 하면 AI는 원인을 추측해서 엉뚱한 곳을 고친다. 고치는 일은 AI에게 맡기더라도, 무엇이 잘못됐는지 알아내는 일은 사람이 순서대로 해야 한다.

 

디버깅 5단계 - 재현, 관찰, 범위 좁히기, AI에게 전달, 검증

 

단계 할 일 구체적으로
① 재현 같은 조작으로 다시 일어나는지 확인 새로고침(Ctrl+F5) 후에도 같은지, 특정 값에서만 그런지
② 관찰 화면과 콘솔에서 정상과 다른 점 찾기 빈 화면 / 검은색 / 크기 / 방향 / 콘솔 빨간 줄
③ 범위 좁히기 어느 부분 코드 문제인지 좁히기 축·격자·경계 상자 헬퍼 켜기, 의심 부분 주석 처리
④ AI에게 전달 증상·오류 전문·기대 결과를 함께 추측한 원인과 고칠 범위까지 적기
⑤ 검증 고쳐졌는지, 다른 곳이 망가지지 않았는지 처음 재현 조작을 다시 해 보기

 

F12 콘솔 읽는 법

○ 브라우저에서 F12(맥은 Cmd+Option+I)를 누르고 Console 탭을 연다. 바이브코딩 디버깅의 절반은 여기서 끝난다. 빨간 줄은 실행이 멈춘 오류, 노란 줄은 경고다.

 

F12 개발자 도구 Console 탭 읽는 법

 

콘솔 메시지 (예) 뜻 흔한 원인
Uncaught SyntaxError: Unexpected token 문법 오류. 파일 전체가 실행 안 됨 괄호·따옴표 짝이 안 맞음, 코드 일부만 복사
Failed to resolve module specifier "three" import 이름을 못 찾음 importmap 누락, importmap이 module 스크립트보다 아래에 있음
GET ... 404 (Not Found) 파일 주소가 틀림 examples/js/ 경로(옛 버전), 버전 번호 오타
Cannot read properties of undefined 없는 객체의 속성을 읽음 변수 이름 오타, 만들기 전에 사용
THREE.Geometry is not a constructor 사라진 기능 사용 AI가 오래된 버전 코드를 줌
오류 없음 + 화면 이상 코드는 돌지만 값이 틀림 단위·좌표축·회전·카메라 설정 → 헬퍼로 확인

 

○ 오류 메시지는 요약하지 말고 전문을 그대로 복사해서 AI에게 준다. 메시지 오른쪽의 파일명:줄번호를 클릭하면 문제 줄로 바로 이동한다.

 

자주 만나는 버그 6가지

○ 데모에서 재현한 버그들이다. 앞의 4개는 콘솔에 오류가 없는 버그라서 더 찾기 어렵다. 코드는 정상으로 돌지만 값이 틀렸기 때문이다.

증상 원인 확인 방법 해결
① 배경색만 보임 카메라 far 값이 모델까지 거리보다 작음 카메라 거리 vs near/far 출력 far를 충분히 크게 (1000)
② 모델이 새까맣다 MeshStandardMaterial인데 조명 없음 scene.children에 Light 있는지 조명 추가, scene.add 확인
③ 모델이 너무 큼 치수를 mm로 입력 Box3 크기가 1000배 단위 m로 통일, 도면 값은 /1000
④ 부재가 비스듬함 회전에 도(degree)를 넣음 rotation 값이 90, 180 같은 큰 수 MathUtils.degToRad()
⑤ 교량이 넘어짐 CAD처럼 Z축이 위인 좌표 Box3에서 높이가 Z에 있음 (x, y, z) → (x, z, −y)
⑥ 하얀 화면 + 빨간 오류 import 경로·importmap 오류 콘솔 404 / module specifier importmap과 addons 경로 확인

 

디버깅 도우미: 헬퍼와 Box3

○ 콘솔에 오류가 없는데 화면이 이상하면, 눈에 보이는 기준을 장면에 추가한다. three.js에는 디버깅용 헬퍼가 기본으로 들어 있다.

const DEBUG = true;                                  // 배포할 때는 false
if (DEBUG) {
  scene.add(new THREE.AxesHelper(20));                // 빨강 X · 초록 Y · 파랑 Z (길이 20 m)
  scene.add(new THREE.GridHelper(200, 20));           // 200 m 범위, 10 m 간격 격자

  const bbox = new THREE.Box3().setFromObject(bridge);
  scene.add(new THREE.Box3Helper(bbox, 0xff7a1a));    // 모델 경계 상자 (주황)
  const size = bbox.getSize(new THREE.Vector3());
  console.log('모델 크기', size.x.toFixed(1), size.y.toFixed(1), size.z.toFixed(1));

  window.scene = scene;                               // F12 콘솔에서 scene 직접 조사
}
도우미 알 수 있는 것 이런 버그에
AxesHelper 원점 위치와 X·Y·Z 방향 Z-up 좌표, 부호 반대, 엉뚱한 원점
GridHelper 바닥 기준과 대략의 크기 (칸 = 10 m) 단위 오류, 모델이 땅속에 묻힘
Box3 + Box3Helper 모델 전체 크기와 범위 (숫자) mm·m 혼동, 일부 부재가 멀리 튐
mesh.name + console.table 부재별 위치를 표로 확인 한 부재만 위치가 틀린 경우
window.scene 콘솔에서 객체를 직접 조사 scene.children.length 등 즉석 확인

 

화면에 오류 띄우기

○ 태블릿이나 휴대폰에서는 F12를 열기 어렵다. 아래 코드를 <head>에 넣어 두면 오류가 화면 아래에 빨간 상자로 표시된다. module 스크립트보다 먼저 실행되는 일반 스크립트라서 import 오류도 잡는다.

<pre id="err" style="position:absolute;bottom:0;left:0;right:0;margin:0;display:none;
     background:rgba(120,0,0,.9);color:#fff;font:13px Consolas,monospace;padding:8px"></pre>
<script>
  function showErr(msg) {
    const box = document.getElementById('err');
    box.style.display = 'block';
    box.textContent += msg + '\n';
  }
  addEventListener('error', (e) => showErr('[error] ' + (e.message || e.target.src)), true);
  addEventListener('unhandledrejection', (e) => showErr('[promise] ' + e.reason));
</script>

 

AI에게 디버깅을 요청하는 법

○ 같은 버그라도 요청하는 방법에 따라 한 번에 고쳐지기도 하고, 열 번을 주고받아도 안 고쳐지기도 한다. 4편의 프롬프트 원칙을 디버깅에 그대로 적용한다.

 

AI에게 보내는 디버깅 요청 - 나쁜 요청과 좋은 요청 비교

 

요소 내용 예 (⑤ Z-up 버그)
증상 눈에 보이는 현상을 그대로 교량이 옆으로 넘어져 바닥판이 벽처럼 서 있다
기대 원래 어떻게 나와야 하는지 바닥판이 수평이고 Y축이 위
근거 콘솔 오류 전문, 출력한 값 Box3 크기 93.2 × 13.0 × 9.8
추측 짐작 가는 원인 (틀려도 됨) Z-up 좌표로 넣은 것 같다
범위 고칠 곳과 건드리지 말 곳 좌표 변환만 고치고 나머지는 그대로

 

○ 특히 "범위"가 중요하다. 범위를 정하지 않으면 AI가 버그와 상관없는 부분까지 다시 짜서, 잘 되던 기능이 망가지는 일이 생긴다.

 

AI가 같은 실수를 반복할 때
상황 해결
같은 수정을 계속 되풀이 새 대화를 열고 현재 전체 코드와 증상을 처음부터 다시 준다
코드가 길어 일부만 고쳐 옴 "수정한 함수 전체를 다시 보여줘" 또는 "전체 파일로 줘"
옛 버전 문법을 계속 씀 "three.js 0.186.1 기준, examples/js가 아닌 addons(jsm) 경로로"를 명시
원인을 못 찾음 버그가 있는 부분만 떼어 낸 최소 예제로 다시 질문
고칠수록 더 망가짐 마지막으로 잘 되던 버전으로 돌아가 한 번에 하나씩 변경

 

○ three.js는 버전이 자주 바뀐다. 예를 들어 THREE.Geometry는 r125에서 없어졌고, examples/js 폴더는 r148에서 없어졌다. AI가 이런 코드를 주면 버전을 알려 주고 다시 요청한다.

 

전체 코드

○ 디버깅 도우미가 모두 들어간 템플릿이다. 메모장에 붙여넣고 bridge9.html로 저장해 실행하면 축·격자·경계 상자와 함께 모델 크기·조명 수·카메라 거리가 왼쪽 위에 표시되고, 오류가 생기면 화면 아래에 빨간 상자로 나온다. 새 모델을 만들 때 이 파일에서 시작하면 디버깅이 쉬워진다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>three.js 디버깅 도우미 - 교량 모델</title>
  <style>
    body { margin: 0; overflow: hidden; }
    #err { position: absolute; left: 0; right: 0; bottom: 0; max-height: 40%; overflow: auto; margin: 0;
           background: rgba(120, 0, 0, 0.9); color: #fff; font: 13px Consolas, monospace; padding: 8px 12px; display: none; }
    #dbg { position: absolute; top: 10px; left: 10px; background: rgba(255,255,255,0.9); padding: 8px 12px;
           border-radius: 6px; font: 13px Consolas, monospace; line-height: 1.6; }
  </style>
  <!-- ① 오류를 화면에 표시: module보다 먼저 실행되는 일반 script -->
  <script>
    function showErr(msg) {
      const box = document.getElementById('err');
      box.style.display = 'block';
      box.textContent += msg + '\n';
    }
    addEventListener('error', (e) => showErr('[error] ' + (e.message || e.target.src || e.target.href)), true);
    addEventListener('unhandledrejection', (e) => showErr('[promise] ' + e.reason));
  </script>
  <script type="importmap">
    {
      "imports": {
        "three": "https://cdn.jsdelivr.net/npm/three@0.186.1/build/three.module.js",
        "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.186.1/examples/jsm/"
      }
    }
  </script>
</head>
<body>
<pre id="err"></pre>
<div id="dbg">debug</div>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

const DEBUG = true;                               // 배포할 때는 false

// 1. 장면 기본 설정
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xdfe8f0);
const camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 0.1, 1000);
camera.position.set(60, 38, 75);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
scene.add(new THREE.HemisphereLight(0xffffff, 0x6b7f63, 0.9));
const sun = new THREE.DirectionalLight(0xffffff, 2.0);
sun.position.set(40, 70, 45);
scene.add(sun);
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 4, 0);
controls.update();

// 2. 교량 (3경간 × 30 m, 폭 12 m) - 단위 m, Y축 위
const P = { nSpan: 3, L: 30, B: 12, n: 4, H: 8 };
const h = P.L / 20, Lt = P.nSpan * P.L, x0 = -Lt / 2;
const bridge = new THREE.Group();
scene.add(bridge);
const mat = (c) => new THREE.MeshStandardMaterial({ color: c });
function box(name, w, hh, d, color, x, y, z) {
  const m = new THREE.Mesh(new THREE.BoxGeometry(w, hh, d), mat(color));
  m.name = name;                                  // 이름을 붙여 두면 디버깅이 쉽다
  m.position.set(x, y, z);
  bridge.add(m);
}
box('DECK', Lt, 0.25, P.B, 0xb8bcc2, 0, P.H + h + 0.125, 0);
for (let i = 0; i < P.n; i++) box(`G${i + 1}`, Lt - 0.2, h, 0.4, 0x3f6e9e, 0, P.H + h / 2, -(P.B / 2 - 1) + i * (P.B - 2) / (P.n - 1));
for (let k = 1; k < P.nSpan; k++) box(`P${k}`, 1.8, P.H, 1.8, 0xa9adb3, x0 + k * P.L, P.H / 2, 0);
for (const [id, s] of [['A1', -1], ['A2', 1]]) box(id, 2, P.H, P.B + 1, 0x9da2a8, s * (Lt / 2 + 0.6), P.H / 2, 0);

// 3. 디버깅 도우미
if (DEBUG) {
  scene.add(new THREE.AxesHelper(20));                          // 빨강 X · 초록 Y · 파랑 Z
  scene.add(new THREE.GridHelper(200, 20, 0x666666, 0xaaaaaa)); // 10 m 간격 바닥 격자
  const bbox = new THREE.Box3().setFromObject(bridge);
  scene.add(new THREE.Box3Helper(bbox, 0xff7a1a));              // 모델 경계 상자
  const size = bbox.getSize(new THREE.Vector3());
  const lights = scene.children.filter((o) => o.isLight).length;
  const dist = camera.position.distanceTo(bbox.getCenter(new THREE.Vector3()));
  document.getElementById('dbg').innerHTML =
    `모델 크기: ${size.x.toFixed(1)} × ${size.y.toFixed(1)} × ${size.z.toFixed(1)} m<br>` +
    `조명 수: ${lights}<br>카메라 거리: ${dist.toFixed(1)} m (near ${camera.near}, far ${camera.far})`;
  console.table(bridge.children.map((m) => ({
    name: m.name, x: m.position.x.toFixed(2), y: m.position.y.toFixed(2), z: m.position.z.toFixed(2),
  })));
  window.scene = scene;                                         // F12 콘솔에서 scene 직접 확인 가능
}

renderer.setAnimationLoop(() => { controls.update(); renderer.render(scene, camera); });
addEventListener('resize', () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});
</script>
</body>
</html>

 

Claude에게 이렇게 요청했다

three.js 교량 모델에서 버그가 있어. 아래 정보를 보고 원인을 찾아 고쳐줘.

[증상] 교량이 옆으로 넘어져 바닥판이 벽처럼 서 있어. 콘솔 오류는 없어.

[기대] 바닥판이 수평이고 Y축이 위여야 해. (three.js 0.186.1, 단위 m)

[근거] Box3로 잰 모델 크기가 93.2 × 13.0 × 9.8 m야. 높이가 Z 방향에 있어.

[추측] 좌표를 CAD처럼 Z축이 위인 기준으로 넣은 것 같아.

[범위] 좌표 변환 부분만 고치고, 재질·조명·카메라 코드는 바꾸지 마. 수정한 함수 전체를 보여줘.

 

○ 이 다섯 줄 틀(증상·기대·근거·추측·범위)을 메모장에 저장해 두고 빈칸만 채워서 쓰면 된다.

 

정리

○ 디버깅은 재현 → 관찰 → 범위 좁히기 → AI에게 전달 → 검증 순서로 한다.

○ F12 콘솔의 빨간 줄은 전문 그대로 AI에게 준다. 오류가 없으면 값(크기·각도·좌표)을 의심한다.

○ AxesHelper · GridHelper · Box3를 켜면 단위·좌표축·크기 버그가 눈에 보인다.

○ AI에게는 증상·기대·근거·추측·범위를 함께 보낸다.

 

다음 편 예고

10편은 연재의 마지막 편이다. 지금까지 만든 교량 모델을 glTF(.glb) 파일로 내보내서 Blender나 윈도우 3D 뷰어, 웹 뷰어에서 열고, 7편에서 넣은 부재 속성(userData)이 파일에 함께 저장되는지 확인한다.

 

관련 글

     → [교량 BIM 바이브코딩 1편] three.js 입문: Claude 바이브코딩으로 3D 교량 만들기

     → [교량 BIM 바이브코딩 2편] three.js 기초: 장면·카메라·렌더러

     → [교량 BIM 바이브코딩 3편] OrbitControls·조명·그림자

     → [교량 BIM 바이브코딩 4편] AI 코딩 프롬프트 작성법: Claude에게 3D 모델 정확히 요청하기

     → [교량 BIM 바이브코딩 5편] three.js ExtrudeGeometry: I형 거더 단면 3D 모델링

     → [교량 BIM 바이브코딩 6편] three.js 파라메트릭 모델링: 슬라이더로 바뀌는 교량

     → [교량 BIM 바이브코딩 7편] three.js 교량 BIM 모델: 클릭하면 속성이 나오는 부재 조립

     → [교량 BIM 바이브코딩 8편] three.js 곡선교 모델링: 곡선 반경 R과 편경사로 휘는 교량

     → [교량 BIM 바이브코딩 10편] three.js glTF 내보내기: 교량 BIM 모델을 GLB 파일로 저장하고 속성까지 공유하기

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/10   »
일 월 화 수 목 금 토
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31