에이전트 코드베이스에서 리팩터링이 돈이 되는 이유

이 글은 Giles Edwards-Alexander의 The Economic Benefit of Refactoring을 읽고 정리한 해석입니다. 원문의 실험 결과와 내가 제안하는 검증 방법을 구분합니다.

요즘 Claude Code나 Cursor로 기능을 붙이다 보면 코드는 생각보다 빨리 늘어난다. 구현 초안이 나오고 테스트도 돌아간다. 그런데 어느 순간 한 파일이 수천 줄을 넘기고 비슷한 HTTP 설정과 JSON 변환이 반복되기 시작한다.

개인적으로 큰 파일을 맡길 때도 비슷한 느낌이 있다. 파일을 넓게 읽고 비슷한 구현을 옆에 붙이는 경우가 많다. 책임이 나뉜 모듈에서는 수정할 위치를 찾기가 상대적으로 수월했다. 다만 이것은 내 사용 경험이지, 파일 크기와 모델 성능의 관계를 측정한 결과는 아니다.

원문이 흥미로웠던 이유는 그 느낌을 질문으로 바꿨기 때문이다.

지금 구조를 정리하는 데 비용을 쓰면, 이후 변경의 비용이 줄어드는가?

원문에서 확인한 것과 확인하지 못한 것

저자는 주로 에이전트로 만든 앱의 17,155줄짜리 Rust 데이터 접근 계층을 리팩터링했다. 각 단계에서 이전 대화를 넘기지 않은 새 에이전트에게 같은 기능 추가를 맡기고, 그 변경을 버린 뒤 다음 단계를 비교했다.

항목리팩터링 전최종 단계
데이터 접근 계층 전체 줄 수17,15516,608
가장 큰 파일의 줄 수17,1553,695
변경당 추정 입력 토큰159,56427,360
변경당 추정 출력 토큰1,7052,113
작업 시간342초454초

입력 토큰은 약 83% 줄었다. 다만 에이전트가 보고한 문자 수를 4로 나눈 근사치이며 실제 API 사용량이나 청구액은 아니다. 작업 시간은 오히려 늘었고, 리팩터링 자체의 정확한 토큰 비용도 분리하지 못했다. 한 코드베이스의 대표 변경 하나를 비교한 사례다. 원문 결과와 측정 한계

따라서 “리팩터링하면 83% 싸지고 더 빨라진다”는 결론은 낼 수 없다. 확인된 것은 이 실험에서 해당 변경을 수행할 때 추정 입력량이 줄었다는 점이다.

절약한 것은 전체 코드보다 읽어야 할 범위다

전체 코드량이 크게 줄지 않았는데 입력량이 줄었다는 관찰은 유용하다. 관련 코드가 모여 있으면 매번 모든 내용을 읽을 필요가 줄어들 수 있다는 가설을 세울 수 있기 때문이다.

예를 들어 문서 이름 변경 정책을 고친다고 해보자. 이 규칙이 UI 이벤트, 업로드 함수, 여러 API 호출에 각각 들어 있다면 위치를 모두 찾고 같은 의미인지 확인해야 한다. 규칙이 이름을 가진 함수 한곳에 모이고 호출 관계가 드러나면 탐색과 검증 범위가 줄 수 있다. 이는 설명을 위한 가상 예시다.

하지만 파일을 쪼개기만 한다고 해결되지는 않는다. 같은 규칙이 열 개의 작은 파일에 흩어지면 오히려 이동과 검색이 늘 수 있다. 공통 함수도 실제로 다른 정책을 억지로 합치면 변경할 때 예외 분기가 늘어난다.

내가 보고 싶은 것은 줄 수가 아니라 다음 세 가지다.

  • 같은 이유로 바뀌는 코드가 가까이 있는가?
  • 이름과 호출 관계만으로 수정할 위치를 찾을 수 있는가?
  • 변경을 검증하는 데 읽고 실행해야 할 범위가 줄었는가?

이 조건이 개선되면 사람의 이해 비용도 줄 수 있다. 반대로 에이전트 토큰이 줄어도 사람이 결과를 해석하는 시간이 늘면 비용을 다른 곳으로 옮긴 것일 수 있다.

토큰 절감과 돈을 구분해야 한다

입력 토큰을 줄이는 것은 비용 계산의 한 부분이다. 실제 지출은 입력·출력 단가, 캐시 적중, 재시도, 구독이나 사용량 기반 과금 방식에 따라 달라진다. 같은 입력량이라도 청구 비용은 같지 않을 수 있다.

