AI 에이전트가 프로덕션에 병합되도록 허용한 경험
요약
AI 에이전트가 코드 생성부터 테스트, 배포까지 전체 파이프라인을 자동화하는 경험을 공유합니다. 저자는 모든 단계에 대한 신뢰도가 높아지자, 마지막 '병합(Merge)' 단계마저 에이전트에게 맡겼습니다. 그러나 프로덕션 환경에서 발생한 실제 장애를 통해, 아무리 완벽해 보이는 자동화된 폐쇄 루프라도 인간의 최종적인 책임과 판단이 필요한 결정적 순간이 있음을 깨달았습니다.
핵심 포인트
- AI 에이전트는 코드 생성부터 배포까지 파이프라인을 자동화할 수 있다.
- 자동화는 '행복한 경로(happy path)'만 테스트하는 경향이 있어 취약점이 발생한다.
- 가장 중요한 것은 기술적 오류가 아닌, 시스템의 최종적인 책임과 인간의 개입 지점이다.
올해 저는 거의 전체 파이프라인을 자동화했고, 이 상태를 유지하기 위해 싸울 것입니다.
이제 하나의 에이전트가 대부분의 변경 사항 초안을 작성합니다. 두 번째 에이전트가 그 diff(차이점)를 검토하는데, 이는 금요일 오후 5시에 제가 하는 것보다 더 어렵고, 네 번째 백 번을 해도 지루해하지 않습니다. 테스트는 스스로 실행됩니다. 타이핑, lint, 스테이징 배포, 실제와 비슷한 데이터베이스에 대한 스모크 체크까지 거칩니다. 변경 사항이 저에게 거의 도달할 무렵에는 이미 다섯 개의 별도 자동화 단계가 그것을 검토하고 '예'라고 말했습니다. 이는 제가 3년 전에 수동으로 하던 버전보다 진정으로 더 좋았고, 타이핑은 결코 그리울 부분이 아니었습니다.
그래서 한 스프린트 동안 저는 당연하게 여겨지는 마지막 단계를 수행했습니다. 녹색 체크 표시 네 개와 이미 깨끗한 검토가 된 풀 리퀘스트를 보고 생각했습니다: 왜 제 손이 아직 병합 버튼 위에 있는 걸까? 제가 직접 클릭함으로써 추가하는 것이, 이미 네 번의 자동화된 '예'들이 얻어내지 못한 것은 무엇일까? 그래서 저는 에이전트들에게 마지막 단계까지 맡겼습니다. 생성(Generate), 검토(Review), 테스트(Test), 스테이징(Stage), 병합(Merge). 완전히 폐쇄 루프였습니다. 약 9일 동안은 미래처럼 느껴졌습니다.
그러다 그 병합 중 하나가 새벽 2시에 유료 고객 한 명을 자신의 계정에서 차단하는 일이 발생했고, 저는 — 프로덕션 환경에서, 전화 통화로 — 어떤 단일 단계의 파이프라인을 절대 넘겨주어서는 안 되는지 비싼 값에 배웠습니다. 그것은 대부분의 사람들이 추측할 만한 단계가 아닙니다. 거의 모든 사람이 가장 먼저 자동화하는 바로 그 단계입니다.
diff는 깨끗했다. 그것이 전체 문제였다.
다음 것이 스스로 배포되었습니다.
변경 사항은 쓰기 경로(write path)였습니다. 이 변경 사항은 실제로 행(row)을 영속화하기 전에 요청을 인지하고 — 클라이언트에게
저자 에이전트(author agent)가 코드를 작성했습니다. 검토 에이전트(review agent)는 그것을 읽고 승인했고 — 저는 검토 에이전트에게 공정해야 한다고 생각합니다. 왜냐하면 정말 좋았기 때문입니다. 제가 놓쳤을 두 가지 실제 문제를 잡아냈습니다. 다만, 이것만은 잡지 못했습니다. 왜냐하면 이것은 버그처럼 보이지 않기 때문입니다. 완성된 작업처럼 보입니다. 테스트가 녹색(green)이었던 이유는 테스트가 행복한 경로(happy path)만을 테스트했기 때문이며, 이 코드가 정확한 바로 그 경로입니다. 스테이징 환경도 괜찮았습니다. 아무도 잘못된 밀리초에 대해 스테이징 환경에 요청을 재시도하지 않았습니다. 자동화된 '예' 답변 다섯 개가 모두 기술적으로 정직했고, 모두 diff를 바라보았으며, 누구 하나 새벽 두 시의 상황을 보지 못했습니다.
자동으로 병합(auto-merged)되었습니다. 자동으로 배포(auto-deployed)되었습니다. 그리고 평범한 나쁜 밤에 재시도 요청이 들어왔고, 응답(ack)은 나갔지만 쓰기 작업(write)은 일어나지 않았습니다. 그러자 돈을 지불하는 실제 사람이 자신의 계정에서 로그를 통해 자신이 그곳에 있었음을 증명할 것이 아무것도 없는 상태로 잠금 처리되었습니다. 저는 아직도 그 전화 통화가 느껴집니다 — 버그 자체가 이국적이었기 때문이 아니라, 저 아름다운 폐쇄 루프(closed loop) 어디에서도, 그 전화를 받아야 할 사람이 그것을 보고 '배포하는 것'에 대한 책임을 지는 순간이 없었기 때문입니다.
우리가 '검토(review)'라고 부르는 두 가지 — 그리고 이 둘은 같지 않다
여기에는 잠금 처리된 고객이 저에게 가르쳐 준 구분이 담겨 있으며, 이것이 바로 글 전체의 핵심입니다.
우리는 완전히 다른 두 가지 작업을 위해 하나의 단어인 '검토(review)'를 사용합니다.
첫 번째 작업은 코드 판단하기: 이것이 올바른가, 관용적인가(idiomatic), 엣지 케이스(edge case)를 처리하는가, 명명 규칙이 합리적인가. 이것은 _기술_입니다. 방대한 양의 이전 코드와 시스템에 대한 정신적 모델을 기반으로 패턴 매칭하는 것입니다. 그리고 이것은 올해 값싸진 바로 그 종류의 기술입니다. 좋은 검토 에이전트는 피곤함 없이, 일관되게, 새벽 3시에, 네 번째 diff에서도 수행할 수 있으며, 인간 시니어 개발자가 금요일 오후에 PR(Pull Request)를 대충 넘기는 것에서 오는 피로감도 없습니다. 이것은 반드시 자동화해야 합니다. 저는 그렇게 했고, 그것이 올바른 결정이었습니다.
두 번째 업무는 병합(merge)을 책임지는 것입니다: '이것이 이제 실제 사용자에게 나갈 것이고, 만약 잘못된다면 그건 내 책임이다'라는 것을 받아들이는 것입니다. 이것은 기술이 아닙니다. 일치시킬 패턴도 없습니다. 그것은 특정 책임을 지는 주체가 되돌릴 수 없는, 외부에 노출되는 결정에 자신의 이름을 걸고, 만약 일이 잘못되었을 때 그 결과를 흡수하는 행위입니다.
지난 20년 동안 이 두 가지 업무는 하나로 합쳐져 있었습니다. 왜냐하면 코드를 검토하는 사람이 호출(page)을 받을 사람과 같았기 때문에, 우리는 그것들이 다른 것이라는 것을 인지할 필요가 없었습니다. 자동화가 그것들을 분리했습니다. 기계는 이제 첫 번째 업무를 제가 하는 것보다 더 잘 수행할 수 있습니다. 하지만 두 번째 업무는 전혀 할 수 없습니다. 그것은 지능의 문제가 아니기 때문입니다. 두 번째 업무는 책임(accountability)에 관한 것이고, 책임에는 실제로 결과를 감당할 수 있는 무언가가 필요합니다.
판단은 자동화할 수 있지만, 책임은 자동화할 수 없다.
잘못된 diff를 병합하고 프로덕션 환경을 다운시킬 수 있는 에이전트는 호출(page)을 받을 수 없습니다. 사과할 수도 없고. 2시의 그 통화가 다음 결정에 어떤 영향을 미칠지 감당할 무게도 지닐 수 없습니다. 왜냐하면 그것은 자신이 이해관계가 걸린 결정을 내리는 것이 아니기 때문입니다. 그것은 인간이 따라올 수 없는 규모로 자신감 있는 결과물을 생산하며, diff가 명작이든 시한폭탄이든 똑같은 평온한 목소리로 승인(sign off)하기 때문입니다. 무한한 처리량, 제로 책임. 병합이야말로 전체 파이프라인에서 책임을 져야 하는 유일한 지점인데, 저는 그 책임을 아무런 책임도 지지 않는 참여자에게 넘겨버렸습니다.
우리는 잘못된 클릭을 감시한다
이제 여러분을 불편하게 해야 할 부분이 있습니다. 왜냐하면 이것을 한 번 보면 어디서든 그것을 발견하기 때문입니다.
팀들이 본능적으로 무엇은 수동으로 유지하고, 무엇은 기꺼이 자동화하는지 지켜보세요.
그들은 **코드 리뷰(code review)**에 사람을 배치합니다. “모든 diff는 사람이 읽어야 해.” 풀 리퀘스트(pull request)에 의무적인 사람의 승인을 거치게 하고, 리뷰 커버리지에 대해 논쟁하며, 인간의 눈이 그 라인들에 머물러 있기 때문에 안전하다고 느낍니다. 그리고 나서 **녹색 신호 시 자동 병합(auto-merge on green)**과 **프로덕션으로의 지속적 배포(continuous deploy to prod)**를 연결하고는, 이 부분이 그냥 파이프라인 구성일 뿐이라며 스스로 똑똑해합니다.
그것은 정확히 역방향입니다.
코드 리뷰는 되돌릴 수 있는(reversible) 단계입니다. 만약 사람이 리뷰에서 무언가를 놓치더라도 아직 아무 일도 일어나지 않았습니다. 다시 검토할 수 있고, 댓글을 달 수 있습니다. 스테이징 환경에서 잡아낼 수도 있습니다. 아무것도 실제 세계로 넘어가지 않았습니다. 이것은 전체 파이프라인에서 가장 복구 가능한 지점입니다—그리고 우리가 기어코 인간의 손길이 유지되기를 고집하는 부분임에도 불구하고, 이제는 기계가 더 잘 수행하게 된 단계입니다.
프로덕션으로의 병합(merge to production)은 되돌릴 수 없고 외부로 노출되는(irreversible, outward-facing) 단계입니다. 이것은 변경 사항이 제안에서 벗어나 고객이 새벽 2시에 건드릴 수 있는 무언가가 되는 정확한 순간입니다. 이 파이프라인의 어느 지점에서 재시도(retry)가 누군가를 계정에서 차단할 수 있는지에 대한 유일한 지점입니다. 그리고 이것은 우리가 로봇에게 가장 편안하게 맡기는 단계인데, 바로 그것이 결정이라기보다는 버튼이나 웹훅, 녹색 체크 표시 같은 파이프라인 구성처럼 보이기 때문입니다.
우리는 저렴하고 되돌릴 수 있는 단계를 인간의 손으로 지키고, 비싸하고 되돌릴 수 없는 단계를 자동화합니다. 우리는 기계가 안전하게 만든 한 곳에 우리의 손을 유지했고, 기계가 할 수 없는 곳에서는 손을 뗐습니다.
병합은 아무것도 생산하지 않는다—이것이 핵심입니다
병합 버튼이 왜 그렇게 자동화하기 쉬운지, 그리고 '아니오'와 예방된 장애(outage)가 항상 저평가되는 이유가 바로 이것입니다: 눈에 보이는 결과물을 만들어내지 않기 때문입니다.
순조롭게 진행되는 병합은 눈에 보이지 않습니다. 아무 일도 일어나지 않습니다. 아티팩트도 없고, 올라가는 그래프도 없고, 당신의 이름이 적힌 코드 라인도 없습니다—저자 에이전트가 코드를 작성했고, 리뷰 에이전트가 버그를 찾아냈으며, 당신은 단지 이미 네 개의 녹색 체크 표시로 정당화된 버튼을 클릭했을 뿐입니다. 이것은 건물에서 가장 삭제하기 쉬워 보이는 업무처럼 보입니다.
병합(merge)이 잘못되면 그건 이름 붙일 수 있는 사건입니다: 사고(incident), 사후 검토 보고서(postmortem), 계정을 잠근 고객, 전화 통화 같은 것이죠. 그래서 병합 버튼을 누르는 사람은 순전히 마이너스 측면의 위치에 앉아 있습니다 — 망가졌을 때 모든 비난을 받고, 문제가 없어도 아무런 공로를 인정받지 못하죠. 어떤 생산성 지표로도 그 사람이 아무것도 하지 않는 것처럼 보입니다. 그리고 이것이 바로 그 직업이 자동화될 수 없는 정확한 이유입니다: 그들이 실제로 제공하는 것은 처리량(throughput)이 아니라, 결과가 떨어질 장소인 셈이죠. 사람을 병합 단계에 남겨두는 이유는 그 사람이 더 빠르거나 에이전트보다 diff를 더 잘 읽기 때문이 아닙니다. 그것은 새벽 2시에 문제가 생겼을 때, '파이프라인이 그랬어요'라는 답변을 고객이나 규제 기관, 혹은 자신에게 할 수 없기 때문에 그들을 거기에 유지하는 것입니다.
분명히 하자면 — 이것은
주장은 좁으며, 두 역할이 분리되면 반박하기 어렵다고 생각합니다: 파이프라인에서 정확히 한 단계는 인간이 담당해야 하고, 그것은 병합(merge)입니다. 인간이 더 잘해서가 아니라, 인간만이 책임을 질 수 있는 유일한 참여자이기 때문입니다. 그 버튼 상류에 있는 모든 것은 기술(skill)이고, 기술은 저렴해졌습니다. 이 버튼 자체는 기술이 아닙니다. 서명(signature)입니다.
실제로 변경한 것들
저는 자동화 기능을 제거하지 않았습니다. 인간의 역할을 필요한 한 자리에 재배치했을 뿐입니다:
- 에이전트는 여전히 생성하고 검토합니다. 저는 둘 다를 덜 하도록 만든 것이 아니라, 더 하도록 만들었습니다. 저자가 초안을 작성하고, 회의론자는 그것을 깨뜨리려고 시도합니다. 이 루프의 부분은 열려 있기보다 닫혀 있는 편이 좋습니다. 기계는 제가 피곤할 때 지치지 않습니다.
- 인간이 프로덕션으로 병합되는 모든 과정에 대한 소유권을 가지며, 다른 것은 아무것도 소유하지 않습니다. 단순히 diff를 다시 읽는 코드 검토자로서가 아닙니다 — 에이전트가 이미 그것을 더 잘 했습니다. 책임 당사자(accountable party)로서 _파급 효과(blast radius)_를 살펴보는 것입니다: 이것이 무엇에 영향을 미치는지, 잘못되었을 때 누가 알림을 받는지, 재시도 시나리오는 무엇인지, 새벽 2시에 저에게 전화할 것인지. 병합 단계에서 인간이 던지는 질문은
그리고 작가가 만든 것을 흠집 내려고만 하는 별도의 **회의론자(skeptic)**가 있습니다. 이 회의론자는 감탄하는 것이 아니라 오직 부수는 것만을 임무로 합니다. '아니요'라는 대답이 자체 좌석을 갖게 되며, 인간 검토자가 지칠 때도 지치지 않습니다. 이것마저 자동화하고 의미를 부여하세요. 왜냐하면 기계가 오후 5시의 사람보다 일관되게 회의적일 수 있기 때문입니다.
그리고 병합 단계에 있는 인간이 있습니다. 코드를 검토하는 것이 아닙니다 — 그건 회의론자가 인간보다 더 힘들게 했습니다. 통화(call)를 소유하고, 파급 효과(blast radius)를 보고, 재시도(retry)가 새벽 2시에 발생했을 때 결과가 떨어지는 곳에 있는 사람입니다. 작가는 무한한 처리량(throughput)을 가지고 있고 저는 그것이 작동하도록 내버려둡니다. 회의론자는 무한한 인내심을 가지고 있고 저는 그것이 작동하도록 내버려둡니다. 인간은 둘 다 가지지 못하며 — 세 명 중 결과에 책임을 질 수 있는 유일한 사람입니다. 이것이야말로 제가 다시는 자동화하지 않을 그 자리입니다.
이것이 바로 xenition의 형태이며, 여러분에게도 마찬가지입니다: 채팅 한 번으로 원하는 것을 설명합니다 — 문서(doc), 추적기(tracker), 전체 작동하는 앱(working app)을요 — 그리고 그것은 그 물건을 구축하고, 회의론자를 통해 테스트하며, 아무것도 라이브(live)되기 전에 승인을 위해 멈춥니다. 두 가지 저렴한 일은 스스로 실행되고; 여러분은 되돌릴 수 없는 단 하나의 클릭을 유지합니다. 기술(skills)은 자동화하고, 서명에는 인간을 배치하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기