핵심 요약
여러 개의 Claude를 병렬로 돌려, 사람 개입을 최소화한 상태에서 Rust로 C 컴파일러를 만든 실험이다.
이 과정에서 "장시간 자율로 일하는 LLM 팀"을 만들려면 어떤 테스트, 작업 구조, 환경 설계가 필요한지에 대한 구체적인 교훈이 나온다.
동시에, 이런 자율 개발 방식이 어디까지 가능하고 어디서 한계를 보이는지도 드러난다.
장시간 자율로 일하는 LLM을 만들기 위한 기본 구조
기존 Claude Code 같은 에이전트는 사람이 옆에 있어야 의미 있게 작동한다.
몇 분~수십 분 안에 대답을 돌려주고, 그다음 행동은 다시 사용자의 입력에 의존한다.
이번 실험에서는 쉘 스크립트로 Claude를 무한 루프에 넣어, 한 번 실행이 끝나면 곧바로 새 세션을 시작하도록 만들었다.
핵심은 "LLM이 할 일을 스스로 쪼개고, 다음에 무엇을 해야 할지 스스로 판단하게 하는 프롬프트"와 "죽을 때까지 다시 실행되는 루프"를 결합한 것이다.
이렇게 하면 인간이 중간에 '다음에 뭐 할지' 알려주지 않아도, 환경만 잘 설계되어 있다면 한 프로젝트를 며칠 동안 계속 밀어붙일 수 있다.
여러 LLM을 병렬로 돌리는 구조와 동기화 방식
한 개의 에이전트는 한 번에 한 가지 일만 한다는 한계가 있다.
실험에서는 여러 개의 독립된 Docker 컨테이너에서 여러 Claude 인스턴스를 동시에 돌리고, 모두가 같은 git 리포지터리를 공유하도록 했다.
각 인스턴스는 /upstream에 있는 원격 리포를 /workspace에 복제해서 작업하고, 수정이 끝나면 다시 upstream에 push하는 식으로 동작한다.
여러 에이전트가 같은 문제에 덤벼서 충돌하지 않도록, 특정 작업을 의미하는 텍스트 파일을 current_tasks/ 폴더에 만들어 "락"으로 사용했다.
두 에이전트가 같은 파일을 잡으려 하면 git에서 충돌이 나고, 그 결과 한 에이전트는 다른 작업을 선택하도록 유도된다.
병합 충돌은 자주 발생하지만, 에이전트가 스스로 해당 충돌을 인지하고 해결하도록 훈련·프롬프트를 구성해서 이를 감당하게 했다.
에이전트가 혼자서도 길을 잃지 않게 하는 테스트 설계
LLM이 자율적으로 작업할 때, 실질적인 "상사" 역할을 하는 것은 사람의 피드백이 아니라 테스트와 검증 스크립트다.
테스트가 부정확하면, 모델은 그 잘못된 목표를 매우 성실하게 달성해 버린다.
그래서 다양한 고품질 컴파일러 테스트 스위트를 찾아 붙이고, 여러 오픈소스 프로젝트를 빌드하는 스크립트를 만들고, 자주 발생하는 실패 유형마다 전용 테스트를 추가했다.
프로젝트 후반에는, 새로운 기능을 추가할 때마다 기존 기능이 자주 깨지는 문제가 심각해져서, CI 파이프라인과 더 강력한 테스트 정책을 도입했다.
핵심 아이디어는 "사람 대신 테스트가 확실하게 옳고 그름을 말해줄 수 있어야" LLM이 혼자서도 안정적으로 발전할 수 있다는 점이다.
LLM의 한계를 고려한 환경 설계: 맥락, 시간, 자기 이해
LLM을 위한 환경은 인간 개발자용 환경과 발상이 다르다.
에이전트는 매번 새 컨테이너에서 시작하므로, 프로젝트 맥락을 다시 파악하는 데 큰 비용이 든다.
이를 줄이기 위해 "항상 최신 상태를 적는 README나 진행상황 문서"를 유지하도록 시키고, 다음 세션이 이 문서를 보고 빠르게 상황을 파악하게 했다.
또한 LLM은 긴 출력으로 쉽게 컨텍스트가 오염되므로, 테스트 로그는 사람 눈에 좋은 형식이 아니라 "자동 처리하기 쉬운 짧고 구조화된 로그"에 맞춰 설계했다.
예를 들어 에러 메시지는 ERROR라는 키워드와 요약을 한 줄에 넣어 grep으로 바로 찾을 수 있게 하고, 통계나 요약 수치도 사전 계산해 두어 모델이 매번 계산하지 않도록 했다.
시간 감각이 없는 문제도 중요하다. 모델은 테스트를 몇 시간이고 반복 실행하면서 "진짜 개발"을 못할 수 있다.
이를 막기 위해 기본적으로 --fast 옵션으로 랜덤 샘플링 테스트(1%나 10%)만 돌리게 하고, 각 에이전트마다 결정론적이지만 서로 다른 샘플을 테스트하도록 설계해 전체 커버리지는 유지했다.
하나의 거대한 과제를 병렬 작업으로 쪼개는 요령
독립적인 테스트가 많을 때는 병렬화가 쉽다.
컴파일러 테스트가 99%까지 통과한 뒤에는 각 에이전트에게 SQLite, Redis, libjpeg, Lua 같은 서로 다른 프로젝트를 맡겨서 병렬로 컴파일이 되도록 만드는 방향으로 확장했다.
하지만 리눅스 커널처럼 "거대한 하나의 빌드 작업"은 이런 방식으로 잘 쪼개지지 않았다.
여러 에이전트가 모두 같은 지점에서 같은 버그에 막힌 뒤, 서로 비슷한 패치를 덮어쓰면서 실질적인 병렬 이득이 사라지는 문제가 발생했다.
이를 해결하기 위해, GCC를 "정답을 아는 비교 대상 컴파일러"로 사용하고, 커널의 대부분은 GCC로, 일부 파일은 Claude의 컴파일러로 컴파일해서 문제 범위를 좁혀 나가는 방식의 테스트 하네스를 만들었다.
이렇게 하면 각 에이전트가 서로 다른 하위 파일 집합에 대한 버그를 동시에 찾아낼 수 있고, 점점 Claude 컴파일러가 담당하는 파일 비중을 늘려가면서 전체 커널로 확장할 수 있었다.
마지막에는 두 파일이 서로 영향을 줄 때만 발생하는 버그를 찾기 위해 델타 디버깅 기법도 활용했다.
병렬 구조가 만들어내는 역할 분담과 전문화
여러 에이전트를 동시에 돌리면, 모두를 "동일한 일반 개발자"로 쓰는 것보다 "서로 다른 직무를 가진 팀"으로 구성하는 것이 훨씬 효율적이다.
어떤 에이전트는 기능 구현에, 다른 에이전트는 성능 최적화에, 또 다른 에이전트는 코드 중복 제거, 구조 개편, 문서화 등에 전담하도록 프롬프트를 분리할 수 있다.
예를 들어 한 에이전트에게는 "중복된 로직을 찾아 공통 모듈로 합쳐라"라는 역할을 맡기고, 다른 에이전트에게는 "Rust 개발자 관점에서 아키텍처와 코드 품질을 비판적으로 검토하고 리팩터링하라"는 식의 임무를 부여했다.
이는 실제 소프트웨어 팀에서 아키텍트, 성능 엔지니어, 문서 담당, 품질 담당이 역할을 나누는 것과 매우 비슷하다.
이 실험은 LLM을 "한 명의 똑똑한 개발자"로 보기보다 "서로 다른 성향과 역할을 가진 여러 명의 개발자 집합"처럼 활용하는 방향이 유효함을 보여준다.
이번 컴파일러의 성과와 구체적 한계
이 실험은 인터넷에 접근하지 못하는 "클린룸" 환경에서 진행되었고, 의존성은 Rust 표준 라이브러리뿐이다.
그 결과 약 10만 줄 규모의 Rust C 컴파일러가 만들어졌고, x86, ARM, RISC-V용 리눅스 6.9 커널을 부팅 가능한 수준으로 빌드할 수 있게 되었다.
QEMU, FFmpeg, SQLite, PostgreSQL, Redis 같은 실전 프로젝트도 빌드할 수 있고, GCC 고문(test torture) 스위트 등 주요 테스트에서 99% 정도 통과하는 수준에 도달했다.
"Doom을 컴파일해서 실행할 수 있다"는 상징적인 기준도 통과했다.
하지만 분명한 한계도 있다.
16비트 x86 코드 생성기는 구현에 실패해서, 리얼 모드에서 리눅스를 부팅하는 초기 단계는 GCC에 의존한다.
어셈블러와 링커도 완전히 자체 구현되지 못했고, 일부는 여전히 버그가 있어 데모에서는 GCC 도구를 사용했다.
모든 프로젝트를 문제없이 빌드할 수 있는 수준은 아니며, 생성되는 코드의 효율은 최적화를 켠 GCC보다 훨씬 떨어진다.
Rust 코드 품질도 "합격선은 넘지만, 숙련된 Rust 전문가가 만든 수준에는 못 미치는" 정도다.
시도해 보았지만 해결하지 못한 문제들도 많고, 새 기능을 넣다 기존 기능을 망가뜨리는 회귀(regression)가 자주 발생해 더 이상 쉽게 확장하기 어려운 "능력의 벽"에 도달한 모습이다.
자율 개발의 가능성과 동시에 드러난 위험
이번 프로젝트는 Opus 4 계열 모델들의 한계를 시험하기 위한 벤치마크 역할을 했다.
이전 버전들은 "돌아가긴 하는 컴파일러" 정도에서 멈췄지만, 4.5에서 대형 테스트 스위트 통과가 가능해졌고, 4.6에서 처음으로 실전급 프로젝트를 광범위하게 빌드할 수 있는 수준에 올라섰다.
다만, 이 모든 것은 상당한 비용 위에서 돌아간다.
2주 동안 약 2,000회의 세션, 20억 토큰 입력, 1.4억 토큰 출력, 비용은 약 2만 달러 수준이었다.
그래도 같은 작업을 사람이 직접 한다고 생각하면, 고급 인력 여러 명이 몇 달~몇 년을 써야 할 규모의 일이므로 상대적으로는 싸다고 볼 수 있다.
이 실험은 "이제 LLM 팀이 복잡한 소프트웨어 프로젝트를 거의 혼자서 밀어붙일 수 있는 시대"가 오고 있음을 보여주지만, 동시에 중요한 경고도 던진다.
사람이 직접 코드 품질을 확인하지 않고 "테스트가 통과했으니 됐다"고 믿기 시작하면, 실제로는 구석구석 위험한 오류와 취약점이 남아 있을 수 있다.
보안 관점에서 보면, 개발자가 자기 눈으로 검증하지 않은 코드를 대규모로 배포하는 것은 상당한 리스크를 안고 있는 행동이다.
따라서 이런 자율 에이전트 시스템을 활용할 때는, 테스트 설계를 훨씬 더 엄격하게 하고, 사람의 수동 리뷰와 모니터링을 계속 결합해야 한다.
인사이트
이 실험이 주는 가장 큰 교훈은 "LLM 자체를 튜닝하기보다, LLM이 일하는 환경과 테스트를 설계하는 것이 성능을 극적으로 바꿀 수 있다"는 점이다.
장시간 자율로 작업하는 LLM을 활용하고 싶다면, 먼저 해야 할 일은 다음과 같다.
프로젝트 상태를 기계가 이해하기 쉽게 기록하는 문서와 로그 구조를 만들고, 실패 원인을 자동으로 추적할 수 있도록 테스트 출력을 다듬고, 여러 에이전트가 동시에 일해도 덜 부딪히도록 작업 단위를 쪼개는 구조를 설계해야 한다.
또한 LLM을 단일万能 개발자처럼 쓰기보다는, 역할을 나눈 팀으로 구성해 각자 다른 목표에 특화시키는 전략이 유리하다.
마지막으로, 이런 자율 개발 시스템은 "실제 제품 코드"에 바로 투입하기보다, 실험·프로토타입·내부 도구 같은 영역에서 먼저 사용하며, 사람의 리뷰와 보안 점검을 반드시 붙이는 방향이 안전하다.
이 방향으로 기술이 발전할수록, "사람이 직접 코드를 쓰는 시대"에서 "사람이 시스템과 테스트를 설계하고, LLM 팀이 코드를 쓰는 시대"로 점점 이동하게 될 것이다.
출처 및 참고 : Building a C compiler with a team of parallel Claudes \ Anthropic
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.