---
title: "에이전트가 읽는 코드도 리팩터링하면 토큰 비용이 83% 줄어든다"
published: 2026-07-30T15:10:27.000Z
canonical: https://jeff.news/article/5282
---
# 에이전트가 읽는 코드도 리팩터링하면 토큰 비용이 83% 줄어든다

Martin Fowler가 에이전트가 만든 15만 줄 규모 앱에서 1만7155줄짜리 Rust 데이터 접근 파일을 단계적으로 리팩터링하며, 같은 기능 변경에 드는 토큰 비용이 어떻게 바뀌는지 실험했다. 최종적으로 입력 토큰은 15만9564개에서 2만7360개로 83% 줄었고, 가장 큰 단일 파일은 1만7155줄에서 3695줄로 줄었다.

## 실험 배경

- Martin Fowler가 에이전트 기반 개발 환경에서 리팩터링의 경제적 이득을 직접 실험함
  - 대상 앱은 약 15만 줄 규모고, Rust가 약 12만 줄, 나머지는 TypeScript와 Terraform임
  - 고품질 웹 UI, 동적 갱신, 모달, 자동 저장, 외부 시스템 연동, 머신러닝과 텍스트 분석, 백그라운드 잡, 자동 배포까지 있는 앱이라고 함
  - 코드는 거의 전부 Claude Code와 Cursor가 작성했고, 저자는 가끔 흥미로 볼 때 말고는 읽거나 리뷰하지 않았음

- 문제는 데이터 접근 계층이 단일 Rust 파일 1만7155줄까지 커졌다는 점임
  - 같은 HTTP 요청 설정, JSON 인코딩과 디코딩, 읽기와 쓰기 패턴이 계속 반복됨
  - 내부 언어도 없고, 함수 추출이나 중복 제거도 거의 없었다고 함
  - 그래도 외부 인터페이스 경계는 명확해서 리팩터링 대상으로는 좋았음

## 실험 설계

- 목표는 “지금 리팩터링에 토큰을 쓰면, 앞으로 기능 변경에 드는 토큰이 줄어드는가”를 보는 것임
  - 인간 개발자는 반복 작업을 하며 학습하므로 실험이 오염될 수 있음
  - 반대로 에이전트는 매번 새 세션으로 시작하면 이전 시도에서 배우지 않기 때문에 같은 변경을 반복 측정하기 좋다고 봄

- 절차는 꽤 엄격했음
  - 전체 리팩터링 계획을 만들고, 대표 기능 변경 프롬프트를 하나 정함
  - 기준 상태에서 새 하위 에이전트에게 같은 변경을 시키고 토큰 사용량을 기록함
  - 변경은 버리고, 리팩터링 한 단계를 적용한 뒤 다시 같은 변경을 새 에이전트에게 시킴
  - 각 단계마다 입력 토큰, 출력 토큰, 걸린 시간, 코드 줄 수를 기록함

- 대표 변경은 Firestore 계층에 `ItemWatchStore` 비동기 trait을 추가하는 작업이었음
  - `watch_item`, `unwatch_item`, `watched_items_for_user` 세 메서드를 추가해야 했음
  - 실제 FirestoreStore와 인메모리 FakeStore 양쪽에 구현해야 했음
  - `item_watches` 컬렉션에 `itemId`, `userId`, `createdAt` 필드를 쓰는 조건도 포함됨

## 결과

- 최종 결과는 꽤 세게 나옴. 같은 변경의 입력 토큰이 83% 줄었음
  - 기준 입력 토큰은 159,564개
  - 최종 리팩터링 뒤 입력 토큰은 27,360개
  - 절감량은 132,204토큰이고, 비율로는 83%임
  - Sonnet 5 가격을 100만 토큰당 3달러로 계산하면 한 변경당 약 39.7센트 절약이라고 함

> [!IMPORTANT]
> 리팩터링으로 전체 데이터 접근 계층 코드량이 크게 줄어든 건 아님. 효과는 에이전트가 변경에 필요한 더 작은 파일 집합만 읽을 수 있게 된 데서 나왔음.

- 가장 큰 단일 파일 크기가 줄어들 때 입력 토큰도 본격적으로 떨어짐
  - 시작점에서는 데이터 접근 계층 전체가 1만7155줄짜리 단일 파일이었음
  - 최종 단계에서는 데이터 접근 계층이 19개 Rust 파일로 나뉨
  - 가장 큰 단일 파일은 1만7155줄에서 3695줄로 줄었음
  - 마지막 단계에서 입력 토큰이 104,080개에서 27,360개로 거의 절벽처럼 떨어졌다고 함

- 출력 토큰은 크게 줄지 않았음
  - 코드를 실제로 작성하는 출력 토큰 수는 대체로 비슷하게 움직임
  - 즉 리팩터링이 대표 변경 자체를 더 작게 만든 건 아니었음
  - 이번 실험에서 절약된 건 주로 “읽어야 하는 코드”였음

```mermaid
sequenceDiagram
    participant 개발자
    participant 리팩터링된코드
    participant 하위에이전트
    participant 토큰측정
    개발자->>리팩터링된코드: 한 단계 리팩터링 적용
    개발자->>하위에이전트: 같은 기능 변경 프롬프트 전달
    하위에이전트->>리팩터링된코드: 필요한 파일 탐색 및 읽기
    하위에이전트->>리팩터링된코드: ItemWatchStore 변경 작성
    하위에이전트->>토큰측정: 읽은 문자 수와 응답 문자 수 보고
    개발자->>리팩터링된코드: 변경 폐기 후 다음 단계 진행
```

