아들과 함께 만들어보는 인공지능(LLM) 로봇 만들기 프로젝트 — EP 5. 12살이 AI로 로봇 코딩한 첫날 기록
아들과 함께 만들어보는 인공지능(LLM) 로봇 만들기 프로젝트 — EP 5. 12살이 AI로 로봇 코딩한 첫날 기록
아들이 혼자 해보겠다고 한 날이 왔다.
그동안은 내가 옆에 있거나, 같이 입력하거나, 에러가 나면 내가 보고 설명해줬다. 근데 이날은 "나 혼자 해볼게"였다. 주말 오후였다. 나는 다른 방에 있었다.
30분쯤 지나서 아들이 왔다. "아빠, 로봇이 왼쪽으로만 계속 돌아."
아들이 쓴 첫 프롬프트
나중에 아들이 그날 입력한 것들을 같이 봤다.
첫 번째로 입력한 게 이거였다.
"로봇이 장애물 만나면 왼쪽으로 피해가게 해줘"
Claude Code가 코드를 냈다. 아들이 올렸다. 로봇이 앞으로 가다가 장애물 감지하면 멈추고 왼쪽으로 돌았다. 여기까지는 맞았다.
근데 돌고 나서 다시 앞으로 안 갔다. 왼쪽으로 계속 돌기만 했다.
아들이 두 번째 입력:
"장애물 피하고 나서 다시 앞으로 가게 해줘"
코드가 수정됐다. 다시 올렸다. 이번엔 장애물 앞에서 멈추고, 왼쪽으로 돌고, 다시 앞으로 갔다.
근데 매번 같은 각도로만 돌았다. 장애물이 벽이면 계속 같은 방향으로 돌다가 벽을 따라가게 됐다.
아들이 세 번째 입력:
"한 번 피할 때마다 왼쪽으로 도는 시간을 좀 다르게 해줘"
그다음부터 좀 바뀌기 시작했다.
Claude한테 물어본 지점
세 번째 코드를 올리고 나서 아들이 멈췄다.
Serial 모니터를 켜니까 이런 출력이 나왔다.
dist: 0
dist: 0
dist: 0
dist: 18
dist: 0
dist: 400
dist: 23
0이랑 400이 계속 섞였다. 초음파 센서 노이즈 문제였다. EP 2에서 언급했던 바로 그 문제였다.
0cm가 나오면 코드가 장애물로 인식해서 계속 멈췄다. 아들이 "왜 아무것도 없는데 멈춰"라고 했다. 코드 문제가 아니라 센서 값 문제인데, 아들 입장에서는 코드가 잘못된 건지 센서가 잘못된 건지 구분이 안 됐다.
이때 나한테 왔다. "아빠, 이상해."
Serial 모니터 출력을 같이 봤다. 0이 왜 나오는지 설명했다. 초음파 센서가 가끔 측정에 실패하면 0을 반환한다. NewPing에서 이걸 필터링하는 옵션이 있다. 아들한테 "이걸 Claude한테 말해봐"라고 했다.
아들이 입력한 네 번째 프롬프트:
"센서 값이 0이나 400이 나오면 무시하고 그 전 값을 쓰게 해줘"
코드가 나왔다. 직전 유효 측정값을 저장해두고, 현재 값이 0이거나 MAX_DISTANCE 이상이면 이전 값을 쓰는 로직이었다. 올렸다. 0이 나와도 멈추지 않았다.
아들 얼굴이 바뀌었다.
아들이 직접 발견한 것
그 이후로 아들이 혼자 계속 했다.
다섯 번째 프롬프트:
"로봇이 앞으로 가다가 왼쪽으로 피할 때 너무 급하게 꺾여서 자꾸 한쪽 바퀴가 들려. 부드럽게 방향 바꾸게 해줘"
이건 내가 시킨 게 아니었다. 아들이 직접 보고 발견한 문제였다. 급격한 방향 전환 때 샤시가 들리는 걸 눈으로 봤고, 그걸 말로 설명했다.
Claude Code가 제안한 코드는 방향 전환 전에 속도를 낮추고, 전환 후에 다시 속도를 올리는 방식이었다. 아들이 올렸다. 덜 들렸다.
"좀 나은 것 같아."
좀 나은 거다. 완전히 고쳐진 건 아니었다. 근데 아들이 문제를 식별하고, 말로 설명하고, 코드로 이어지는 과정을 혼자 했다.
그날의 프롬프트 로그
아들이 그날 입력한 프롬프트를 모아봤다. 총 8번이었다.
- "로봇이 장애물 만나면 왼쪽으로 피해가게 해줘"
- "장애물 피하고 나서 다시 앞으로 가게 해줘"
- "한 번 피할 때마다 왼쪽으로 도는 시간을 좀 다르게 해줘"
- "센서 값이 0이나 400이 나오면 무시하고 그 전 값을 쓰게 해줘"
- "로봇이 앞으로 가다가 왼쪽으로 피할 때 너무 급하게 꺾여서 자꾸 한쪽 바퀴가 들려. 부드럽게 방향 바꾸게 해줘"
- "속도 150 말고 200으로 해봐"
- "200은 너무 빠른 것 같아. 175로 해줘"
- "지금 코드에서 Serial.println 다 지워줘, 시리얼 모니터 안 켜고 쓸 거라서"
8번 프롬프트가 좀 의외였다. Serial 디버그 출력이 루프에 영향을 준다는 걸 어디서 봤거나 직관적으로 느낀 것 같다. 물어봤더니 "출력하는 게 시간 걸릴 것 같아서"였다. 정확한 이해는 아니지만 방향은 맞았다.
이 여덟 개 프롬프트를 보면 아들이 뭘 배웠는지 보인다. 코드 문법이 아니다. "원하는 동작"을 설명하는 방식, 문제가 생겼을 때 어디를 봐야 하는지, 그리고 조금씩 좁혀가는 방식.
아들이 처음으로 혼자 완성한 동작
그날 저녁에 아들이 최종 버전을 올렸다. 장애물 감지 → 속도 감속 → 왼쪽 회전(랜덤 각도) → 다시 전진. 센서 노이즈 필터링 포함. Serial 출력 제거.
테스트했다. 거실을 돌아다니면서 의자 다리를 피했다. 한 번에 막히기도 했지만, 대부분 피했다.
아들이 "이건 내가 짠 거야"라고 했다.
기술적으로는 Claude Code가 코드를 썼다. 근데 아들이 뭘 만들지 결정했고, 문제가 생겼을 때 어떻게 고칠지를 말했고, 여덟 번의 프롬프트를 통해 동작을 만들어냈다. 코드를 한 줄도 안 쳤는데 "내가 짠 거"라는 말이 틀리지 않다고 생각했다.
이게 바이브 코딩이고, 이게 내가 이 프로젝트에서 가르치고 싶었던 것이다.
코드를 모르고 코딩한다는 것
한 가지 솔직하게 쓴다.
아들이 그날 만든 코드를 아들이 이해하지는 못한다. 어느 줄이 뭘 하는지 물어보면 모른다. 컴파일 에러가 나면 에러 메시지를 읽을 줄 모른다. 이건 사실이다.
이게 문제인지 아닌지는 내가 아직 판단 못 했다. "코드를 이해하지 못하고 작동하는 것만 만드는 게 의미 있냐"는 질문은 정당하다. 어쩌면 나중에 기초부터 배워야 하는 순간이 올 수도 있다.
근데 나는 지금 단계에서 그걸 강요하지 않으려 한다. 아들이 지금 배우고 있는 건 "원하는 걸 설명해서 뭔가를 만드는 경험"이다. 그 경험이 코딩에 대한 흥미를 만들어줄 거라고 생각한다. 문법은 그 흥미가 생긴 다음에 가르쳐도 늦지 않다.
열 살짜리가 자전거를 처음 탈 때 역학을 배우지 않는다. 일단 타본다. 나중에 궁금해지면 배운다.
지금은 일단 타보는 단계다.
댓글
댓글 쓰기