온보딩은 두 가지 일을 하고 있었습니다. 제 생각에 AI는 그중 하나만 제거했습니다.
요약
AI가 코드 이해와 온보딩에 드는 시간은 획기적으로 줄여주었지만, 시스템의 맥락과 의사결정의 이유를 파악하는 과정까지 제거해버렸음을 지적합니다. 코드 작성 속도는 빨라졌으나, 운영과 유지보수에 필요한 깊은 이해와 지식 공유의 중요성은 여전히 남아있습니다.
핵심 포인트
- AI는 코드 이해와 기여 속도를 높였으나, 시스템 맥락 파악의 기회는 줄임
- 온보딩의 비용은 줄었지만, 운영 및 배포 권한 등 책임의 영역은 변하지 않음
- 코드 요약만으로는 서비스 간의 복잡한 상호작용과 설계 의도를 파악하기 어려움
- 콘웨이의 법칙 관점에서 코드의 경계는 허물어졌으나 운영의 경계는 유지됨
다른 팀의 서비스에서 작업할 때 비용이 많이 드는 부분은 코드를 작성하는 것이 아니었습니다. 50줄의 코드를 작성하는 데 일주일이 걸린 적은 한 번도 없습니다. 일주일이 걸렸던 이유는 그 50줄의 코드가 안전하게 작동할 수 있도록 해당 서비스에 대한 충분한 모델(model)을 구축하는 것이었습니다.
그것이 경계(boundary)에 지불해야 하는 통행료였습니다. 그것을 지불하거나, 아니면 건너지 못하거나 둘 중 하나였습니다. 제 생각에 우리는 그 통행료를 징수하는 것을 중단했을 뿐, 다른 것은 변하지 않았습니다.
예전에는 저장소(repo)를 클론(clone)하고, 하나의 요청(request)을 끝까지 따라가며, 작은 티켓(ticket)—이상적으로는 버그(bug)—를 맡았습니다. 버그는 당신이 작성하지 않은 코드를 역으로 추적하며 작업하게 만들기 때문입니다. 왜 특정 필드가 null 허용(nullable)인지 묻다 보면, 아무도 마무리하지 못한 마이그레이션(migration)에 대한 이야기를 듣게 됩니다.
이제는 모델(model)을 저장소에 연결하면 모듈 구조(module structure), 요청 생명주기(request lifecycle), 의존성(dependencies), 그리고 방어 가능한 아키텍처 요약(defensible architecture summary)을 얻을 수 있습니다. 단 한 번의 오후면 충분합니다.
저는 과거의 방식이 옳다고 주장하는 것이 아닙니다. 그 통행료는 게이트키핑(gatekeeping), 지식 독점, 그리고 3주간의 대기 시간이라는 실제 비용을 발생시켰습니다. 또한 그것은 질문을 유도하고, 미지의 영역을 드러내며, 폭발 반경(blast radius)을 작게 유지했습니다. 제 걱정은 우리가 단 하나만 제거하려 했을 뿐, 지연(delay)과 질문을 통째로 제거해 버렸다는 점입니다.
변한 것과 변하지 않은 것
변한 것: 이해(comprehension)에 드는 비용, 기여(contributing)하는 속도, 그리고 그것이 정당한지 여부와 상관없이 확신(confidence)이 도달하는 속도.
변하지 않은 것: 리뷰 대역폭(review bandwidth), 온콜(on-call), 배포 권한(deployment rights), 런북(runbooks), 그리고 왜 그 필드가 null 허용(nullable)인지 기억하는 사람.
콘웨이의 법칙(Conway’s Law)은 시스템이 조직도와 같은 모양으로 끝난다는 의미로 인용되곤 합니다. 그 밑바탕에 깔린 메커니즘은 팀의 경계를 넘는 데 일주일의 이해 시간이 필요했기에, 사람들이 주로 그러지 않았다는 것입니다. 원하는 아키텍처를 얻기 위해 팀을 재편성하는 역 콘웨이 전략(inverse Conway manoeuvre)은 내내 그 점에 의존해 왔습니다. 이제 코드는 어디에나 나타날 수 있습니다. 하지만 그것을 운영(operate)할 수 있는 곳은 여전히 한 곳뿐입니다.
요약(brief)이 말해주지 못하는 것
예약 서비스(reservation service)가 상태 변경 이벤트(state change event)를 발행합니다. 세 개의 서비스가 이를 소비(consume)합니다. 두 개는 관대하게 역직렬화(deserialise permissively)하여 무엇이 도착하든 저장(persist)합니다. 세 번째 서비스는 엄격하게 검증(validate strictly)하며, 인식하지 못하는 모든 것을 데드 레터(dead-letter)로 처리합니다.
그 사실은 예약 서비스(reservation service)의 저장소(repository)에는 들어있지 않습니다. 그것은 다른 세 개의 코드베이스(codebase)와 팀을 옮긴 누군가의 기억 속에 존재합니다. 그 저장소에서 추출한 어떤 요약(brief)도 그것을 만들어낼 수 없는데, 왜냐하면 찾을 수 있는 정보가 그곳에 없기 때문입니다. 스키마 레지스트리(schema registry), 등록된 컨슈머(registered consumers) 또는 계약 테스트(contract tests)가 있었다면 그것을 손에 닿는 곳에 두었을 것입니다. 그것이 실제 해결책이며, 그 필요성을 드러낸 변경 사항보다 훨씬 더 많은 작업이 필요합니다.
요약(brief)이 틀린 것은 아닙니다. 문제는 그것이 완전해 보인다는 점입니다. 느린 경로는 당신을 눈에 띄게 무지하게 만들었고, 바로 그 점이 사람들이 질문하게 만들었습니다.
비용 (What it costs)
풀필먼트(fulfilment) 팀의 누군가가 해당 이벤트(event)에 필드(field) 하나가 필요합니다. 예약 팀의 스프린트(sprint)는 이미 가득 차 있어서, 그들은 요약(brief)을 읽고, 변경 사항을 작성하고, 머지 리퀘스트(merge request)를 올립니다. 20줄의 코드, 테스트 통과, 리뷰어는 다른 4개의 리퀘스트를 열어두고 있습니다. 그대로 통과됩니다.
그 리뷰어는 누구도 계획하지 않은 병목 현상(bottleneck)입니다. 저는 특정 테크 리드(tech lead)와 시니어 개발자들에게 리뷰가 주간 업무의 40~50%를 차지하는 것을 목격해 왔습니다. 팀 속도(velocity)는 올라갔지만 대기열(queue)은 결코 비워지지 않았기 때문입니다. 아무도 역할 기술서(role description)에 이를 적지 않았고, 아무도 이를 위해 인력을 배치하지 않았습니다.
두 개의 컨슈머(consumer)는 불만 없이 새 필드를 저장합니다. 세 번째 컨슈머는 모든 메시지를 데드 레터(dead-letter)로 처리합니다. 야간 작업(nightly job)이므로 하루 동안은 아무 일도 일어나지 않습니다.
03:12에 재보충(replenishment) 작업의 온콜(on-call) 담당자에게 페이지(paged)가 울립니다. 그들이 소유한 것 중에는 변경된 것이 없습니다. 그들은 이를 예약 서비스(reservation service)로 추적하고, 이 서비스 또한 그들의 것이 아님을 확인하며, 거기서 다시 제3의 팀이 올린 머지 리퀘스트(merge request)로 추적합니다. 작성자가 깨어나서 호출에 응답할 때쯤에는 세 팀이 연루되어 있으며, 그들 중 누구도 전체 그림을 파악하지 못합니다. 호출된 사람은 서비스도, 변경 사항도 소유하고 있지 않습니다. 서비스를 소유한 사람은 변경 사항을 작성하지 않았습니다. 변경 사항을 작성한 사람은 이 서비스가 실패하는 것을 본 적이 없습니다.
작성자가 저장소(repository)를 열어보니 요약(brief)에 적힌 내용과 정확히 일치합니다. 그것이 문제입니다. 요약(brief)은 맞았습니다. 그것은 이벤트를 발행(publish)하는 서비스를 설명했을 뿐, 누가 듣고(listening) 있는지에 대해서는 아무것도 말하지 않았습니다.
그들은 모델에게 질문하여 합리적인 답변을 얻어내고, 세 번째 소비자(consumer)가 이를 수용할 수 있게 만들면 페이지는 깨끗해집니다. 눈에 보이는 실패는 사라집니다. 하지만 아무도 살펴보지 않은 것은 다른 두 명의 소비자들입니다. 이들은 아무도 검증하지 않은 필드를 하루 종일 영구 저장(persisting)해 왔습니다. 누군가 2주 후에 이를 발견하고는 관련 없는 버그(bug)로 등록합니다.
그곳의 누구도 방어할 수 없는 행동을 한 것은 아닙니다. 해당 자산(estate)은 하나의 제어 장치가 여러 가지 일을 수행하고 있었고, 그것이 대체물 없이 철수된 것뿐입니다.
내가 틀렸을 수도 있는 부분
경계 간 기여(cross-boundary contribution)가 실제로 증가했다는 것을 보여주는 데이터는 없으므로, 이는 테스트가 수반된 가설입니다. 조직도(org chart)가 아닌 CODEOWNERS나 온콜(on-call) 순번에 의해 정의되는, 소유 팀(owning team) 외부에 있는 작성자가 수행한 병합된 변경 사항(merged changes)의 비율을 측정하십시오.
작성자(authorship) 정보만으로는 권한(permissions)이나 정책(policy)에 의해 여전히 강제되는 경계를 놓칠 수 있으므로, 소유자 대 비소유자 변경 사항에 대해 리뷰 라운드(review rounds), 리드 타임(lead time), 그리고 병합 후 장애(post-merge incidents)와 결합하여 분석하십시오. 만약 이 중 어느 것도 움직이지 않는다면, 저는 메커니즘에 대해 틀린 것이며 그 사실을 알고 싶습니다.
DORA의 2025년 보고서는 이 메커니즘을 직접 테스트하지는 않지만, 제가 신뢰하는 가장 가까운 뒷받침 근거입니다. 해당 보고서는 AI 도입률이 높을수록 전달 처리량(delivery throughput)과 전달 불안정성(delivery instability)이 모두 증가하며, 생성 과정에서 절약된 시간이 감사(auditing) 및 검증(verification)으로 재할당된다는 것을 발견했습니다.
경계를 넘어 병합하기 전 네 가지 질문
-
영향을 받는 각 소비자(consumer)에 대해 책임을 지는 누군가가 이 작업이 진행될 것임을 알고 있으며, 그 동작에 동의합니까?
-
테스트가 모의 객체(mock)가 아닌 실제 소비자(real consumer)를 통해 실행됩니까?
-
만약 이것이 권한(permissions), 자격 증명(credentials), 의존성 범위(dependency scope) 또는 데이터 액세스 경로(data access paths)를 변경한다면, 그것이 각각의 조건에 따라 검토되었습니까?
-
만약 새벽 3시에 작성자와 연락이 닿지 않는 상황에서 되돌리기(reverting)가 필요하다면, 런북(runbook)이 이를 다루고 있으며, 되돌리기 작업이 하류(downstream)에 기록된 내용까지 처리합니까?
어떤 것이 '아니오(no)'를 의미한다면, 그것은 스스로 병합(merge)될 준비가 되지 않았음을 뜻합니다. 범위를 좁히거나, 소유자(owner)와 협업하거나, 누락된 증거를 찾아 나서십시오. 전체를 통째로 넘겨버리는 것은 첫 번째 선택지가 아닌 마지막 선택지가 되어야 합니다. 그렇지 않으면 당신은 우회하려고 했던 그 관문(gate)을 다시 구축하게 될 것입니다.
우리는 이해(comprehension)에 드는 비용을 낭비로 취급했습니다. 일부는 실제로 낭비였습니다. 하지만 일부는 신호 전달(signalling), 조정(coordination), 그리고 제어(control)였으며, 이제 그 비용이 사라진 만큼 이에 대한 명시적인 대체 수단이 필요합니다.
당신의 조직은 어떤 제어(control)를 제거했습니까? 그리고 그것을 전화가 울리기 전(사고 발생 전)에 알게 되었습니까, 아니면 울린 후에 알게 되었습니까?
만약 당신의 팀이 외부인이 해당 서비스를 안전하게 변경하기 전에 서비스 개요(service brief)에 반드시 포함되어야 할 내용을 문서화해 두었다면, 저는 그것을 꼭 읽어보고 싶습니다.
출처: DORA, 2025 State of AI-assisted Software Development.
저는 Google이 아닌 기업들을 위해 아키텍처(architecture)와 AI 엔지니어링(AI engineering)에 대해 글을 씁니다. 뉴스레터는 mayankkaul.com에서 확인할 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기