우리는 더 빠르게 배포했습니다. 기술 부채도 마찬가지였습니다.
요약
AI 에이전트를 활용한 빠른 코드 생성 속도가 개발자의 인지적 맥락과 소유권을 약화시켜 새로운 형태의 기술 부채를 발생시킨다는 점을 지적합니다. 생성 속도에 비해 검토 시간이 부족해지면서, 시간이 흐른 뒤 코드를 다시 이해하기 어려워지는 문제를 다룹니다.
핵심 포인트
- AI 에이전트의 빠른 생성 속도가 개발자의 맥락 유지 능력을 저해함
- 검토(Review) 시간과 생성(Generation) 시간 사이의 불균형 발생
- 직접 작성할 때 발생하는 의사결정 과정의 맥락과 소유권 상실
- AI가 생성한 코드는 배포 시에는 내 것이지만, 나중에는 물려받은 코드처럼 느껴짐
몇 달 동안 손대지 않은 파일을 열었을 때, 당신의 첫 번째 본능은 마치 다른 사람이 작성한 것처럼 읽어 내려가는 것입니다.
코드가 고장 났기 때문이 아닙니다. 테스트가 실패하고 있기 때문도 아닙니다. 그저 그 코드의 경계가 어디인지 즉각적으로 알 수 없기 때문입니다.
최근에 저도 약 6개월 전에 마지막으로 만졌던 모듈에서 그런 기분을 느꼈다고 말씀드리면 믿어주셔야 합니다. 코드는 실행되었습니다. 로직도 유지되었습니다. 하지만 저는 제가 작성하지 않은 코드를 다시 읽을 때처럼 그것을 다시 읽어야 했습니다. 천천히, 하중을 견디는 핵심 부분들을 찾아내며, 안전하게 코드를 수정하기 전에 왜 이 코드가 작동하는지에 대한 그림을 다시 그려야 했습니다.
제가 그 코드의 대부분을 작성했습니다. "도움을 받아서 말이죠."
AI 에이전트 (AI agent)가 방대한 섹션들을 생성했습니다. 저는 차이점(diffs)을 검토하고, 조정하고, 승인했습니다. 당시에는 그 속도가 진정한 돌파구처럼 느껴졌습니다. 6개월이 지난 지금, 그 코드는 완전히 다른 시대에서 온 것처럼 느껴집니다.
이러한 느낌에는 이름이 있습니다. 다만 저는 보통 6개월 된 코드에서 이런 느낌을 예상하지 못할 뿐입니다.
부채가 천천히 쌓일 때는 유예 협상이 합리적이었습니다
제가 함께 일했던 모든 팀은 동일한 방식의 합의를 각자의 형태로 가지고 있었습니다. 어디에도 적혀 있지는 않았지만, 그냥 이해하고 있었죠. 부채가 쌓이면 누군가 "릴리스(release) 전에 혹은 조용한 스프린트(sprint) 기간에 정리해야 해요"라고 말했고, 우리 중 몇 명이 그 일을 했습니다.
그것이 작동했던 이유는 부채가 우리가 따라잡을 수 있는 속도로 쌓였기 때문입니다. 저는 그 속도를 머릿속에 담아둘 수 있었습니다. 기능 하나를 만드는 데 일주일, 혹은 이주일 정도 걸렸고, "나중에"라는 말은 막연한 약속이 아니라 제가 머릿속에 그릴 수 있는 실제 날짜를 의미했습니다.
그것이 바로 조정(calibration)의 실체입니다. 정책도 아니고, 완벽한 시스템도 아닙니다. 인지할 수 있을 만큼 충분히 천천히 작업을 수행하며 쌓아온, 일정 기간의 작업이 얼마나 많은 부채를 추가하는지에 대한 감각입니다.
이제 이것에 이름이 필요한 이유는, 그것이 전제했던 속도가 사라졌기 때문입니다.
AI는 입력 속도를 바꿨습니다. 그 외의 것은 바뀌지 않았습니다.
에이전트 (agent)를 사용하여 처음으로 실제 기능을 생성했을 때, 짧은 시간 안에 얼마나 많은 양이 나타나는지 보고 놀랐습니다. 단순히 양뿐만이 아니었습니다. 구조 또한 마찬가지였습니다. 그것은 마치 집중해서 일주일 동안 해낸 작업이 단 몇 시간 만에 이루어진 것처럼 보였습니다.
나는 그것을 검토하고, 핵심 경로(critical paths)를 테스트한 뒤 배포했습니다. 내가 계산에 넣지 못했던 것은 비율이었습니다. 며칠에 걸친 저작(authorship)에 대해 며칠간의 검토가 이루어지는 것이 아니라, 며칠에 걸친 생성(generation)에 대해 단 몇 시간의 검토만이 이루어지는 비율 말입니다.
내가 천천히 작성할 때는, 의도하지 않아도 맥락(context)을 간직하게 됩니다. 나는 내가 어떤 트레이드오프(tradeoff)를 했는지, 그리고 왜 그렇게 했는지 알고 있습니다. 왜냐하면 그 결정 앞에 서 있었던 사람이 바로 나였기 때문입니다. 소유권(ownership)은 바로 거기에서 나옵니다. 나중에 디프(diff)를 읽는 것에서 나오는 것이 아닙니다.
에이전트(agent)가 작성할 때는 그러한 속도감이 사라집니다. 결과물은 완성된 상태로 도착하며, 나의 검토는 명백한 오류들을 잡아냅니다. 하지만 에이전트가 할 수 없는 것은, 내가 직접 내릴 만큼 충분히 그 과정 안에 머물지 못해 놓쳐버린 트레이드오프에 대한 기억을 나에게 전달해 주는 일입니다.
그것은 내가 작성한 것처럼 배포되었습니다. 하지만 그것은 내가 물려받은 것처럼 도착했습니다.
6개월 후, 팀의 그 누구도 해당 모듈을 완전히 "알고" 있지 않습니다. 모듈이 고장 난 것은 아닙니다. 다만 동일한 연령대의 AI 이전 코드에서는 좀처럼 볼 수 없었던 방식으로 매우 밀집(dense)되어 있을 뿐입니다.
이제 6개월은 과거의 3년처럼 읽힙니다
이것은 명백한 의미에서의 "코드 품질(code quality)"에 관한 문제가 아닙니다. 내가 돌려받은 결과물은 솔직히 내가 쓸 수 있는 것보다 더 나았습니다. 구조가 잘 잡혀 있었고, 함수 이름들도 일관되었으며, 경고 신호처럼 보이는 것도 없었습니다. 나쁜 코드는 스스로를 드러내기 마련이지만, 이것은 그렇지 않았습니다.
예를 들어, 해당 모듈은 은행 거래를 처리하는 외부 제공업체와의 통합 모듈이었습니다. 나는 그들의 문서를 면밀히 따랐습니다. 처음에는 파일당 하나의 책임(responsibility)을 갖는 깔끔한 상태로 시작되었습니다. 그러다 요구사항이 내가 하나하나 검토할 수 있는 속도보다 더 빠르게 밀려들었고, 대부분의 작업이 AI의 도움을 받았기에 그 속도 아래에서 코드 스멜(smells)이 조용히 쌓여갔습니다. 6개월이 지난 후 무언가 고장 났을 때, 나는 코드를 읽는 것만으로는 그 이유를 찾을 수 없었습니다. 파일은 더 이상 자신이 만들어내는 동작(behaviour)을 설명해주지 못했습니다.
나 또한 품질 기준(quality bar)을 마땅히 지켜야 했던 것만큼 엄격하게 유지하지 않았습니다. 하지만 바로 그게 핵심 아닌가요? 그 속도 때문에 내가 멈춰 서 있다는 사실을 알아차리지 못하기가 너무나 쉬웠던 것입니다.
그런 종류의 코드는 도달하기까지 수년이 걸리곤 했습니다. 이직, 드리프트 (drift), 이미 떠난 사람들이 내린 결정들이 뒤섞인 코드 말입니다. 저는 6개월 만에 그 지점에 도달했습니다. 제가 일을 못 하게 되어서가 아니라, 코드가 그에 따르는 소유권 (ownership)보다 더 빠르게 도착했기 때문입니다.
제가 계속 되새기는 휴리스틱 (Heuristic)은 이것입니다: 생성 속도 (generation rate)는 올라갔지만, 리뷰 깊이 (review depth)는 올라가지 않았습니다. 그래서 배포된 것과 제가 실제로 이해하고 있는 것 사이의 간극이 조용히 벌어집니다. 코드는 여전히 멀쩡해 보이기 때문입니다.
그것이 바로 과거의 유예 (deferral) 방식으로는 결코 대응할 수 없었던 상태입니다.
도착하지 않는 미래로의 유예
유예 전략은 특정 지점에서 무너집니다. 바로 필요한 정리 스프린트 (cleanup sprint)가 가용 가능한 용량 (capacity)보다 커지는 지점입니다.
과거에는 이 임계값이 천천히 다가왔습니다. 팀은 1년에 걸쳐 의미 있는 부채를 쌓을 수 있었고, 집중적인 한 달을 통해 이를 상환할 수 있었습니다. 입력 속도 (input rate)와 정리 속도 (cleanup rate)가 같은 범위 내에 있었기에 수학적으로 계산이 맞았습니다.
저는 6개월 된 모듈의 정리를 계획하려 할 때 비로소 이 사실을 깨달았습니다. 필요한 스프린트가 로드맵 어디에도 들어맞지 않는다는 것을 알게 된 것입니다. 팀이 느려서가 아니었습니다. 그 범위 (scope)가 스프린트가 흡수할 수 있도록 설계된 수준을 이미 넘어섰기 때문입니다.
이해하는 측면, 즉 읽기, 리팩터링 (refactoring), 공유된 컨텍스트 (shared context)의 재구축은 여전히 제가 움직이는 속도로 진행됩니다. 그것은 여전히 제가 해야 할 일이기 때문입니다. 왜 그런 결정이 내려졌는지 문서화된 것이 아무것도 없었기에, 에이전트 (agent)에게 전달하여 자신의 출력물을 스스로 재설명하게 할 수 있는 것도 없었습니다. 제가 필요로 했던 이해는 애초에 축적된 적이 없었으며, 그 상태로 되돌아갈 지름길도 없었습니다.
AI 보조 개발 (AI-assisted development)로 보낸 6개월은 과거에 구축하는 데 2~3년이 걸렸을 법한 밀도를 담아냈습니다. 제가 마주하고 있는 정리 범위 (cleanup scope)는
새로운 접근 방식이 어떤 모습일지는 저도 확신할 수 없습니다.
저는 찾아 헤맸습니다. 하지만 이 문제를 완전히 해결한 팀도, 프로세스(Process)도, 도구(Tool)도 찾지 못했습니다. 가시화(Seeing)하는 부분과 결정(Deciding)하는 부분, 이 두 가지 서로 다른 이음새(Seams) 모두 말입니다. 어떤 모듈이 조용히 소유자를 잃었는지, 혹은 출시된 기능과 실제로 사람들이 이해하고 있는 기능 사이의 간극이 한 스프린트(Sprint)로 메울 수 없을 만큼 벌어졌는지 알려주는 것은 아무것도 없습니다. 그리고 설령 그것을 볼 수 있다고 하더라도, 아무도 일정을 잡을 수 없는 리팩터링(Refactor) 기간을 요구하지 않으면서 다음에 무엇을 할지 결정할 수 있는 확립된 방법은 없습니다.
저는 이 분야에서 하나의 아이디어를 작업 중입니다. 솔루션(Solution)이라고 부르기에는 아직 매우 초기 단계입니다. 하지만 이를 더 구체화하기 전에 한 가지 질문이 머릿속에 떠올랐습니다. 제가 설명하고 있는 이 문제가 다른 누군가에게도 실제로 존재하는 문제인가요, 아니면 저에게만 실재하는 문제인가요?
만약 여러분도 이런 느낌을 받았다면: 여러분에게 더 어려운 문제는 AI가 생성한 부채(AI-generated debt)를 얼마나 안고 있는지 알 수 없다는 것인가요, 아니면 그것을 볼 수는 있지만 다음에 무엇을 해야 할지에 대한 시스템이 없다는 것인가요?
저는 어느 쪽인지 알고 싶습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기