도메인 주도 에이전트: 레거시 코드에서 AI가 실패하는 이유
LLM 기반 코딩 에이전트는 신규 프로젝트에서는 잘 작동하지만, 기술 부채가 쌓인 레거시 코드베이스에서는 개념이 중구난방으로 정의되어 있어 성능이 급격히 떨어진다고 지적합니다. 저자는 전략적 작업(무엇을 왜 바꿀지 결정)은 인간이, 전술적 작업(코드 구현)은 AI가 담당하도록 분업하고, GitHub 이슈와 스킬·서브에이전트 기반 AI 시스템으로 실행한다고 설명합니다.
도메인 주도 에이전트
나는 지난 몇 년간 코딩, 더 넓게는 소프트웨어 엔지니어링 전반에 LLM을 집중적으로 사용해왔다. 생산성이 얼마나 향상되는지 여러 차례 직접 확인했고, 점점 더 많은 프로젝트에 LLM을 도입했다. 신규(greenfield) 프로젝트나 소규모 프로젝트에서는 잘 작동한다. 하지만 현실적인 일상 업무에서는 무거운 의존성 트리, 강한 결합도, 그리고 미처 처리하지 못한 모든 것이 쌓인 기술 부채 백로그를 가진 레거시 코드베이스에 에이전트를 도입해야 한다. 그러면 LLM이 제공하는 작업 품질이 급격히 떨어진다는 것을 금방 알게 된다.
이 실패에는 특유의 패턴이 있다. 신규 저장소에서 "채용 공고 상태" 필드를 요청하면 그대로 만들어진다. 그런데 4년간 운영해온 시스템에서 요청하면, 이미 세 가지 표기로 존재하는 개념의 네 번째 표기를 모델이 새로 발명해낸다. 코드베이스 자체가 어느 것이 진짜인지 결정한 적이 없기 때문이다. 단순 호출로 충분한 곳에 어댑터를 쓰거나, 어댑터가 핵심이었어야 할 곳을 직접 호출로 뚫어버리기도 한다. 이런 것들은 하나같이 시스템에 대한 질문인데, 시스템 어디에도 답이 없다. 모델은 추측하고, 대개 틀리게 추측한다.
그래서 브라운필드(기존) 프로젝트는 깊다. 기술적인 깊이는 첫 번째 층일 뿐이다. 그 아래에는 두 번째 층이 있다: 혼란, 의미의 결핍, 그리고 이를 해결할 공유 언어의 부재다. 모델이 빠져드는 것은 바로 이 층이다.
업그레이드가 필요한 것은 모델이 아니다. 코드가 준비되지 않은 것이고, 준비성(Readiness)은 우리가 만들 수 있다. 점진적으로, 조각조각씩. 내가 어떻게 하는지 보여주겠다.
이전보다 쉬워졌다
소프트웨어 엔지니어링의 시작에는 유일한 존재가 있었다: 기술 부채다. 이는 우리 개발자들이 추구하는 것의 자연스러운 결과다. 우리는 미래의 비즈니스 결정이 현재의 코드 관점을 흔들 것에 대비하지 못한다. 빠르게 배포해야 하고, 그러며 트레이드오프를 치러야 한다. 그 결과 코드 스멜은 점점 커진다.
일반적인 대응은 엔지니어링 예산의 일부를 정리 작업에 쓰는 것이다: 기술 예산의 10~20%를 기술 부채 해소에 배정하라. 이론상으로는... 다음 분기에...
예산의 다섯 분의 일은 '무엇을 바꿀지 결정하는 비용'과 '그것을 타이핑하는 비용'으로 나뉘는데, 이 둘은 결코 같은 가격이 아니었다. 결정하는 비용은 예전과 거의 비슷하게 유지됐다. 타이핑하는 비용은 폭락했다. LLM은 정리 작업의 기계적 부분(모듈 추출, 두 패키지에 걸친 리팩토링, 테스트 커버리지 확대)을 2020년과는 비교할 수 없는 비용으로 처리해준다. 기술 부채 갚기에는 여전히 시간이 걸린다. 하지만 훨씬 적게 걸리고, 내게 남는 것은 결정하는 부분이다.
전략적 vs 전술적
나는 이 작업을 둘로 나눈다. 존 오스터하우트(John Ousterhout)의 『소프트웨어 설계 철학(A Philosophy of Software Design)』에서 단어를 빌리되, 의미를 다소 비틀어 쓴다는 점은 솔직히 밝힌다. 그는 전술적(tactical)과 전략적(strategic)을 코딩할 때 취할 수 있는 두 가지 태도로 사용한다: 전술적 프로그래밍은 '지금 당장 작동하게 만들기'이고, 전략적 프로그래밍은 진행하며 설계에 투자하는 것이다. 나는 앞서 설명한 경제성이 이 선을 따라 갈라지기 때문에, 같은 용어 쌍을 '저자십(authorship)'의 구분으로 사용한다.
전략적 작업은 결정이다: 시스템을 읽고, 무엇을 왜 바꿔야 하는지, 그 변경이 기능에 실제로 부합하는지 파악하는 것. 전술적 작업은 그 결정을 파일로 옮기는 것이다. 전자는 시스템을 머릿속에 담고 있어야 하는 부분이다. 후자는 저렴해진 부분이다.
내가 하는 방식
첫 번째(전략적 작업)에는 내가 온전히 개입하고, 두 번째(전술적 작업)에서는 구현자보다는 검토자로 참여한다. 첫 번째 경로에서는 코드베이스를 보다 일반적인 방식으로 분석하며, 구현해야 할 변경사항과 내가 제공하려는 기능의 정합성을 평가한다. 이러한 접근의 결과물은 각 저장소에 내가 생성하는 GitHub 이슈다. 그 이슈들은 이후 스킬(skills)과 서브 에이전트(sub-agents) 기반의 내 AI 시스템이 처리한다. 스킬이란 문서화된 절차다: 작업이 일치할 때 모델이 로드하는 마크다운 지침 파일로, "이슈를 처리하라"나 "컨텍스트 맵을 재생성하라" 같은 작업이 내 그때그때 상황과 무관하게 매번 동일한 방식으로 실행되도록 한다.