이것이 확정적인 해결책입니다
요약
Kubernetes Operator 개발 중 발생한 레이스 컨디션 문제를 해결하며 겪은 LLM의 한계를 다룹니다. LLM은 구체적인 맥락이 결여될 경우 잘못된 해결책을 확신을 가지고 제시하며, 자율 에이전트 환경에서는 오히려 코드베이스를 망가뜨릴 위험이 있음을 경고합니다.
핵심 포인트
- LLM은 맥락 특화적 동작에 대해 잘못된 해결책을 확신하며 제시할 수 있음
- 인터넷 검색 기능이 LLM의 환각이나 잘못된 적용을 막아주지 못함
- 복잡한 디버깅은 모델이 아닌 인간의 근본 원인 분석이 선행되어야 함
- 인간의 개입 없는 에이전트 흐름은 코드베이스를 스파게티로 만들 위험이 있음
LLM (Large Language Model)이 할 수 있는 가장 위험한 말은 다음과 같습니다:
"이것이 확정적인 해결책입니다."
제가 그렇게 말하는 이유는, 동일한 버그에 대해 매번 다른 수정 방법을 제시하며 이 말을 연속으로 여섯 번이나 들었기 때문입니다.
저는 Kubernetes Operator를 구축하던 중 reconcile loop (조정 루프)에서 race condition (경쟁 상태)에 직면했습니다.
Operator가 커스텀 리소스의 상태를 업데이트하면, 아직 플러시 (flush)되지 않은 이전 상태에 의해 즉시 덮어씌워지는 현상이 발생했습니다. 그 결과 phase transition loop (단계 전환 루프)가 발생하여, 리소스가 안정화되지 못한 채 상태를 끝없이 순환했습니다.
저는 LLM에 의존했습니다. 인터넷 검색 기능이 활성화되어 있었고, 전체 컨텍스트 (context)도 제공된 상태였습니다.
첫 번째 제안은 자신감 넘치고 구체적이었습니다. 동시 조정 (concurrent reconciliation)을 처리하기 위한 패턴이었고, 합리적으로 보였습니다. 시도해 보았지만, 작동하지 않았습니다.
두 번째 제안은 더 깊게 파고들어 controller runtime 내의 서브 함수 (sub-function)를 제시했습니다. 이 역시 자신감 넘쳤고, 구체적이었으며, 역시 틀렸습니다.
네 번째나 다섯 번째 반복에 이르자, 모델은 Kubernetes 내부 구조의 점점 더 모호한 구석으로 빠져들기 시작했습니다. 매번 다음과 같은 어조를 유지하면서 말이죠:
"이것은 Kubernetes Operator에서 흔히 발생하는 race condition입니다. 이것이 확정적인 해결책입니다."
모델은 거짓말을 하고 있는 것이 아니었습니다. 존재하지 않는 함수를 환각 (hallucination)하고 있는 것도 아니었습니다. 모델은 실제 패턴, 실제 API, 실제 Kubernetes 동작을 찾아내고 있었지만, 그 모든 것을 저의 구체적인 맥락에 완전히 확신을 가지고 잘못 적용하고 있었던 것입니다.
인터넷 검색은 도움이 되지 않았습니다. 그저 모델이 틀린 답을 내놓을 수 있는 더 많은 근거를 제공할 뿐이었습니다.
결국 문제를 해결한 것은 모델과 아무런 관련이 없었습니다.
저는 질문을 멈췄습니다. 직접 조사를 수행하고, controller-runtime 소스 코드를 읽었으며, 덮어쓰기를 유발하는 특정 동작을 찾아냈고, 제 reconcile loop에서 발생하는 정확한 이벤트 순서를 이해했습니다. 그런 다음 근본 원인에 대한 명확하고 근거 있는 설명과 수정을 위한 명시적인 지침을 가지고 모델에게 다시 돌아갔습니다.
그제야 즉시 작동했습니다.
모델이 문제를 해결한 것이 아닙니다. 제가 문제를 해결했습니다. 모델은 코드를 작성했을 뿐입니다.
이 차이는 대부분의 사람들이 인정하고 싶어 하는 것보다 훨씬 더 중요합니다.
이제 에이전트 흐름 (agentic flow)을 추가했을 때 어떤 일이 발생하는지 생각해 보십시오.
인간의 개입 (human in the loop)은 없습니다. 모델은 동일한 종류의 문제에 직면합니다. 미묘한 레이스 컨디션 (race condition), 즉 학습 데이터만으로는 올바르게 추론할 수 없는 컨텍스트 특화적 동작 (context-specific behavior) 같은 것 말입니다. 모델은 해결책을 생성합니다. 그것을 실행합니다. 출력을 관찰합니다. 해결책이 작동하지 않았다고 판단하고 더 깊은 시도를 합니다.
모델은 이를 자율적으로 수행합니다. 자신감 있게. 반복적으로.
매 반복마다 모델은 코드베이스 (codebase)의 더 깊은 곳으로 들어갑니다. 여기서는 리팩터링 (refactoring)을 하고, 저기서는 추상화 계층 (abstraction layer)을 추가합니다. 한 곳에서 증상을 패치(patching)하는 동안 다른 곳에서는 새로운 증상을 유발합니다. 매 단계마다 토큰 (tokens)을 태웁니다.
인간이 출력을 확인하려 할 때쯤이면, 코드베이스는 스파게티처럼 엉망이 되어 있고 원래의 버그는 자신감 넘치고 선의를 가졌으나 완전히 잘못된 여섯 단계의 변경 사항 아래에 파묻혀 여전히 남아 있습니다.
모델이 실패한 이유는 멍청해서가 아닙니다. 적절한 컨텍스트 (context) 없이는 근본적으로 알 수 없는 무언가에 대해 확신했기 때문입니다. 그리고 그 확신에 따라 빠르고 반복적으로 행동하는 것을 막을 수 있는 것은 아무것도 없었습니다.
이것이 데모 영상에서는 보여주지 않는 에이전트형 AI (agentic AI) 개발의 이면입니다.
그 능력은 실재합니다. 생산성 향상도 실재합니다. 하지만 자율적 실행 (autonomous execution)은 올바른 판단과 잘못된 판단을 똑같이 증폭시킵니다. 채팅 세션에서 개발자의 시간을 30분 낭비했을 모델이, 에이전트 루프 (agentic loop)에서는 3시간의 컴퓨팅 자원을 낭비하고 코드베이스를 훨씬 더 나쁜 상태로 만들 수 있습니다.
해결책은 에이전트 워크플로 (agentic workflows)를 피하는 것이 아닙니다. 모델이 어디에서 실패하는지 이해하고, 바로 그 지점에 인간의 체크포인트 (human checkpoints), 그라운딩 단계 (grounding steps), 그리고 컨텍스트 주입 (context injection)을 구축하는 것입니다.
저는 레이스 컨디션을 하나씩 겪으며 이 교훈을 어렵게 배웠습니다.
에이전트 워크플로가 문제를 해결하기 전에 오히려 악화시키는 것을 본 적이 있습니까? 당신은 어떤 가드레일 (guardrails)을 구축했습니까?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기