## 무엇이 효과를 만들었나

- 단순히 파일을 랜덤하게 쪼갠다고 같은 효과가 나는 건 아니라고 함
  - 파일이 작아져도 관련 코드를 찾기 위해 여러 파일을 뒤져야 하면 토큰 절약이 약해질 수 있음
  - 이번에는 중복을 먼저 추출하고, 공통 구조가 보인 뒤 의미 있는 모듈 경계로 나눈 게 중요했음
  - FirestoreClient 추출, query helper, value constructor, FieldsBuilder, traits 분리, codec 분리, FakeStore 분리, store 하위 모듈 분리 같은 단계가 이어짐

- 에이전트는 리팩터링을 스스로 잘하지 못했다고 평가함
  - 명시적인 리팩터링 프롬프트와 사람이 만든 계획에 직접 반응해서 작업했을 뿐임
  - 저자의 개발 harness에 리팩터링 단계가 있었지만, Claude가 알아서 이 거대한 파일을 개선하지는 못했음
  - Claude.ai가 Claude Code보다 리팩터링 계획을 더 잘 잡았다는 관찰도 있음

- 적용 과정도 매끈하지 않았음
  - 실제 기계적 리팩터링은 Python 스크립트와 grep, sed로 수행됐는데, 들여쓰기 때문에 자주 꼬였다고 함
  - 가장 가치 있는 분리 단계가 첫 패스에서 빠져서 나중에 다시 지시해야 했음
  - 전체 실험은 약 8시간 걸렸고, 대부분은 방치형으로 돌아갔음

## 의미

- 이 실험은 AI 코딩 시대에 리팩터링의 경제적 의미가 바뀐다는 걸 보여줌
  - 예전 리팩터링은 주로 사람이 읽고 바꾸기 쉬운 구조를 만드는 일이었음
  - 이제는 에이전트가 관련 파일만 정확히 읽게 만들어 토큰 비용과 실행 시간을 줄이는 일도 됨
  - 한 번의 변경에서 39.7센트 절약은 작아 보여도, 디버깅과 반복 기능 개발 전체에 곱해지면 무시하기 어려움

- 다만 실험 한 번으로 일반화하긴 이르다고 저자도 말함
  - 리팩터링 자체에 든 토큰을 정확히 세지 못했고, 상한은 500만 토큰 정도로 추정함
  - 더 복잡한 변경, 더 넓은 코드베이스, 지속적 리팩터링, 리팩터링 방식별 효율 비교가 후속 과제로 남음

---

## 기술 맥락

- 이 글의 중요한 선택은 리팩터링 효과를 감으로 말하지 않고, 같은 변경을 반복 실행해서 토큰 비용으로 잰 거예요. 에이전트 코딩에서는 비용 단위가 시간뿐 아니라 입력 토큰이기 때문에, 구조 개선의 경제성이 더 직접적으로 드러나요.

- 단일 1만7000줄 파일을 나누는 이유는 “큰 파일은 못생겼다”가 아니에요. 에이전트가 변경 지점을 찾으려면 파일을 많이 읽어야 하고, 그 읽기 비용이 매번 반복되기 때문이에요.

- 여기서 중요한 건 파일 개수보다 경계예요. query, codec, fake store, trait, store 구현처럼 의미 있는 단위로 나눠야 에이전트가 필요한 부분만 고를 수 있어요. 그냥 줄 수만 맞춰 자르면 오히려 탐색 비용이 남아요.

- 인간의 역할도 분명해져요. 에이전트가 코드를 많이 만들 수는 있지만, 어떤 구조로 쪼개야 다음 변경이 싸지는지 판단하는 일은 아직 사람이 강하게 잡아줘야 해요.

- 이 실험은 DevOps 비용 관점으로도 볼 수 있어요. CI 시간이 줄어드는 리팩터링처럼, 에이전트 입력 토큰이 줄어드는 리팩터링도 앞으로는 아키텍처 의사결정의 한 축이 될 수 있어요.

## 핵심 포인트

- 약 15만 줄 앱을 Claude Code와 Cursor 에이전트로 만들었고, 그중 Rust가 약 12만 줄
- 데이터 접근 계층이 단일 Rust 파일 1만7155줄까지 커진 뒤 리팩터링 실험 대상이 됨
- 같은 대표 변경을 각 리팩터링 단계마다 새 에이전트에게 시켜 입력 토큰, 출력 토큰, 시간, 코드 줄 수를 측정
- 최종 단계에서 입력 토큰이 15만9564개에서 2만7360개로 83% 감소
- 저자는 에이전트가 스스로 좋은 리팩터링을 찾지는 못했고, 인간의 명시적 계획과 지도가 필요했다고 평가

## 인사이트

AI 코딩 시대의 리팩터링은 ‘사람이 읽기 좋게’에서 끝나지 않고 ‘에이전트가 필요한 파일만 읽게 만들어 비용과 시간을 줄이는 작업’이 된다. 큰 파일을 잘게 자르는 게 아니라, 의미 있는 경계로 쪼개야 효과가 난다는 점이 진짜 포인트다.
