우리는 모델을 신뢰하지 않게 되었다. 그다음에는 우리 자신의 수치조차 신뢰하지 않게 되었다.
요약
코딩 에이전트 시스템 구축 과정에서 모델뿐만 아니라 측정 지표(metrics)조차 신뢰할 수 없음을 발견한 경험을 다룹니다. 비결정성(Nondeterminism)을 제거해야 할 버그가 아닌, 시스템의 탐색 능력을 높이기 위해 전략적으로 배치해야 할 요소로 재정의합니다.
핵심 포인트
- 모델의 성능보다 시스템 주변의 측정 도구와 환경의 신뢰성이 더 큰 병목이 될 수 있음
- 검증 도구 자체가 틀린 결과를 성공으로 보고할 수 있는 위험성을 인지해야 함
- 비결정성을 제거하기보다 시스템 내에서 적절한 위치에 배치하는 전략이 필요함
- 결정론적 규칙만으로는 모델의 핵심 가치인 제안과 탐색 능력을 활용할 수 없음
비결정성 (Nondeterminism)은 금지해야 할 버그가 아니라, 배치해야 할 힘이다
ForgeFlow 시리즈의 일부 — M5 Max에서 실행 루프를 로컬로 실행하는 코딩 에이전트를 구축하며, 실제로 무엇이 고장 나는지 기록합니다. 계획 수립은 Claude에서 수행하고, 코드 생성은 Ollama를 통해 로컬 모델에서 실행하며, Docker 샌드박스 내부에서 테스트 주도 방식으로 진행됩니다.
얼마 전 저는 우리가 더 나은 모델을 쫓는 것을 멈췄다고 썼습니다. 이 프로젝트의 경우, 더 강력한 모델로 교체해도 모델 자체가 아닌 모델 주변의 시스템 문제로 인해 문제가 해결되지 않는다는 사실이 밝혀졌기 때문입니다. 그 포스트는 깔끔하게 마무리되었습니다. 병목 현상은 모델이 아니라 시스템이었다는 결론이었죠.
이 포스트는 동일한 의구심을 우리 자신의 측정값(measurements)으로 돌리는 내용입니다. 모델이 정답이라는 믿음을 버리고 나면, 그다음으로 의지하게 되는 것은 바로 자신의 측정값입니다. 즉, 시스템이 작동하고 있는지 알려주는 테스트 횟수, 게이트 통계(gate statistics), 집계 수치들입니다. 그리고 구축 과정을 거치며, 저는 이 수치들 또한 맹목적으로 신뢰할 수 없다는 것을 배웠습니다. 이번 시리즈의 이전 세 개의 포스트는 각각 그러한 발견의 과정이었습니다:
- 잘못된 환경을 측정하면서도 **통과(passed)**한 테스트 스위트.
- 횟수가 더 이상 품질의 증거로 기능할 수 없을 만큼 자주 틀리면서도 198번이나 **차단(blocked)**했던 게이트.
- 실제 숫자는 13인데 12라고 **계산(counted)**한 에이전트.
세 가지 서로 다른 도구였습니다. 하지만 그 밑바닥에는 반복되는 실패의 형태가 있었습니다. 검증을 위해 사용하는 도구 자체가 틀릴 수 있으며, 심지어 성공처럼 보이는 방식으로 틀리는 경향이 있다는 것입니다. 이 포스트는 제가 그 과정에서 얻은 교훈, 그리고 더 중요하게는, 그로부터 거의 도출할 뻔했던 잘못된 결론에 관한 이야기입니다.
잘못된 교훈: "불확실성을 금지하라"
당신이 신뢰했던 측정값에 세 번이나 데이고 나면, 본능적인 반응이 나타납니다. 확실하지 않은 것은 아무것도 믿지 마라. 시스템에서 모든 불확실성(uncertainty)의 근원을 밀어내라. 비결정론(nondeterminism) — 즉, 확률적(probabilistic)인 것, 두 번 실행했을 때 결과가 다르게 나올 수 있는 모든 것 — 을 제거해야 할 결함으로 취급하십시오. 만약 언어 모델(language model)이 불확실한 부분이라면, 언어 모델을 최소화하십시오. 모든 것을 결정론적(deterministic)으로 만들고, 마침내 발 뻗고 잘 수 있다고 스스로를 안심시키십시오.
저도 한동안 그런 방향으로 기울었습니다. 하지만 그것은 틀렸으며, 적어도 유용하다고 하기엔 너무 투박한 방식입니다. "모든 비결정론을 금지하라"는 말을 진지하게 받아들인다면, 모델이 이 시스템에 가져다주는 가장 가치 있는 단 한 가지, 즉 _제안(propose)_하고, _탐색(explore)_하며, 제가 미처 열거하지 못했을 해결책을 제시하는 능력을 버리게 됩니다. 결정론적인 규칙으로부터는 그런 것을 얻을 수 없습니다. 불확실성은 단지 부채(liability)일 뿐만 아니라, 적절한 자리(seat)에 있다면 그것이 바로 존재의 목적이기도 합니다.
그래서 질문은 "어떻게 불확실성을 제거할 것인가"에서 "불확실성이 어디에 위치해야 하는가?"로 바뀌었습니다.
더 나은 교훈: 금지하지 말고 배치하라
여기에 제가 깨달은, 그리고 유효하다고 판명된 재정의(reframing)가 있습니다. 이 사실을 깨닫기까지 부끄러울 정도로 오랜 시간이 걸렸는데, 부분적으로는 제가 비결정론을 그동안 확인도 없이 마치 갚아야 할 부채처럼 조용히 가정해 왔기 때문입니다.
이와 같은 시스템에는 두 종류의 자리가 있습니다.
제안하고 탐색하는 자리. 다음에 무엇을 시도해야 할까? 이 실패의 원인은 무엇일까? 해결책의 후보는 무엇인가? 이러한 자리들은 비결정론(nondeterminism)을 원합니다. 가능성을 생성하는 확률적 모델(probabilistic model)은 여기서 위험 요소가 아니라 기능(feature)입니다. 만약 모델이 가끔 틀리더라도 그 비용은 낮습니다. 제안만 하는 단계에서는 틀려도 괜찮기 때문입니다. 왜냐하면 후속 단계(downstream)에서 여전히 당신의 제안을 승인해야 하기 때문입니다.
판단하고 기록하는 자리 (Seats that judge and record). 테스트가 실제로 통과했는가? 이것이 통과되어도 괜찮은가? 무엇이 사실로 기록되는가? 이러한 자리(seats)는 책임 소재가 불분명한 입력을 용납할 수 없습니다. 이 자리들은 결정론적(deterministic)이고, 재현 가능(reproducible)하며, 검증 가능(checkable)해야 합니다. 왜냐하면 바로 이 지점이 "거의 맞음"이 "맞음"과 구별할 수 없게 되는 지점이며, 이것이 바로 지난 세 개의 포스트가 계속해서 빠졌던 함정이기 때문입니다.
세 가지 실패 사례는 모두 동일한 형태를 띠었습니다. 최종 권한을 가져서는 안 될 무언가가 판단하는(judging) 자리에 스며들었다는 점입니다. 오염된 환경은 고정되지 않은 변수(unpinned variable)가 판결을 내리게 방치했습니다. 잘못 보정된 게이트(gate)는 검증되지 않은 휴리스틱(heuristic)이 판단을 내리고 유효한 작업을 거부하게 만들었습니다. 에이전트의 자기 보고(self-report)는 확률적 카운터(probabilistic counter)가 숫자에 대한 최종 결론을 내리게 할 뻔했습니다. 모든 경우에서 해결책은 시스템 전체에서 불확실성을 제거하는 것이 아니었습니다. 그것은 잘못된 것을 판단하는 자리에서 몰아내고, 그 자리가 결정론적이고, 고정되어 있으며, 증명 가능한(witnessable) 무언가에 의해 유지되도록 만드는 것이었습니다.
결과적으로 비결정론(Nondeterminism)은 높이거나 낮출 수 있는 시스템의 속성이 아닙니다. 그것은 _배치해야 할 힘(force to be placed)_입니다. 제안과 탐색이 이루어지는 앞단(front)에서는 비결정론이 작동하도록 두십시오. 하지만 판단과 기록이 이루어지는 뒷단(back)에서는 그것을 차단해야 합니다. 모델은 제안하고, 결정론적인 체크(deterministic check)가 결정합니다. 이 단 하나의 분리가 이번 과정에서 이루어진 해결책들을 연결하는 실타래가 되었습니다.
이것이 왜 단순히 "결정론적인 것을 더 신뢰하라"는 뜻이 아닌가
이 모든 내용을 "결정론적인 것은 선(good)이고, 확률적인 것은 악(bad)이다"라고 읽고 싶은 유혹이 들 것입니다. 하지만 그렇지 않으며, 그 차이는 매우 중요합니다.
제안하는 자리에 있는 확률적인 제안(probabilistic suggestion)은 결정론적인(deterministic) 제안보다 더 가치 있습니다. 왜냐하면 규칙이 도달할 수 없는 영역에 도달할 수 있기 때문입니다. 그리고 결정론적인 검증(deterministic check)은 그것이 실제로 정확하고 검증 가능한지 여부에 따라 그 가치가 결정됩니다. 두 번째 포스트의 게이트는 결정론적이었음에도 불구하고 여전히 많은 경우에 틀렸습니다. 일관되게 틀리는 결정론적인 판정관은 동전 던지기보다 더 나쁠 수 있는데, 왜냐하면 그것은 결국 의심을 멈추게 되는 지속적인(steady) 오류이기 때문입니다. 따라서 결정론이 미덕이고 불확실성이 죄악이라는 뜻은 아닙니다. 그것들은 서로 다른 위치에 속해 있으며, 전체 엔지니어링 문제는 이들을 제대로 분류하여 유지하는 것입니다.
불확실한 것은 탐색하게 하라. 결정론적인 검증이 판단하게 하라 — 단, 검증 자체에 대한 검증이 이루어진 후에만 그러해야 한다.
이것을 설명하는 데 네 개의 포스트가 필요했고 꽤 많은 시행착오를 겪은 이유는, 실패가 자신이 어느 범주에 속하는지 알려주지 않기 때문입니다. 조용히 틀린 측정값은 직접 확인하기 전까지는 정확한 측정값과 똑같이 보입니다. 분류는 자동으로 이루어지지 않습니다. 당신은 도구 하나하나를 사용하여 의도적으로 분류해야 하며, 보통 당신이 신뢰했던 숫자가 알고 보니 처음부터 문제였다는 사실을 알게 되었을 때야 비로소 틀렸음을 깨닫게 됩니다.
이것이 증명하지 못한 것
저는 이 시리즈를 제가 전체 글을 써온 방식대로 — 부풀리지 않고 — 마무리하고 싶습니다.
이것은 하나의 시스템에 도움이 되었던 프레임워크입니다. 즉, 제가 관찰할 수 있는 결정론적인 검증에 판정 자리를 고정할 수 있는 사치를 누릴 수 있었던, 테스트 주도 루프(test-driven loop)를 가진 로컬 AI 코딩 에이전트(local AI coding agent) 말입니다. 저는 이것이 모든 AI 시스템에 적합한 분해 방식임을 증명하지 않았으며, "비결정론을 금지하지 말고 배치하라"를 보편적인 법칙으로 만드는 사람 — 저를 포함해서 — 을 경계할 것입니다. 이것은 작동하는 관점(lens)이지, 확립된 결과가 아닙니다. 그 이면의 근거는 통제된 연구가 아니라, 정직하게 보고된 몇 가지 사례들입니다.
또한 이것은 어려운 문제, 즉 "제안(propose)"과 "판단(judge)" 사이의 경계가 항상 명확하지는 않다는 점을 해결해주지는 않습니다. 수많은 실제 의사결정은 이 둘의 혼합입니다. 불확실한 증거를 함께 고려해야 하는 판단이거나, 다른 무엇인가가 투표를 거치기도 전에 조용히 당신을 무언가에 구속시키는 제안인 식입니다. 결정론적 검증(deterministic check)을 정확히 어디에 배치할 것인지, 그리고 확률론적 부분(probabilistic part)이 판단 그 자체가 되지 않으면서도 판단에 어느 정도까지 영향을 미치게 할 것인지는 제가 여전히 고민하고 있는 문제입니다. 이전 포스트의 열린 질문인—인간이 목격한 검증이 언제 신뢰할 수 있는 자동화된 검증으로 승격될 수 있는가—는 이와 동일한 미해결 영역의 일부입니다. 제가 이 관점(lens)을 공유하는 이유는 이것이 저에게 혼란을 정리해 주었기 때문이지, 이것이 완성되었기 때문은 아닙니다.
전체 연재의 핵심 요약
네 개의 포스트, 하나의 흐름. 우리는 더 나은 모델이 우리를 구원할 것이라는 믿음을 멈췄습니다. 그다음 우리는 우리 자신의 측정치 또한 맹목적으로 신뢰하지 않는 법을 배웠습니다. 통과된 테스트도, 바쁜 게이트(gate)도, 에이전트(agent)의 깔끔한 수치도 믿지 않게 되었습니다. 그 모든 의구심 속에서 저에게 견고하게 버틸 수 있음을 증명한 단 하나의 원칙은 다음과 같습니다:
이러한 시스템에서, 신뢰를 부여하는 모든 계층은 신뢰하기 전에 먼저 측정되어야 하며, 그 측정은 가능한 한 당신이 직접 목격할 수 있는 결정론적인(deterministic) 무언가에 근거해야 합니다.
그것이 전부입니다. 모델도 아니고, 프레임워크도 아니며, 영리한 아키텍처(architecture)도 아닙니다. 바로 설 수 있는 지점입니다. 모델, 게이트, 집계, 그리고 우리 자신의 수치를 의심한 끝에, 제가 다음 단계를 구축하기 위해 충분히 단단하다고 발견한 유일한 것입니다.
이것으로 이 짧은 연재를 마칩니다. 그래서 저는 보다 포괄적인 질문을 던지려 합니다. AI를 루프(loop)에 포함하여 시스템을 구축하는 분들에게 묻습니다. 불확실성을 허용할 부분과 결정론적(deterministic)이어야 한다고 고집할 부분 사이의 선을 어디에 긋습니까? 그리고 그 선을 올바른 위치에 그었는지 어떻게 확인합니까? 저는 일련의 실수들을 통해 하나의 답에 도달했습니다. 저는 저의 다음 실수를 통해 배우기보다 다른 사람들의 경험을 통해 다음 것을 배우고 싶습니다.
이번 실행을 팔로우해 주셔서 감사합니다. 로컬 에이전트(local agent) 자체에 대한 내용, 우리가 왜 모델을 쫓는 것을 멈췄는지에 대한 내용, 그리고 규모가 커질 때 무엇이 깨지는지에 대한 이전의 ForgeFlow 포스트들은 제 프로필에서 링크로 확인하실 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기