헤드리스 스크린샷 루프를 통해 로컬 30B 에이전트가 순수 C 언어로 레이트레이싱 FPS 데모를 완성하다
Headless screenshot loops let a local 30B agent finish a raytraced FPS demo in pure C
핵심 요약
로컬 LLM 에이전트가 스크린샷 피드백 루프를 활용해 스스로 코드를 디버깅하며 복잡한 C 언어 프로젝트를 완성함.
- 스크린샷 디버깅 — 에이전트가 스스로 스크린샷을 찍어 시각적으로 오류를 확인하고 수정함
- 로컬 모델 성능 — 27B 모델이 프론티어 모델과 유사한 수준의 문제 해결 능력을 보여줌
- 프롬프트 전략 — 에이전트에게 결과 확인 권한을 주어 난이도 높은 작업 수행 가능
- 오픈 소스 프로젝트 — 작성자가 개발한 codehamr를 통해 직접 테스트 가능
솔직하게 말하자면 배경 설명 좀 할게. 지난 몇 달 동안 three.js로 만든 단일 파일 게임들로 원샷(oneshot) 실험을 엄청나게 돌려봤어. 마인크래프트 클론 같은 것들 말이야. 굳이 이걸 고른 이유는 학습 데이터에 워낙 깊숙이 박혀 있어서 눈으로 디버깅하기가 개꿀이기 때문이지. 애초에 퀄리티 비교가 목적이 아니었어. 원샷으로 싸게 먹히면서 로그랑 눈으로 바로 확인 가능한 문제들이 필요했거든. 그래야 하네스(harness), 시스템 프롬프트, 툴 콜링을 튜닝할 수 있으니까.
이번 주에는 난이도를 좀 높여봤어. Claude Code(Opus 4.8)랑 로컬에서 돌리는 Qwen3.6 27B 에이전트한테 C언어 표준 라이브러리만 써서 작은 레이트레이싱 FPS 데모를 짜보라고 시켰지.
그래, C언어 레이트레이서도 학습 데이터에 있긴 해. three.js보다는 드물지만 어쨌든 있긴 하거든. 솔직히 말해서 LLM 나오기 전에도 우리 대부분은 패턴 재사용하면서 살았잖아. 스택 오버플로우 뒤지고, 문서 보고, 잘 돌아가는 코드 긁어와서 수정하고. 좋은 패턴 재사용하는 건 치팅이 아니라 그냥 일이야. 그러니까 그게 핵심은 아니라는 거지.
진짜 핵심은 프롬프트 딱 하나 바꾼 거였어. 둘 다 처음에는 원샷으로 해결하는 걸 엄청 힘들어하더라고. 그래서 요구사항을 하나 추가했지. 컴파일된 바이너리에 헤드리스(headless) 모드를 넣어서, 에이전트가 키보드랑 마우스 입력을 쏘고 특정 프레임에서 스크린샷을 찍을 수 있게 만들라고 했어.
그러니까 판도가 확 바뀌더라. 모델이 알아서 자기가 확인하고 싶은 이벤트 타이밍에 맞춰서 스크린샷을 찍기 시작했어. 로켓을 쏘고, 딱 충돌하는 순간 프레임을 캡처해서 파티클이랑 파편 효과를 확인하고, 잘못된 걸 고친 다음 다시 돌리는 식이지. 스스로 재귀적인 시각적 디버깅 루프를 구축한 거야.
최상위 모델이 해내는 건 놀랍지도 않아. 근데 Qwen3.6 27B가 혼자서 똑같은 루프를 돌리는 건 진짜 충격이었어. 나도 옛날에 C언어 처음 배울 때 고생 좀 했는데, 작은 로컬 에이전트가 지가 찍은 스크린샷 보면서 레이트레이서 디버깅하는 꼴을 보게 될 줄은 몰랐거든. 물론 대가는 따르지. 런타임도 길어지고, 토큰도 훨씬 많이 먹고, 반복할 때마다 시간도 꽤 걸려.
이건 모델에 대한 교훈이라기보다 프롬프트에 대한 교훈에 가까운 것 같아. 에이전트한테 결과를 볼 수 있는 방법을 주고, 언제 볼지 스스로 결정하게만 해줘도 작은 로컬 모델이 꽤 어려운 문제까지 해결할 수 있게 돼.
혹시 스크린샷 피드백 아이디어를 더 발전시켜 본 사람 있어? 정지 화면 말고 비디오 프레임으로 한다거나, 모델이 캡처하기 전에 더 긴 입력 시퀀스를 스크립트로 짜게 한다거나 하는 거 말이야.
참고로 말하자면, 여기서 쓴 로컬 에이전트는 내 오픈소스 프로젝트인 codehamr야. 그러니까 이 비교를 볼 때 그 점을 감안해서 판단해 줘. 직접 돌려보고 싶으면 코드는 공개되어 있어. https://github.com/codehamr/codehamr




