AI 세 대가 코드를 이어 쓰자, 기능과 함께 버그도 쌓였다
브라우저에서 도는 3D 항공기 게임을 만드는 데 서로 다른 AI 모델 셋을 초안, 보강, 완성 순으로 이어 앉혔다. 뒤로 갈수록 기능은 화려해졌지만, 마지막 모델은 앞선 코드에서 중력이 사실상 0이 되는 물리 오류와 산과 충돌면이 어긋난 좌표 문제부터 걷어내야 했다.
AI와 사회 · 2026-07-30
AI에게 코딩을 시킬 때 흔한 방식은 한 모델에게 처음부터 끝까지 맡기는 것이다. 여기서는 다른 방식을 시험했다. 하나의 과제를 놓고 서로 다른 회사의 AI 모델 셋을 릴레이처럼 이어 앉혔다. 앞 모델이 짠 코드를 다음 모델이 받아 개선하고, 그 위에 또 다음 모델이 쌓는 식이다.
과제는 브라우저에서 바로 실행되는 3D 실사풍 항공기 조종 게임이었다. HTML 파일 하나로 열리고, 조종해 날 수 있으며, 그 장면을 영상으로 뽑을 수 있어야 했다. 세 모델에게는 각각 초안 설계, 기능 보강, 최종 완성이라는 자리가 주어졌다.
쌓이는 것은 기능만이 아니었다
초안은 Three.js를 바탕으로 하늘과 지형, 프로펠러가 달린 기체, 속도와 고도를 보여주는 계기판, 그리고 간단한 비행 물리까지 갖춘 뼈대를 세웠다. 두 번째 차례는 그 위에 입체적인 산악 지형과 통과할 목표물인 체크포인트 링, 파형을 합성해 만든 엔진음, 화면 흔들림 효과를 얹었다. 매 라운드 게임은 눈에 띄게 화려해졌다.
그러나 마지막 자리에 앉은 모델이 보고한 것은 새 기능 목록이 아니라 앞선 코드에 조용히 누적된 결함들이었다. 이것이 이 릴레이가 드러낸 핵심이다. 기능을 얹는 손길마다 버그도 함께 얹혔고, 다음 모델은 그것을 알아채지 못한 채 그 위에 또 쌓았다.
마지막 모델이 걷어낸 것들
가장 무거운 문제는 비행 물리에 있었다. 가속도를 위치에 더하는 식이 시간 간격의 제곱으로 계산되어, 사실상 중력이 거의 0으로 사라져 있었다. 이를 잡기 위해 최종 모델은 속도 벡터를 상태로 따로 두고 힘을 제대로 적분하는 방식으로 물리를 다시 썼다.
지형에도 어긋남이 있었다. 산을 생성하는 계산과 기체가 땅에 부딪히는지 판정하는 계산이 서로 다른 좌표를 쓰고 있어서, 화면에 보이는 산과 실제 충돌하는 면이 따로 놀았다. 두 계산을 하나의 높이 함수로 통일해 맞췄다.
그 밖에도 HTML에서 같은 식별자가 두 번 붙어 뒤엣것이 무시되던 문제, 카메라가 시선을 맞춘 뒤 회전값을 덮어써 미세하게 떨리던 문제, 구름 스프라이트가 재질 하나를 공유해 개별 투명도를 줄 수 없던 문제가 지목되어 수정되었다. 최종본은 여기에 영상 녹화 기능과 시네마틱 카메라, 후처리 효과, 받음각 기반 실속 모델까지 더해 원래 요구였던 '영상 만들기'를 충족시켰다.
여러 모델을 이어 앉힌다는 것
이 결과는 폴로라(Polora)가 하나의 물음에 서로 다른 AI 모델을 각기 다른 자리에 앉혀 본 방식에서 나왔다. 한 모델에게 통째로 맡겼다면 초안, 보강, 검수가 한 시야 안에서 흐려졌을 것이다. 자리를 나눴기에, 앞 단계가 무엇을 놓쳤는지를 뒤 단계가 바깥에서 짚어낼 수 있었다.
그래서 이 릴레이가 말해 주는 것은 두 가지다. 이어 쓰기는 기능을 빠르게 불려 나가는 데 효과가 있었다. 동시에, 앞선 코드를 믿고 그 위에 쌓기만 하면 결함도 함께 물려받는다. 마지막에 앞의 것을 뜯어보고 바로잡는 자리가 없었다면, 화면은 그럴듯해도 속은 어긋난 채였을 것이다.
grok, gemini, opus 세 ai가 협동해서 코딩을 해보자. 1개의 라운드에 순차적으로 이전 ai가 작성한 것을 토대로 더 개선하고 쌓아나가면 됨. 그록이 초안을 쓰고, 제미나이가 한번 더 보태고, 마지막에 오푸스가 최종코드를 제출해. 코드 작성 주제는, HTML로 실행가능한 3d 실사 스타일 항공기 조종 게임 영상 만들기임.
초안 설계자 (Grok) · grok-4.5
초안 설계자 (Grok) — 1라운드 초안
안녕하세요. 요청하신 대로 HTML 한 파일로 실행 가능한 3D 실사 스타일 항공기 조종 게임 초안을 작성했습니다.
Three.js 기반으로, 브라우저에서 바로 열고 조종할 수 있게 구성했습니다.
제미나이·오푸스가 이어서 개선할 수 있도록 구조·주석·확장 포인트를 명확히 잡아 두었습니다.
---
초안 설계 방향
| 항목 | 내용 |
|------|------|
| 실행 | 단일 .html 파일 (CDN Three.js) |
| 그래픽 | 하늘 그라데이션 + 안개 + 지형 + 구름 + 방향광/그림자 |
| 기체 | 프로시저럴 메시 항공기 (동체·날개·꼬리·프로펠러) |
| 조종 | WASD / 방향키 + 마우스 시야 + Space/Ctrl 고도 |
| 카메라 | 3인칭 추적 카메라 |
| HUD | 속도·고도·자세 표시 |
| 확장 여지 | 활주로, 충돌, 사운드, 파티클, GLTF 모델 교체 등 |
---
초안 코드 (이 파일을 flight.html로 저장 후 브라우저에서 열기)
html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>3D Flight Sim — Draft (Grok)</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; font-family: "Segoe UI", system-ui, sans-serif; }
#canvas-container { width: 100%; height: 100%; display: block; }
canvas { display: block; width: 100%; height: 100%; }
/* HUD */
#hud {
position: fixed; inset: 0; pointer-events: none;
color: #c8f7c5; text-shadow: 0 0 6px rgb…
기능 보강자 (Gemini) · gemini-3.1-pro
안녕하세요! 기능 보강자(Gemini)입니다.
초안 설계자(Grok)가 작성해 준 탄탄한 뼈대 위에, 게임으로서의 재미와 실사 느낌을 한층 끌어올릴 수 있는 요소들을 추가했습니다. 단일 HTML 파일로 바로 실행할 수 있는 제약 안에서 최대한 효과를 내기 위해 절차적 생성(Procedural Generation) 기법을 적극 활용했습니다.
---
🚀 제미나이(Gemini) 보강 포인트
1. 절차적 3D 지형 (Procedural Terrain): 평평했던 바닥을 세분화하여, 수식을 이용해 산과 골짜기가 있는 입체적인 지형으로 만들었습니다. (활주로 주변은 평탄하게 유지)
2. 목표물(체크포인트 링) 추가: 하늘에 통과할 수 있는 빛나는 링을 배치하여 조종해야 할 목적(게임성)을 부여했습니다. 링을 통과하면 점수가 오릅니다.
3. 웹 오디오 엔진음 (Web Audio API): 외부 파일 없이 브라우저 내장 오디오 노드를 이용해 스로틀과 속도에 반응하는 프로펠러 엔진음을 합성했습니다.
4. 시작 화면 (오디오 정책 대응): 브라우저 오디오 자동 재생 정책을 준수하기 위해 '클릭하여 시작' 화면을 추가했습니다.
5. 카메라 쉐이크 & 비행 물리 개선: 속도가 빠르거나 기동이 격렬할 때 화면이 미세하게 떨리는 효과를 추가하고, 선회 시 양력 벡터가 기울어지는 느낌을 보강했습니다.
---
💻 2라운드 코드 (이 파일을 flight_gemini.html로 저장)
html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>3D Flight Sim — Round 2 (Gemini)</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; font-family: "Segoe UI", system-ui, sans-serif; }
#canvas-container { width: 100%; height: 100%;…
최종 완성자 (Opus) · claude-opus-5
최종 완성자 (Opus) — 3라운드 최종본
Grok의 뼈대와 Gemini의 보강을 받아 버그를 잡고, 물리를 다시 쓰고, "영상 만들기"라는 원래 요구를 실제로 충족시켰습니다.
먼저, 이전 라운드에서 반드시 고쳐야 했던 것들
| 문제 | 위치 | 수정 |
|---|---|---|
| <div id="attitude" id="att-val"> — id 중복 (HTML 파싱 시 뒤쪽 무시) | Grok | 단일 id로 정리 |
| 지형 높이 샘플링 좌표계 불일치 | Gemini | Plane을 rotation.x=-π/2 하면 local y → world −z. 생성식은 (x,y), 충돌 판정은 (x,z)로 써서 산과 충돌면이 어긋나 있었음 → H(x,z) 단일 함수로 통일 |
| addScaledVector(accel, dt*dt*0.5) | Gemini | 가속도를 위치에 dt² 로 더해 사실상 중력이 0. 속도 벡터 상태를 도입해 제대로 적분 |
| camera.lookAt() 후 camera.rotation.z 대입 | Gemini | lookAt이 만든 쿼터니언을 오일러로 덮어써 미세 떨림 → 쿼터니언 slerp 방식으로 교체 |
| 구름 스프라이트가 머티리얼 1개 공유 | Gemini | opacity 개별화 불가 → 인스턴스별 clone + 재활용(무한 스크롤) |
| getWorldQuaternion(new THREE.Quaternion()) 결과 미사용 | Gemini | 삭제 |
| 링 15개가 모두 −Z 일직선 | Gemini | 코스 형태로 배치 + 다음 목표 화살표 |
최종본에서 새로 넣은 것
1. 실제 영상 저장 — canvas.captureStream() + MediaRecorder로 R 키 녹화 → .webm 다운로드 (엔진음까지 믹싱)
2. 시네마틱 카메라 4종 (C 키) — 추격 / 콕핏 / 윙뷰 / 플라이바이(자동 스윕). 영상 뽑기용
3. UnrealBloom + 톤매핑 포스트프로세싱
4. 고도별 버텍스 컬러 지형 (초지 → 암반 → 설선)
5. 날개끝 와류 트레일 (고G 기동 시 진해짐)
6. 양력/항력/받음각(AoA) 기반 비행 모델 — 실속·스핀·과속 진동
7. 미니맵 레이더 + 착륙 판정 + 추락/리스폰
---
ht…