경제성을 보려면 같은 단위로 비교해야 한다. 다음은 단가 추천이나 원문 실적이 아니라 판단을 위한 단순 모델이다.

예상 변경 횟수 × (변경 전 평균 비용 − 변경 후 평균 비용) > 리팩터링 비용

여기서 비용에 포함할 범위를 먼저 정한다. 도구 지출만 볼지, 사람의 리뷰·수정 시간까지 금액으로 환산할지 섞지 말아야 한다. 운영 위험을 충분히 평가하지 못했다면 억지로 금액을 붙이기보다 별도의 품질 조건으로 남기는 편이 낫다.

가령 리팩터링과 검증에 10만 원이 들고 같은 유형의 변경마다 전체 비용 5천 원이 줄어든다고 가정하면, 20회에서 비용이 같아진다. 앞으로 두 번 바꿀 영역이라면 이 비용 근거만으로는 서두를 이유가 약하다. 반대로 자주 바뀌는 영역이라면 투자 가치가 커질 수 있다.

토큰 비용이 조금 줄어드는 대신 회귀 위험이나 검토 부담이 커진다면 그 리팩터링은 이 모델의 전제부터 다시 봐야 한다.

내 코드베이스에서 확인한다면

처음부터 전면 리팩터링을 시작하고 싶지는 않다. 자주 수정하고 탐색 비용이 큰 한 영역에서 다음과 같이 확인하겠다. 아직 수행한 실험 결과는 아니다.

  1. 대표 변경을 여러 종류 고른다. 새 필드 추가 하나만이 아니라 결함 수정, 정책 변경 등 실제 반복되는 작업을 포함한다. 특정 구조에 유리한 과제만 고르지 않는다.
  2. 같은 완료 조건을 고정한다. 프롬프트뿐 아니라 테스트와 호환성 기준을 맞춘다. 토큰을 덜 쓰고 중요한 실패 처리를 빼먹었다면 절약이 아니다.
  3. 전후 작업을 별도 체크아웃에서 비교한다. 이전 시도의 결과를 넘기지 않고, 모델·도구·권한·캐시 조건을 기록한다. 반복 실행의 편차와 실패한 시도도 남긴다.
  4. 실제 사용량과 사람 시간을 기록한다. 사용량 집계가 가능하면 입력·캐시·출력·재시도를 구분한다. 에이전트의 자체 토큰 추정만으로 청구액을 확정하지 않는다.
  5. 리팩터링 비용까지 포함해 멈출 지점을 정한다. 절감이 작거나 품질이 나빠지면 더 쪼개지 않는다. 다른 종류의 변경에서 비용이 늘었는지도 본다.

반복 횟수가 적으면 방향을 탐색하는 자료로만 사용한다. 코드 생성에는 변동이 있으므로 한 번 잘된 결과만으로 구조의 효과를 확정하기 어렵다.

리팩터링의 범위는 어떻게 고를까

현재 문제먼저 시도할 작은 변경잘못된 방향의 신호
같은 정책이 여러 곳에 반복됨정책을 이름 있는 함수로 모으기호출자별 예외 옵션이 계속 늘어남
도메인 판단과 HTTP 처리가 섞임변경 이유가 다른 책임을 분리계층만 늘고 읽어야 할 파일은 증가
파일이 크지만 각 구역은 독립적임구역의 책임과 테스트를 함께 이동순환 의존성이나 광범위한 재수정 발생
거의 바뀌지 않고 잘 동작함다음 관련 변경까지 보류 검토줄 수 목표 때문에 대규모 이동만 발생

에이전트는 후보를 찾고 기계적인 변경을 수행하는 데 도움을 줄 수 있다. 방향도 제안받을 수 있다. 다만 “리팩터링해”라는 요청과 테스트 통과만으로 좋은 경계가 만들어졌다고 보지는 않겠다. 테스트가 놓치는 동작과 다음 변경의 비용은 따로 확인해야 한다.

내가 가져가고 싶은 질문

이 사례를 읽고 리팩터링이 항상 돈이 된다고 생각하게 된 것은 아니다. 오히려 돈이 되는지 더 구체적으로 물을 수 있게 됐다.

어떤 변경이 얼마나 자주 발생하고, 그때마다 어떤 비용을 줄이는가?

입력량 감소는 좋은 단서다. 그 절감이 반복되고, 사람의 검토 부담과 회귀 위험을 키우지 않으며, 리팩터링과 검증 비용까지 회수한다면 경제적인 개선이라고 부를 수 있다.

그 기준으로 보면 목적은 파일을 작게 만드는 일이 아니다. 다음 변경을 찾고 이해하고 검증하는 일을 더 싸게 만드는 것이다.