코딩 에이전트는 왜 작동하고 왜 무너지는가

같은 모델이다. 웹 채팅에서 hallucinate하던 그 모델이, Claude Code에서는 200줄짜리 기능을 한 번에 올린다. Codex의 /goal은 이슈 하나를 통째로 해결한다. 모델이 갑자기 똑똑해진 게 아니다. 달라진 건 구조다.

왜 작동하는가

대화형 AI의 루프는 이렇다:

LLM → 사람 → LLM → 사람

피드백이 전부 자연어다. 확률적 생성에 확률적 평가가 이어진다. 정확도가 곱으로 열화된다.

코딩 에이전트의 루프는 다르다:

LLM → 코드 생성 → 파일 저장 → 테스트 실행 → pass/fail → LLM
LLM → 코드 수정 → 빌드 → 성공/실패 → LLM
LLM → 타입 체크 → 오류 메시지 → LLM

루프 안에 결정론적 게이트가 끼어있다. 파일시스템은 쓴 그대로 저장한다. 테스트는 pass 아니면 fail이다. 컴파일러는 틀리면 틀렸다고 한다. 이것들이 의도치 않게 래칫 역할을 한다.

LLM은 unreliable component다. 하지만 unreliable component 위에 reliable protocol을 올리는 건 공학의 기본이다. TCP는 unreliable network 위에서 reliable delivery를 만든다. RAID는 unreliable disk 위에서 reliable storage를 만든다. ECC는 unreliable memory 위에서 reliable computation을 만든다.

코딩 에이전트가 작동하는 이유는 같다. unreliable LLM 위에 deterministic verifier(테스트, 빌드, 린터, 타입 체커)를 올렸기 때문이다. 모델 성능이 아니라 topology가 성공의 원인이다.

그런데 왜 무너지는가

작동한다고 했다. 그런데 종종 무너진다. 왜?

래칫이 우연히 끼어있는 것과 의식적으로 설계된 것은 다르기 때문이다.

래칫이 없는 구간이 존재한다

테스트가 없는 코드를 에이전트가 수정하면? 빌드는 통과하고, 린트도 통과하고, 그런데 기능은 망가져 있다. 결정론적 게이트가 없는 구간에서는 LLM이 확률적으로 판단하고, 확률적 판단은 곱으로 열화된다.

200 엔드포인트 중 180개에는 테스트가 있고 20개에는 없다. 에이전트는 180개를 완벽하게 처리하고, 20개에서 조용히 버그를 심는다. “거의 다 됐는데 어딘가 이상하다"가 되는 이유다.

피드백의 정보량이 부족하다

1000개 단어를 정렬하는 실험을 했다. CPU는 0.08ms에 100%. LLM은 438초에 97.7%. 그 자체로 놀랍다 — 순수 인지로 97.7%라니. 하지만 진짜 발견은 다른 곳에 있었다.

같은 결과에 대해 피드백 수준만 달리해봤다:

피드백결과
없음6개 오류 (99.4%)
“오류가 있다”10개 오류 (99.0%) — 악화
“23개 오류가 있다”1개 오류 (99.9%)
“6개, 여기에 있다”0개 오류 (100%)

“틀렸다"만 알려주면 과잉 수정으로 오히려 나빠진다. 오류 개수를 알려주면 목표치가 생겨서 집요하게 찾는다. 위치까지 알려주면 완벽하게 고친다.

지금의 에이전트는 대부분 두 번째 수준에 머물러 있다. 테스트가 실패하면 “뭔가 틀렸다"는 알지만, 왜 틀렸는지의 구조적 이유까지는 전달하지 않는다. 에러 메시지가 있긴 하지만, 그것은 원인이 아니라 증상이다.

사각지대가 존재하고, 반복으로 해결되지 않는다

정렬 실험에서 LLM은 R2에서 6개 오류를 남겼다. R3에서 “오류 없음"이라고 보고했다. R4b에서도 “오류 없음"이라고 보고했다. 같은 6개를 같은 방식으로 놓쳤다.

힌트 없이는 몇 번을 반복해도 99.4%에서 수렴했다. “6개 남아있다"고 알려주자 비로소 100%를 달성했다.

코딩 에이전트에서도 같은 일이 벌어진다. 에이전트가 버그를 만들고, self-review로 “문제없다"고 판단하고, 다시 고치라고 해도 같은 곳을 놓친다. retry가 해결책이 아닌 이유다. 사각지대는 모델의 확률적 특성에서 오는 구조적 한계이지, 노력 부족이 아니다.

스케일에서 곱셈이 작동한다

97.7% 정확도의 단계를 두 번 체이닝하면 0.977² = 95.4%. 세 번이면 93.2%. 열 번이면 79.2%.

에이전트가 파일 하나를 수정하는 건 잘한다. 하지만 100개 파일에 걸친 리팩토링을 시키면? 각 단계가 97%라도, 100단계를 거치면 0.97¹⁰⁰ = 4.8%. 사실상 실패가 보장된다.

이것이 “vibe coding이 200 엔드포인트에서 무너진다"의 수학적 설명이다. 작은 프로젝트에서는 체이닝 횟수가 적어서 확률이 버텨주고, 큰 프로젝트에서는 곱셈이 파멸적으로 작동한다.

무엇이 필요한가

작동하는 이유와 무너지는 이유가 같은 곳을 가리킨다: 결정론적 검증 게이트의 유무.

지금의 에이전트는 우연히 끼어있는 래칫(테스트, 빌드, 린터)에 의존한다. 이것을 의식적으로 설계하면 더 강해진다.

래칫을 의식적으로 설계한다는 것:

첫째, 래칫이 없는 구간을 식별한다. 테스트가 없는 코드, 스키마가 없는 API, 타입이 없는 데이터. 에이전트가 확률적으로 판단하고 있는 모든 곳이 취약점이다.

둘째, 피드백의 정보량을 높인다. pass/fail만 돌려주면 과잉 수정을 유발한다. “어디서, 왜, 무엇이 기대와 다른지"를 구조화해서 전달해야 한다.

셋째, 체이닝 중간에 결정론적 게이트를 끼운다. 10단계를 한 번에 돌리면 곱셈이 파멸적이지만, 매 단계마다 래칫으로 고정하면 열화가 리셋된다.

LLM은 놀라운 생성기다. 1000개 단어를 순수 사고로 97.7% 정확하게 정렬한다. 인간도 못 할 일이다. 하지만 100%가 아닌 모든 것은 반복하면 무너진다. 0.977을 제곱하면 0.954다.

코딩 에이전트가 작동하는 건 모델이 똑똑해서가 아니다. 루프 안에 결정론적 게이트가 끼어있기 때문이다. 무너지는 건 그 게이트가 빠져있기 때문이다.

생성은 확률적이어도 된다. 검증은 결정론적이어야 한다.


관련 글