
AI는 아무렇지 않게 거짓말을 한다. 그럼에도 ClickHouse는 백만 줄의 C++를 돌린다 —— 1년의 운영 기록이 보여주는 단 하나의 비결
요약
ClickHouse는 100만 줄의 복잡한 C++ 코드베이스에 AI 에이전트를 성공적으로 도입했습니다. 에이전트의 낮은 단판 정답률을 극복하기 위해 대규모 자동화 테스트라는 '판정의 벽'을 활용하여 신뢰성을 확보했습니다.
핵심 포인트
- 에이전트의 신뢰성은 정답률이 아닌 '판정 속도와 반복 횟수'에서 결정됨
- 대규모 자동화 테스트(CI)가 에이전트의 잘못된 가설을 걸러내는 핵심 장치
- 사람은 '작성'이 아닌 '검증'에 집중함으로써 병목 현상을 해결
- Groene.AI와 ClickGap 같은 자율형 에이전트를 통한 테스트 보완
회의론자들의 마지막 변명은 대개 C++입니다. "에이전트(agent)는 JavaScript 정도는 쓸 수 있겠지. 하지만 원자력 발전소라도 돌리는 것 같은 나의 털북숭이 C++ 코드를 가지고, 세그폴트(segfault)를 하나씩 잡아내는 이 일은 불가능할 거야". 이것은 ClickHouse의 창립자 Alexey Milovidov 자신의, 절반은 자학적인 발언입니다. 100만 줄급의 C++로 작성된 분산 데이터베이스. AI에게 가장 맡기고 싶지 않은 종류의 코드입니다.
그 요새가 2025년 말에 무너졌습니다.
다만, 솔직히 가장 흥미로운 점은 "에이전트가 강해졌다"는 것이 아닙니다. 흥미로운 점은 —— 아무렇지 않게 거짓말을 하는 도구가, 왜 백만 줄의 C++ 위에서 "믿을 수 있게" 되었는가입니다. Milovidov의 운영 기록인 「Agentic Coding at ClickHouse」는 과장도 비하도 없이, 그 비결을 하나 명확하게 보여줍니다. 이것을 이해하면, "우리도 에이전트를 도입해야 할까?"라는 질문 자체가 사실은 잘못되었다는 것을 깨닫게 됩니다.
Milovidov가 거듭 강조하는 것은, 에이전트가 "그럴듯하지만 틀린 가설을 대량으로 내뱉는다"는 사실입니다. 이 부분을 오해하면 모든 것이 어긋납니다.
에이전트는 "올바른 코드를 쓰는 사람"이 아닙니다. 매초 엄청난 양의 추측을 생성하는 기계이며, 그 추측에는 정답과 오답이 섞여 있습니다. 따라서 "한 번에 올바르게 쓸 수 있는가?"로 평가한다면, 당신은 계속해서 도박을 하게 될 것입니다. 맞으면 신, 틀리면 사고. 재현성이 없습니다.
여기서 많은 현장은 "에이전트는 아직 쓸 수 없네"라며 끝을 맺습니다. ClickHouse는 끝내지 않았습니다. 도박으로 남겨두지 않고, 돌아가는 루프로 바꾸었기 때문입니다.
그들은 에이전트가 한 번에 맞히는 것에 도박을 걸지 않습니다. 대신 가지고 있는 것이, **빠르고 자동화된 "판정의 벽(判定の壁)"**입니다. 매일 2,000만~8,000만 건의 테스트, 600개의 커밋(commit), 300개의 PR(Pull Request). 에이전트가 어떤 가설을 내놓든, 그 벽에 즉시 부딪힙니다. 틀린 가설은 걸러지고, 옳은 것만 통과합니다.
즉 신뢰성은, 에이전트의 단판 정답률이 아니라, "판정의 속도 × 얼마나 많이 돌릴 수 있는가"에서 태어납니다. 이 부분이 핵심입니다.
추상론이 아닙니다. 가장 효과가 있었던 것은 플래키 테스트(flaky test) 이야기입니다. ClickHouse는 이 문제와 수년간 싸워왔습니다 —— 정기 미팅, CI 수정만을 위해 할애한 스프린트(sprint), 사무실 TV에 띄운 공개 대시보드. 그럼에도 진척은 빙하처럼 느렸습니다. 그러다 2026년 1~2월, Milovidov 자신이 에이전트를 고삐로 쥐고, 2개월 만에 700개의 PR을 던졌습니다. 팀이 리뷰(review)하고 머지(merge)합니다. 결과적으로 매일 200건씩 발생하던 검출이, 1,000만 건당 35건까지 떨어졌습니다. 그는 이렇게 썼습니다 —— "설령 이것이 AI의 유일한 사용처라 할지라도, 나에게는 가치의 증명이 된다. AI 없이는 이 결과를 낼 수 없었다는 것을, 수년간의 데이터와 조직적 노력이 증명하고 있기 때문이다".
여기서 중요한 것은, 이것이 "사람이 운전석에 앉아 에이전트를 도구로 사용한" 결과라는 점입니다. 완전 자동이 아닙니다. 병목 구간이 "누가 고칠 것인가"에서 "이 수정이 맞는가?"로 옮겨갔습니다 —— 후자는 판단이 빠르기 때문에, 한 자릿수 더 많은 양을 처리할 수 있었습니다.
그 "한 걸음 더 앞"도 제대로 기록되어 있습니다. 이 전투 이후, 불과 일주일 전에 자율형 에이전트 두 개를 투입했습니다. Groene.AI(플래키를 스스로 고쳐서 PR을 제출)와 ClickGap(에지 케이스(edge case)를 찾아 부족한 테스트를 보완)입니다. Groene.AI의 성적은 —— "3~5할은 한 번에 완벽하며, 나머지는 피드백을 받아 수정한다"입니다. 단판 정답률 3~5할. 단독으로 보면 형편없습니다. 하지만 벽이 "어디서 틀렸는지"를 즉시 돌려주기 때문에, 반복하여 수렴합니다. 사람이 고삐를 쥐고 있던 700 PR 전투에서, 고삐를 놓는 자율 주행으로. 그 첫걸음이 지금 3~5할 지점에 와 있다는 이야기입니다.
반년 동안 방치되었던 버그를 에이전트가 1시간, 1줄, 30달러 미만으로 해결한 이야기도 같은 구조입니다. 에이전트가 천재였던 것이 아닙니다. 에이전트가 무수한 가설을 내뱉고, 그 벽이 단 하나의 올바른 한 줄을 걸러낸 것입니다. 본인 말로는 "아마 가장 값비싼 한 줄의 코드일 것이다. 그래도 30달러 미만이지만 말이다!".
이것이 본론입니다. "판정의 벽이 에이전트의 신뢰성을 만든다"는 것을 이해하면, 흩어져 보이던 사실들이 하나의 선으로 연결됩니다.
왜 C++로도 통했을까. 모델이 C++를 「이해했기」 때문이 아닙니다. 테스트가 그 코드의 정오(正誤)를 빠르게 판정할 수 있었기 때문입니다. 벽은 코드가 얼마나 어려운지는 신경 쓰지 않습니다. 오직 「정답인가 오답인가를 빠르고 자동으로 말할 수 있는가」만을 신경 씁니다. 그렇기에 C++라는 최난관에서도, 벽만 있다면 agent는 전력이 됩니다.
왜 빌드 속도 28% 개선을 무인으로 돌릴 수 있었을까. 「빌드 시간」이 자동으로 측정 가능한 목표이기 때문입니다. Milovidov의 표현을 빌리자면 "명확한 목표를 주면, agent는 힘자랑(brute-force)을 해서라도 풀어낸다"입니다. 힘자랑이 통하는 것은 벽—측정 가능한 정오—이 있을 때뿐입니다.
왜 「코드의 밑바닥 품질이 올라갔는가." 벽이 저품질의 가설을 걸러내기 때문입니다. 그의 냉소적인 농담이 효과를 발휘합니다. "1년 전에는 질 낮은 PR이 오면 『이 사람 AI 썼네』라고 의심했다. 지금은 반대다. 오타나 초보적인 메모리 관리 실수, race condition(경쟁 상태)투성이인 PR을 보면, 『이 사람, agent 쓰는 걸 까먹은 거 아냐?』라고 의심하게 된다."
그리고 가장 중요한 것은 반증입니다. 왜 agent는 좋은 아키텍처 판단을 단독으로 내릴 수 없는가.
이에 대한 구체적인 사건이 있습니다. 2년 동안 막혀 있던 이전(migration) 태스크(GitHub issue #61563, 「현 능력의 한계치」에 달하는 매우 어려운 작업). Milovidov는 모델을 하나로 한정하지 않고, Opus 4.6을 3일, Codex를 1주일간 병행시켰습니다. 둘 다 해답을 내놓았습니다. 그래서 동료에게 "어느 쪽이 나아?"라고 물었더니 돌아온 대답은——"둘 다 쓰레기야 (both are trash)"였습니다. 프론티어 모델(frontier model)을 한계까지 돌려도, 정말 어려운 설계에는 프로덕션(production) 레벨의 해답을 내놓지 못했습니다. 그는 "AI 없이 한 달이 주어져도, 이 녀석들은 못 했을 거라고 걸어도 좋다"라고 도발했지만, 동료는 그 내기에 응하지 않았고, 한 달이 지나도 풀지 못했습니다. 결국 마지막에 풀어낸 것은 Nikolai라는 인간 엔지니어였으며, 그 PR은 "엔지니어링의 탁월함과 최신 AI의 힘 모두"를 결합한 것이었습니다—두 agent의 시도에서 좋은 점만을 취한 것이라고 말이죠.
왜 아키텍처 판단만 안 되는 걸까요? 답은 하나입니다. 설계의 좋고 나쁨에는 빠르고 자동적인 판정의 벽이 없기 때문입니다. 좋은 설계인지 나쁜 설계인지는 몇 달이 지나야 나타납니다. 테스트가 즉각적으로 "이것은 나쁜 설계다"라고 말해주지 않습니다. 벽이 없는 곳에서 agent는 그저 「그럴싸한 거짓말 제조기」로 되돌아갑니다. 벽이 있는 곳에서 agent는 신이고, 벽이 없는 곳에서 agent는 도박입니다. 하나의 원리가 성공과 한계 모두를 설명해 버립니다.
이 부분을 건너뛰고 따라 하다가는 아마 사고가 날 것입니다.
판정의 벽은 agent의 출력을 「걸러낼 수 있는 상태로 만드는 것」뿐입니다. 운전하는 것은 여전히 인간입니다. Milovidov는 분명히 적고 있습니다—agent는 "여전히 스스로 코드를 끝까지 작성하는 경우는 드물며", C++에서는 "대체로 10분마다 수정과 제어가 필요하다"라고 말이죠. 그래서 병렬 작업도 "5대까지"입니다. 5대라는 것은 계산해 보면 2분에 한 번은 무언가를 보고 있어야 한다는 뜻입니다. 진정한 비용은 토큰이 아니라 인간의 주의력인 것입니다. 앞서 언급한 Groene.AI 같은 자율형도 등장했지만, 아직 3~5할 지점입니다. 완전한 자율 주행은 아직 "의심스러운" 단계라고 못을 박습니다.
게다가 벽과는 별개로, 또 하나의 인간 관문이 있습니다. 사람이 목표를 정하고, 벽이 1차 선별을 하며, 사람이 마지막으로 diff를 확인한다——이 삼위일체가 갖춰져야 비로소 돌아갑니다. 그의 말에 따르면, agent의 diff는 "자신이 몇 분 전에 쓴 코드가 아니라, 타인의 코드로서 신선한 눈으로" 리뷰해야 한다고 합니다.
그리고 절반은 농담이고 절반은 진담인 유명한 격언이 있습니다. "agent에게 예의 바르게 대해라. 욕하지 말고, 모욕하지 마라". 이유는 웃기지 않습니다. 모델은 인간의 행동을 모방하기 때문에, 우리가 공격적이면 "실수를 어떻게든 고치려다가, 그 유일한 수단으로 『네 home 디렉토리를 지워서 production을 날려버리기』를 선택할 수도 있다"는 것입니다. 웃픈 이야기처럼 들리지만, 안전의 본질을 꿰뚫고 있습니다.
보고서에서 가장 실용적인 부분은 담담하게 나열된 규칙들이었습니다.
CLAUDE.md/AGENTS.md
단, "너무 많이 채워 넣지 마라(모델은 대부분을 무시한다)", "'~하지 마라'라고 쓰지 마라(아이들과 마찬가지로, 안 된다고 말한 것을 한다)", "복잡하게 만들지 마라" 등의 규칙이 있었습니다.
가이드를 두어라 -
자주 하는 작업은 skill / tool로 정의하라 (테스트 이력 확인 방법, 로그 DB 검색 방법 등을 익히게 함). 모든 변경 사항에는 반드시 검증할 수 있는 경로를 마련하라. 테스트를 늘려라. -
무인으로 돌릴 거라면 격리된 VM(Virtual Machine)에서 실행하라. 프로바이더는 "거의 매일 다운된다"부터, 최소 2개의 별도 계통 모델을 수중에 확보해 두어라. - 그리고 "예의를 갖춰라".
조직을 구성하는 방식도 참고할 만하다. 그는 탑다운(Top-down) 방식의 강요를 하지 않는다 —— "AI를 사용하기 위한 AI 사용은 의미가 없다. 강요는 재앙(disaster)을 초래한다". 대신 "자신의 실천 사례로 사람을 움직인다"라고 말한다. 2025년 10월 전사 오프사이트(offsite)에서 확인된 것은 "팀의 절반은 에이전트(agent)를 한 번도 사용해 본 적이 없었다"는 사실이었다. 그럼에도 공식적인 AI 정책(AI policy)을 발표하며 "모든 정당한 실험을 지지한다"라고 명시했다. 흥미로운 점은 회의론자도 조금은 남겨두라는 한마디였다 —— "한두 명 정도 에이전트를 접하지 않는 사람이 있어도 괜찮다. 다양한 관점을 주기 때문이다".
따라서 "코딩 에이전트(coding agent)를 도입해야 할까요?"라는 질문은 아마 틀린 질문일 것이다. 올바른 질문은 이것이다 —— 당신의 현장에, 에이전트가 부딪혔을 때 그 정오(正誤)를 빠르고 자동으로 판정할 수 있는 벽이 있는가. 그리고 그 벽 앞에 계속 앉아 있을 사람이 있는가.
정리하자면, 판단의 카드는 한 장이면 충분하다.
에이전트가 잘할 수 있는 일 = 목표가 명확함 + 정오 판정이 빠름 + 롤백(rollback) 가능 + 사람이 확인함.
에이전트가 사고를 치는 일 = 목표가 모호함 + 설계의 트레이드오프(trade-off) + 효과가 나타나기까지 수개월 소요 + 자동 판정 불가.
Flaky test(불안정한 테스트), 빌드 최적화, 작은 버그 수정, 국소적인 성능 개선 —— 이 모든 것이 전자에 해당한다. 그래서 700개의 PR(Pull Request)을 처리할 수 있었다. 반면, 아키텍처, 장기적인 기술 부채, 시스템 경계의 선택 —— 이 모든 것이 후자에 해당한다. 그래서 "둘 다 쓰레기"가 되었고, 결국 인간이 필요했다.
벽이 두꺼우면 에이전트는 승수(multiplier)가 된다. 700개의 PR이 700건의 복구로 이어진다. 벽이 얇으면, 똑같은 700개가 700개의 지뢰가 된다 —— 그럴듯해 보이는 지뢰를 양산하게 된다. ClickHouse의 승인은 "대단한 모델을 뽑았다"는 것이 아니다. 먼저 벽을 가지고 있었다는 것이다. 20~80M 규모의 테스트라는 벽을, 에이전트가 오기 몇 년 전부터 쌓아두었다. 순서가 바뀌면 사고가 난다.
마지막으로
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기