리팩터링의 경제적 이점: AI가 짠 코드를 정리하면 토큰 비용이 83% 줄었다 (Giles Edwards-Alexander)
원문 정보
- 제목: The Economic Benefit of Refactoring
- 출처: martinfowler.com — “Exploring Gen AI” 시리즈 · 저자 Giles Edwards-Alexander (Thoughtworks, CTO for Europe, Middle East and India)
- 발행: 2026-07-30 · 약 12~15분 분량
- 원문 링크: https://martinfowler.com/articles/exploring-gen-ai/refactoring-economic-benefit.html
리팩터링은 오랫동안 “지금은 값을 못 매기지만 나중에 이롭다”는, 신념에 가까운 실천이었다. 이 글은 에이전트가 코드를 만드는 시대에 그 이점을 토큰 단위의 숫자로 측정해 보인다. 그래서 Articles의 AI-Engineering — 에이전트 코드베이스를 만들고 운영하는 실무 — 에 담는다.
한 줄 요약 (TL;DR)
AI 에이전트가 작성한 17,155줄짜리 단일 Rust 파일을 Martin Fowler의 리팩터링 패턴을 따라 15단계로 정리하자, 동일한 기능을 추가하는 데 드는 입력 토큰이 159,564개에서 27,360개로 83% 줄었다. 코드의 총량은 거의 그대로였는데도(오히려 3%만 감소) 비용이 급감한 이유는, 잘 구조화된 코드에서는 에이전트가 전체를 훑지 않고 필요한 작은 파일만 읽어도 되기 때문이다. 리팩터링은 이제 “미래의 토큰 소비를 낮추기 위해 지금 토큰을 쓰는” 계산 가능한 투자다.
한눈에 보기: 왜 같은 코드가 더 싸졌나
flowchart LR
A["17,155줄<br/>단일 파일"] -->|"리팩터링 전"| B["에이전트가<br/>전체를 통째로 읽음"]
B --> C["입력 토큰<br/>159,564"]
A -.->|"15단계 리팩터링<br/>(코드 총량 -3%)"| D["작은 모듈들<br/>(가장 큰 파일 3,695줄)"]
D -->|"리팩터링 후"| E["필요한 파일만<br/>골라 읽음"]
E --> F["입력 토큰<br/>27,360"]
C -.->|"-83%"| F
코드의 총량은 거의 그대로(-3%)인데, 에이전트가 읽어야 할 양이 줄어 입력 토큰이 83% 감소한다.
왜 이 글을 골랐나
에이전트로 코드를 짜는 팀이라면 누구나 마주치는 질문이 있다. “AI가 만든 코드도 정리해야 하나? 어차피 AI가 다시 짤 텐데?” 사람 개발자에게 리팩터링의 이점은 “가독성”, “유지보수성” 같은 정성적 언어로 정당화돼 왔고, 그래서 늘 우선순위 싸움에서 밀렸다.
이 글이 특별한 건 그 이점을 돈으로 환산했다는 점이다. 게다가 실험 설계가 영리하다. 저자는 “에이전트는 사람과 달리 학습하지 않는다”는 성질을 역이용한다. 사람은 같은 작업을 반복하면 익숙해져 측정이 오염되지만, 에이전트는 매번 백지 상태에서 시작하므로 깨끗한 A/B 테스트가 가능하다. 리팩터링 단계마다 동일한 기능 추가를 다시 시켜 토큰을 재는, 사람으로는 불가능했던 통제 실험이다.
우리 위키에는 이미 Intent Debt — 에이전트가 대신 갚아줄 수 없는 부채나 잘못된 추상화: 중복보다 더 비싼 죄처럼 “AI 시대의 코드 품질”을 다룬 글이 있다. 이 글은 거기에 정량적 근거를 더해준다.
핵심 내용
실험의 무대: 리뷰 없이 에이전트로 만든 15만 줄 애플리케이션
저자는 약 15만 줄 규모의 애플리케이션을 코드를 직접 리뷰하지 않고 전적으로 AI 에이전트(대부분 Claude Code, 일부 Cursor)로 만들었다. 이 중 약 12만 줄이 Rust이고 나머지는 TypeScript와 Terraform이다. 개발 과정에서 데이터 접근 계층(data access layer) 하나가 17,155줄짜리 단일 파일로 부풀어 올랐다 — 전형적인 리팩터링 후보다.
실험 설계: 학습하지 않는 에이전트를 이용한 통제 실험
핵심 방법론은 다음과 같다.
- 엄격한 규율을 따르는 리팩터링 계획을 먼저 수립한다.
- 대표 기능을 하나 정한다 — 세 개의 메서드를 가진
ItemWatchStore트레이트를 추가하는 변경. - 리팩터링 전 상태에서 이 변경의 기준선(baseline) 토큰 비용을 측정한다.
- 15개의 리팩터링 단계를 순차적으로 적용한다.
- 각 단계가 끝날 때마다 동일한 변경을 다시 실행하고 토큰 소비를 측정한다.
- 매 측정 후 구현을 폐기해 에이전트가 “학습”으로 오염되는 것을 막는다.
토큰은 tiktoken 대신 문자 수를 4로 나눈 근사치를 프록시로 썼다(저자도 이 근사의 한계를 인정한다).
결과: 코드는 그대로인데 비용은 83% 감소
| 지표 | 기준선 | 최종(15단계) | 변화 |
|---|---|---|---|
| 입력 토큰 | 159,564 | 27,360 | -83% (132,204 절감) |
| 출력 토큰 | 1,705 | 2,113 | +24% |
| 데이터 계층 총 LoC | 17,155 | 16,608 | -3% |
| 가장 큰 파일 LoC | 17,155 | 3,695 | -78% |
가장 중요한 통찰은 코드 총량은 거의 변하지 않았다는 점이다(-3%). 그런데도 입력 토큰이 83% 줄었다. 저자의 표현을 빌리면:
“This saving is because the agent has to read less code. But it is not because there is less code to read.” (이 절감은 에이전트가 더 적은 코드를 읽어야 하기 때문이지, 읽을 코드가 줄었기 때문이 아니다.)
즉 잘 분해된 구조에서는 에이전트가 거대한 모놀리스를 통째로 스캔하는 대신, 작고 초점이 맞은 파일만 식별해 읽는다. 가장 큰 파일이 17,155줄에서 3,695줄로 줄어든 것이 이 “외과적 읽기(surgical reading)”를 가능케 했다.
15단계 리팩터링: 지역적 추출에서 모듈 분해로
모든 단계는 Martin Fowler의 Refactoring 2판 패턴을 따랐고, 대략 세 국면으로 나뉜다.
- 1~6단계 — 지역적 추출(Local Extraction):
FirestoreClient전송 계층을 Extract Class로 분리,extract_doc_id·new_link같은 함수 추출, Firestore 값 생성자 인라인 대체, 문서 인코딩용FieldsBuilder클래스 추출 등. 먼저 지역적 중복을 제거한다. - 7~12단계 — 모듈 분해(Module Decomposition): 상수·타입 정의를
queries.rs로, 트레이트 정의를traits.rs로 옮긴 뒤 이를 다시 도메인별 네 파일(각 300~650줄)로 분리. 인코더/디코더는codec.rs로, 약 4,700줄짜리fake_store.rs를 별도로 추출,FirestoreStore구현을 도메인별 10개 파일로 분할. - 13~15단계 — 테스트 정리(Test Organization): 테스트를 각 모듈과 같은 위치로 옮겨 관심사를 완전히 분리.
핵심 순서는 “먼저 지역적 중복 제거 → 그다음 구조적 분해”다. 아무 파일이나 잘게 쪼개는 것으로는 이득이 없다.
과정에서 관찰한 것: 사람이 여전히 설계자다
저자는 Claude의 한계를 솔직히 기록한다.
“Claude is unable to look at code, look at refactorings in general and work out which are suitable to apply: a human needs to actively guide it.” (Claude는 코드를 보고 일반적인 리팩터링들을 검토해 무엇이 적합한지 스스로 판단하지 못한다. 사람이 능동적으로 이끌어야 한다.)
에이전트는 명시적이고 상세한 지시를 받았을 때만 잘 해냈다. 흥미롭게도 계획 수립에서는 Claude Code보다 Claude.ai(웹 채팅)가 더 나았다고 한다.
숨은 비용과 남은 질문
실험 자체는 무인 실행으로 약 8시간, 계획과 실행에 최대 500만 토큰가량이 들었을 수 있다. 단일 변경 하나로 회수되는 비용이 아니다. Sonnet 5 가격($3/MTok) 기준으로 대표 변경당 절감액은 약 39.7센트. 개별로는 소액이지만, 앞으로의 수천 번 변경(기능 개발·디버깅·추가 리팩터링)에 걸쳐 복리로 누적된다. 저자는 이 실험이 그린필드 프로젝트 위의 단일 사례임을 인정하며, 레거시 시스템·복잡한 변경·지속적 리팩터링 전략으로의 확장 검증을 남은 과제로 제시한다.
분석과 인사이트
여기부터는 원문 요약이 아니라 내 관점이다.
1. “코드 품질”이 드디어 손익계산서로 들어왔다. 사람 개발자에게 리팩터링은 늘 “미래의 나를 위한 선의”였고, 그래서 스프린트 압박 앞에서 가장 먼저 희생됐다. 이 글의 진짜 기여는 83%라는 숫자 자체가 아니라, 리팩터링의 이점을 재무 지표로 번역하는 방법론을 제시했다는 점이다. 이제 “이 리팩터링을 하면 이 코드베이스에 대한 향후 에이전트 작업 비용이 N% 낮아진다”고 말할 수 있다. 정성적 논쟁이 정량적 예산 항목이 된다.
2. 메커니즘이 핵심이다: 비용은 ‘코드 양’이 아니라 ‘읽어야 하는 양’에 걸린다. 총 LoC가 3%만 줄었는데 토큰이 83% 줄었다는 대비가 이 글의 심장이다. 이는 컨텍스트 엔지니어링의 관점과 정확히 맞닿는다 — 에이전트에게 중요한 건 코드베이스의 절대 크기가 아니라 한 작업을 위해 컨텍스트 창에 얼마나 밀어 넣어야 하는가다. 잘 분해된 모듈 경계는 곧 “에이전트가 무시해도 되는 코드”를 만들어 주는 것이고, 이것이 인간 유지보수성과 에이전트 비용이 같은 방향을 가리키는 이유다.
3. 단, 파일을 잘게 쪼개는 것 ≠ 리팩터링. 저자가 못 박듯, 도메인 경계 없이 파일만 잘게 나누면 에이전트가 여러 작은 파일을 뒤지느라 비슷한 비용을 치를 수 있다. 응집도 높은 경계 설정이 관건이다. 이 지점에서 잘못된 추상화의 교훈이 그대로 유효하다 — 잘못 그은 경계는 중복보다 비싸다. 즉 AI 시대에도 “좋은 설계”의 정의는 바뀌지 않았고, 다만 그 대가가 더 즉각적으로 청구될 뿐이다.
4. 인간의 자리가 명확해졌다. 에이전트는 리팩터링을 실행할 수 있지만 무엇을·언제·어떻게 리팩터링할지 판단하지는 못했다. 이건 짧은 목줄 방법이나 Intent Debt가 말하는 것과 같은 결론이다 — 설계 의도와 구조적 판단은 여전히 사람의 몫이고, 에이전트는 그 판단을 값싸게 집행하는 도구다. “리뷰 없이 15만 줄을 만들었다”는 도발적 전제와, “그런데 리팩터링 방향은 사람이 일일이 지시해야 했다”는 결론 사이의 긴장이 이 글에서 가장 정직한 부분이다.
5. 한계는 분명하다. 문자 수 ÷ 4라는 토큰 근사치, 단일 그린필드 사례, 단일 변경 유형이라는 조건은 결과를 일반화하기엔 좁다. 리팩터링에 든 500만 토큰과 8시간이 실제로 언제 회수되는지 — 손익분기 분석이 빠져 있다. 그럼에도 방향성은 설득력 있다: 에이전트 코드베이스에서 구조는 곧 비용이다.
적용 포인트
- 리팩터링을 비용 관점으로 재프레이밍하라. 팀에 리팩터링을 제안할 때 “깨끗해진다” 대신 “이 모듈에 대한 향후 에이전트 작업의 입력 토큰이 줄어든다”로 말하라. 예산 회의에서 이기는 언어다.
- 모놀리식 거대 파일을 우선 타깃으로. 수천 줄짜리 단일 파일은 에이전트가 매 작업마다 통째로 읽어야 하는 상습 비용 지점이다. 가장 큰 파일부터 도메인 경계로 분해하라.
- 순서를 지켜라: 지역적 중복 제거 먼저, 구조적 분해는 그다음. 아무 파일이나 잘게 쪼개는 것은 오히려 탐색 비용을 늘릴 수 있다.
- 리팩터링은 에이전트에게 명시적·단계적으로 지시하라. “이 코드 리팩터링해줘” 같은 열린 지시로는 에이전트가 무엇이 적합한지 판단하지 못한다. Fowler의 명명된 패턴(Extract Class, Move Function 등)을 단계별로 지정하라.
- A/B로 측정하라. 에이전트는 학습하지 않으므로, 리팩터링 전후에 동일 작업을 재실행해 토큰을 재면 구조 변경의 효과를 실제로 검증할 수 있다. 이건 사람 팀에서는 불가능했던 이점이다.
- 계획은 다른 도구를 써보라. 저자는 실행용 Claude Code보다 계획 수립에서 Claude.ai가 나았다고 한다. 리팩터링 설계와 집행의 도구를 분리해 실험해 볼 가치가 있다.
마무리
이 글은 “AI가 짠 코드는 정리할 필요가 없다”는 흔한 직관을 정면으로 반박한다. 오히려 반대다 — 에이전트가 코드를 다룰 때, 잘 구조화된 코드는 매 작업마다 토큰으로 배당금을 지급한다. 리팩터링의 오래된 미덕(응집도, 명확한 경계, 작은 단위)은 하나도 바뀌지 않았지만, 그 이점은 이제 정성적 신념이 아니라 청구서에 찍히는 숫자가 되었다. 그리고 그 숫자를 만들어 내는 판단은 여전히 사람의 손에 있다.
더 읽어보기
- 원문 — The Economic Benefit of Refactoring (Giles Edwards-Alexander, martinfowler.com)
- Intent Debt: 에이전트가 대신 갚아줄 수 없는 단 하나의 부채 (Addy Osmani) — AI가 코드를 짜도 남는 부채의 본질
- 잘못된 추상화: 중복보다 더 비싼 죄 (Sandi Metz) — 왜 “파일 쪼개기 ≠ 좋은 경계”인지의 원리
- 짧은 목줄(Short Leash) 방법 — AI 코딩 에이전트를 통제하며 고품질 코드 만들기 (Greg Slepak) — 에이전트를 이끄는 사람의 역할
- 바이브 코딩과 에이전틱 엔지니어링 (Simon Willison) — 컨텍스트를 다루는 에이전트 개발의 감각
- Refactoring: 동작을 지키며 설계를 개선하는 규율 — 이 실험이 따른 Fowler 리팩터링 패턴의 원전 정리