AI 도구를 선택하는 규칙을 게시했는데, 한 댓글 작성자가 더 나은 버전으로 다시 써주었습니다.
요약
AI 코딩 에이전트 기능 구현 시 '가벼운 도구 우선' 원칙과 '실패 관측성' 사이의 트레이드오프를 다룹니다. 작업의 가역성(reversibility)을 기준으로 가벼운 도구와 구조화된 도구를 선택하는 새로운 기준을 제시합니다.
핵심 포인트
- 가벼운 도구는 컨텍스트 비용을 낮추지만 디버깅이 어려울 수 있음
- 실패 관측성을 높이기 위해 복잡성을 미리 지불해야 하는 시점이 존재함
- 도구 선택의 핵심 트리거는 에러 유형이 아닌 작업의 가역성임
- 롤백이 불가능한 쓰기 작업에는 무겁고 구조화된 도구가 필요함
몇 주 전, 저는 깔끔한 규칙이 담긴 포스트를 게시했습니다. AI 코딩 에이전트(AI coding agent)에 기능을 추가할 때는 가장 가벼운 옵션을 먼저 고려하십시오. CLI(Command Line Interface)보다는 프로시저 파일(procedure file)을, 무거운 통합(integration)보다는 CLI를 먼저 선택하고, 재사용성이 증명된 후에야 비로소 무거운 장치를 구축하십시오. 제 논거의 핵심은 컨텍스트 비용(context cost)에 있었습니다. 무거운 옵션들은 처음에 많은 정의(definitions)를 로드하고 매 턴마다 이를 유지하기 때문에, 가볍게 시작하는 것이 컨텍스트 윈도우(window)를 깨끗하게 유지해 줍니다.
저는 여전히 앞부분의 논리는 맞다고 생각합니다. 하지만 지금 다시 쓴다면 이 규칙을 그대로 쓰지는 않을 것입니다. 한 독자가 댓글에서 제 규칙을 분석하여 더 나은 형태로 돌려주었기 때문입니다. 이 포스트는 그 교환에 관한 것입니다. 왜냐하면 그 재작성된 규칙이 제 원본보다 더 날카로웠으며, 제가 혼자서 그 결론에 도달했다고 가장하는 것은 거짓일 뿐만 아니라 덜 흥미로운 이야기가 될 것이기 때문입니다.
댓글 하나에서 발견된 허점
첫 번째 댓글은 규칙 자체에 반박하지 않았습니다. 대신 곧바로 사각지대(blind spot)를 짚어냈습니다. 도구가 외부 요소나 상태가 있는(stateful) 무언가에 접촉하는 순간, '가벼운 것 우선' 원칙은 역효과를 냅니다. 중간에 조용히 실패하는 가벼운 호출은 실패를 깔끔하게 드러내는 무거운 도구보다 디버깅하기가 더 어렵습니다. 복잡성(complexity)을 미리 지불하십시오.
제 첫 본능은 방어하는 것이었고, 실제로 조금 방어했습니다. 저는 우리가 서로 다른 것을 측정하고 있다고 말했습니다. 저는 컨텍스트 비용(context cost)에 최적화한 반면, 그들은 실패 관측성(failure observability)에 최적화한 것이며, 둘 다 실재하는 서로 다른 축이라고 주장했습니다. 저는 가벼운 호출을 감싸서(wrap) 명시적으로 실패하게 만들 수 있으므로, 저렴한 경로를 계속 유지할 수 있다고 지적하며 제 입장을 고수했습니다.
그 말은 사실이었지만 그들의 논점과는 거리가 멀었고, 그들은 제가 그 뒤에 숨도록 내버려 두지 않았습니다.
규칙을 변화시킨 질문
그들은 제 포스트 전체보다 더 큰 울림을 주는 질문 하나를 던졌습니다. 복잡성을 미리 지불하게 만드는 실제 트리거(trigger)는 무엇입니까? 상태(state)의 유형입니까, 아니면 에러(error)의 클래스입니까?
그 질문을 붙잡고 고민하는 과정에서 저만의 규칙이 바뀌었습니다. 솔직한 답변은 상태 유형 (state type)입니다. 그리고 제가 그 말을 입 밖으로 내뱉는 순간, 규칙의 핵심은 컨텍스트 비용 (context cost)이 아니게 되었습니다. 실패를 비용이 많이 들게 만드는 것은 에러 (error)가 아닙니다. 그것은 작업이 종료되기 전에 되돌릴 수 없는 무언가를 변경했는지 여부입니다. 읽기 (read) 작업에서의 조용한 실패 (silent failure)는 짜증스러운 일일 뿐입니다. 하지만 쓰기 (write) 작업 도중에 발생하는 동일한 실패는, 이제 당신이 재구성해야만 하는 '절반만 변경된 세상'을 의미합니다.
따라서 진짜 트리거 (trigger)는 도구 (tool)도 아니었고, 심지어 에러 (error)조차 아니었습니다. 그것은 가역성 (reversibility)이었습니다. 만약 부분적인 실패 (partial failure)가 깔끔하게 롤백 (roll back)할 수 없는 커밋된 (committed) 무언가를 남긴다면, 그 지점이 바로 컨텍스트 (context) 측면에서 가벼운 버전이 아무리 저렴해 보였을지라도, 더 무겁고 구조화된 실패 (structured-failure) 도구가 그 가치를 증명하는 지점입니다. 상태가 없는 (stateless) 작업이나 멱등성 (idempotent)이 있는 작업은 가볍게 유지되며 크게 실패해도 괜찮습니다. 하지만 상태를 변경하는 (mutating) 비멱등적 (non-idempotent) 작업은 사전에 깔끔한 실패 표면 (failure surface)을 확보해야 합니다.
그 후 그들은 제가 2,000단어를 써서 해낸 것보다 더 훌륭하게 결론을 내렸습니다: "대부분의 에러 클래스 (error classes)는 무언가가 기록되었는지 묻기 전까지는 복구 가능한 것처럼 보이지만, 그 시점에는 분류 체계 (taxonomy)는 방해 요소일 뿐이며 당신은 그저 상태 (state)를 분류 (triaging)하고 있을 뿐이다." 저는 그 이후로 줄곧 그 문장을 스스로에게 인용하고 있습니다. 그것은 제 것이 아니라 그들의 것이며, 이 글 전체에서 가장 명료한 부분입니다.
같은 세 단어, 다른 엔진
저를 당혹스럽게 만든 것은 이것입니다. 제가 게시했던 규칙은 "컨텍스트 비용 (context cost)에 따라 가장 가벼운 것부터"였습니다. 제가 유지한 규칙은 "부분적인 실패가 되돌릴 수 없는 상태 (state)를 남길 때까지 가장 가벼운 것부터"였습니다. 겉모습은 동일하지만, 그 아래에 깔린 엔진은 완전히 다릅니다.
컨텍스트 비용 (context cost)은 복구 가능합니다. 도구를 연결하고, 측정하고, 나중에 연결을 해제하면 그만이며 아무런 해가 없습니다. 3단계에서 조용히 실패한 되돌릴 수 없는 쓰기 (write) 작업은 그런 식으로 복구할 수 없습니다. 피해가 발생한 후에야 그것을 발견하게 됩니다. 따라서 제가 처음에 동일하다고 불렀던 두 축은 결코 동일하지 않았으며, 저는 저도 모르는 사이에 실타래를 따라 더 약한 축에서 더 강력한 축으로 조용히 옮겨가고 있었습니다.
우리는 마지막 부분에 한 층을 더 추가했는데, 이것이 현재 제가 가장 많이 생각하는 부분입니다. 가역성 임계값 (reversibility threshold)을 넘어서더라도, 오류가 발생하는 시점에는 나타나지 않는 비용이 존재합니다. 행위 자체는 기술적으로 가역적 (reversible)일 수 있지만, 신뢰는 그렇지 않은 경우가 많습니다. 데이터베이스를 아무리 되돌린다 해도, 에이전트 (agent)가 자신이 중요하게 생각하는 경계를 넘어 무언가 잘못하는 것을 지켜본 사람의 신뢰는 같은 일정에 맞춰 회복되지 않습니다. 그 비용은 몇 번의 스프린트 (sprint)가 지난 후, 누군가가 에이전트가 생성하는 모든 것을 조용히 수동으로 확인하기 시작할 때 뒤늦게 찾아옵니다. 롤백 (rollback)으로는 이를 되돌릴 수 없습니다. 제가 글을 게시했을 때는 이런 생각이 없었습니다. 이 생각은 우리가 끝났다고 생각했을 때 누군가가 계속해서 밀어붙였기에 존재하게 되었습니다.
내가 원본 게시물을 그대로 둔 이유
이 모든 내용을 원본에 통합하고 그냥 넘어갈 수도 있었습니다. 하지만 그렇게 하지 않았는데, 그 이유는 수정된 규칙 자체가 흥미로운 결과물이 아니기 때문입니다. 수정 과정이 바로 흥미로운 지점입니다.
깔끔한 규칙은 마치 처음부터 완성된 형태로 나타난 것처럼 읽힙니다. 제 것은 그렇지 않았습니다. 제 규칙에는 실제적인 구멍이 있었고, 한 독자가 댓글 하나로 그것을 찾아냈으며, 네다섯 번의 대화가 오간 뒤에 그것은 제가 처음 배포했을 때는 전혀 그렇지 않았던 방식으로 핵심적인 지지대 역할을 하게 되었습니다. 만약 제가 조용히 결론을 바꾸고 뒷정리를 한다면 이 과정은 전혀 드러나지 않을 것입니다. 하지만 그 이음새 (seams)가 바로 유용한 부분입니다. 이음새는 자신감 있게 들리는 규칙이 정확히 어느 지점에서 취약했는지를 표시하며, 그 규칙을 단단하게 만들 만큼 충분한 압력을 가하는 질문이 어떤 종류인지를 보여줍니다. 이음새를 갈아내어 없애버리는 것은 볼 가치가 있는 단 한 가지를 숨기는 일이 될 것입니다.
또한 이것은 게시 (publishing)란 무엇인가에 대한 제 생각을 재정립해주었습니다. 예전에는 포스트를 제가 완성한 뒤, 댓글에서 방어해야 하는 무언가로 취급했습니다. 하지만 이번 사례는 제가 시작하고 다른 사람이 완성하도록 내버려 두는 방식이 더 효과적이었습니다. 댓글 섹션은 결론에 반응하는 관객이 아니었습니다. 그것은 게시 후에, 제가 있는지도 몰랐고 영입하지도 않았던 협업자에 의해 작성된 초안의 후반부였습니다.
내가 유지하는 것
두 가지가 있으며, 그중 하나만이 도구에 관한 것입니다.
도구에 관한 것: '가장 가벼운 것을 우선(lightest first)' 원칙은 여전히 나의 기본값이지만, 더 무거운 도구로 넘어가는 트리거(trigger)는 컨텍스트(context)가 아니라 가역성(reversibility)이며, 롤백(rollback)으로 해결할 수 없는 신뢰(trust)에 대한 두 번째 필터가 존재합니다. 이것은 내가 게시했던 규칙보다 더 나은 규칙이며, 그중 더 나은 절반은 내 것이 아닙니다.
다른 하나는 인정하기 더 어렵습니다. 내 글에서 가장 유용했던 아이디어는 글을 게시한 후에, 나에게 아무런 빚도 없는 누군가로부터, 내가 방어하기 위해 소음(noise)으로 치부해버릴 수도 있었던 스레드(thread)에서 나왔습니다. 만약 내가 그 규칙을 완벽하게(airtight) 출시했다면, 아무도 그 틈새를 찾아내지 못했을 것입니다. 붙잡을 틈새가 없었을 테니까요. 그 구멍이 바로 초대장이었습니다. 그래서 나는 반박할 수 없는 것들을 게시하려고 노력하는 것을 그만두었습니다. 낯선 사람들이 닿을 수 있는 곳에 놓인, 눈에 보이는 결함이 있는 깔끔한 규칙은 내가 갖지 못한 관점과 나 혼자서는 도달할 수 없는 교정 사항들을 끌어들입니다. 완벽해지기 전에 출시하세요. 틈새를 드러내 두세요. 되돌아오는 버전이 대개 간직할 가치가 있는 버전이며, 솔직히 말하자면 그것은 대개 온전히 당신의 것이 아닙니다.
나는 WordPress 플러그인을 제작하며 https://raplsworks.com/에서 AI 도구 및 보안에 관한 글을 씁니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기