1P by GN⁺ | ★ favorite | 댓글 1개
  • 에이전트가 작성한 17,155줄 규모의 Rust 데이터 접근 계층을 단계적으로 리팩터링하자, 같은 기능 변경에 필요한 입력 토큰이 159,564개에서 27,360개로 83% 감소
  • 전체 코드량은 거의 그대로였지만 관련 코드를 응집도 높은 파일로 분리하면서, 에이전트가 변경에 필요한 최소 파일 집합만 읽을 수 있게 됨
  • 입력 토큰은 가장 큰 파일이 충분히 작아지기 전까지 크게 줄지 않았으며, 최종적으로 데이터 계층을 19개 Rust 파일로 나누고 최대 파일 크기를 17,155줄에서 3,695줄로 줄임
  • 출력 토큰과 기능 구현량은 거의 변하지 않았고 Claude도 적절한 리팩터링을 스스로 선택하거나 안정적으로 수행하지 못해, 계획과 실행에 사람의 적극적인 지침이 필요했음
  • Sonnet 5의 입력 가격 $3/MTok 기준으로 변경 1회당 절감액은 약 $0.397에 불과하지만, 이후 데이터 접근 계층을 수정할 때마다 비용이 반복적으로 줄어들 가능성을 확인함

에이전트가 만든 17,155줄짜리 파일

  • 업무 지원용 애플리케이션은 동적 갱신·조회가 가능한 웹 UI, 모달과 자동 저장, 외부 시스템 연동, 머신러닝과 텍스트 분석, 백그라운드 작업, 자동 배포 환경을 갖춤
  • 전체 약 15만 줄 가운데 Rust가 약 12만 줄이고 나머지는 TypeScript와 Terraform이며, 대부분 Claude Code와 일부 Cursor를 이용해 에이전트가 작성함
  • 개발자는 흥미로 가끔 살펴본 경우를 제외하면 코드를 읽거나 검토하지 않았음
  • 데이터 접근 계층은 모든 읽기·쓰기 쿼리에서 같은 HTTP 요청 설정과 JSON 인코딩·디코딩을 반복하면서 6,000줄 이상으로 성장했고, 결국 하나의 Rust 파일이 17,155줄에 도달함
  • 이 모듈에는 중복 제거와 내부 언어가 없고 함수 추출이 제한적이며 클래스 추출도 거의 없었지만, 보존할 인터페이스와 명확한 경계가 있어 리팩터링 실험에 적합했음

동일한 변경을 반복한 측정 방식

  • 목표는 현재 리팩터링에 토큰을 투자해 향후 기능 변경의 토큰 소비를 낮출 수 있는지 확인하는 것이었음
  • 에이전트는 이전 작업에서 학습하지 않으므로, 매 단계마다 새 하위 에이전트에게 정확히 같은 변경을 요청해 학습 효과가 섞이지 않도록 함
  • 실험은 다음 순서로 진행함
    • 엄격한 리팩터링 원칙에 따라 전체 계획을 작성함
    • 하나의 프롬프트로 대표 변경을 정의함
    • 하위 에이전트가 변경을 수행하고 토큰 소비량을 보고하게 해 기준값을 측정함
    • 변경 결과를 폐기한 뒤 리팩터링 한 단계를 적용함
    • 같은 변경을 다시 수행하고 결과를 폐기하는 과정을 반복함
    • 단계별 토큰 비용, 실행 시간, 코드 줄 수를 기록함
  • Claude가 실시간 토큰 수를 신뢰성 있게 제공하지 못해 송수신 문자 수를 보고하게 하고, tiktoken으로 문자 수를 4로 나눠 토큰을 근사함

단계별 측정 결과

  • 기준 상태에서는 데이터 접근 계층과 최대 파일이 모두 17,155줄, 전체 Rust 코드는 50,359줄이었고 대표 변경에 입력 159,564토큰, 출력 1,705토큰, 342초가 필요했음
  • 15단계 이후 데이터 접근 계층은 16,608줄, 최대 파일은 3,695줄, 전체 Rust 코드는 49,812줄이었으며 입력 27,360토큰, 출력 2,113토큰, 실행 시간은 454초였음
  • 중간 단계에서는 최대 파일이 작아질수록 입력 토큰도 함께 감소함
    • 7단계 queries.rs 추출 후 최대 파일은 15,670줄, 입력은 151,850토큰으로 줄어듦
    • 8단계 traits.rs 추출 후 최대 파일은 13,845줄, 입력은 132,558토큰이 됨
    • 12단계 store/ 분리 후 최대 파일은 9,269줄, 입력은 104,080토큰까지 감소함
    • 마지막 store/ 분리 후 최대 파일은 3,695줄, 입력은 27,360토큰으로 급감함
  • 최종 데이터 접근 계층은 19개 Rust 파일로 구성됐고, 가장 큰 파일은 테스트 라이브러리가 됨
  • 추가 리팩터링에서도 같은 방식을 해당 테스트 파일에 적용할 수 있음

입력 토큰이 83% 줄어든 이유

  • 같은 작업의 입력 토큰은 159,564개에서 27,360개로 줄어 132,204토큰을 절약
  • 데이터 접근 계층의 전체 코드량은 거의 변하지 않았으므로, 읽을 코드 자체가 줄어든 결과는 아님
  • 에이전트가 작업에 필요한 최소 파일 집합을 식별해 점점 더 작은 코드 영역만 읽었으며, Claude Code의 사고 출력과 파일 읽기 요약에서도 이를 확인할 수 있었음
  • 파일을 임의로 잘게 나누기만 하면 관련 코드를 찾으려고 여러 파일을 읽어야 하므로 같은 효과를 얻기 어려움
  • 가장 큰 감소는 마지막 분리에서 발생했지만, 앞선 단계에서 중복을 추출하고 반복되는 핵심 구조를 만든 덕분에 파일 분리가 가능했음
  • 이 순서는 비용 절감을 목표로 사전에 설계한 것이 아니라, 로컬 중복을 먼저 제거하고 공통 핵심이 드러난 뒤 작은 파일로 분해하는 일반적인 리팩터링 과정에서 나옴

출력 토큰과 금전적 효과

  • 대표 변경을 작성할 때 생성된 출력 토큰은 거의 변하지 않아, 리팩터링이 실제 변경 크기까지 줄이지는 못함
  • 출력 토큰 가격은 입력 토큰의 5배였지만 절대량은 훨씬 적었음
  • Sonnet 5 입력 가격을 $3/MTok으로 계산하면 변경 1회당 절감액은 약 39.7센트
  • 디버깅이나 더 복잡한 기능, 코드베이스 전체 리팩터링에서도 절감이 누적되는지와 리팩터링 자체 비용이 얼마인지는 확인되지 않음
  • 출력 토큰까지 줄이는 리팩터링이 가능한지도 불분명하며, 단순한 대표 변경에서는 비결정적 코드 생성의 잡음이 구조 변화에 따른 차이를 가렸음

Claude와 진행한 리팩터링

  • Claude는 코드를 보고 적용할 리팩터링을 스스로 선택하지 못했으며, 실제 결과는 프롬프트가 직접 지시한 작업에 대응함
  • 개발 하네스에 명시적인 리팩터링 단계가 있었지만, Claude는 이를 통해 17,155줄짜리 파일을 개선하지 않았음
  • 계획 수립 과정에서 Claude Code는 함수 추출을 첫 단계로 찾은 반면, Claude.ai는 전체 클라이언트 클래스 추출까지 식별함
  • 기계적인 변경에는 grepsed를 사용하는 Python 스크립트를 활용했지만, 스크립트가 들여쓰기 때문에 자주 혼란을 겪음
  • 가장 가치가 컸던 저장소 파일 분리는 첫 시도에서 누락돼 후속 단계로 다시 적용했으며, 이 때문에 측정 결과의 단계 수와 부록의 계획 단계가 일치하지 않음
  • 전체 실험에는 약 8시간이 걸렸고 대부분 무인으로 진행됨
    • 6시간 40분 뒤 누락된 단계를 발견해 한 차례 개입함
    • 느린 호텔 Wi-Fi보다 지나치게 커진 Cargo 임시 빌드 캐시가 테스트 실행을 크게 늦춘 원인이었음

대표 변경 프롬프트

  • 각 하위 에이전트는 코드베이스와 아키텍처 문서만 제공받고 동일한 ItemWatchStore 비동기 공개 트레이트를 구현함
  • 트레이트는 다음 세 메서드를 포함함
    • watch_item(&self, item_id: &str, user_id: &str) -> Result<()>
    • unwatch_item(&self, item_id: &str, user_id: &str) -> Result<()>
    • watched_items_for_user(&self, user_id: &str) -> Result<Vec<String>>
  • watch 정보는 Firestore의 item_watches 컬렉션에 itemId, userId, createdAt 필드로 저장함
  • 별도의 Rust 레코드 구조체 없이 item ID의 Vec<String>을 반환함
  • FakeStore에는 메모리 내 Vec<(String, String)> 필드를 추가하고, FirestoreStore에는 기존 HTTP 패턴을 그대로 사용해 구현함
  • 응답 마지막에는 읽은 파일과 문자 수, 응답 문자 수를 JSON으로 출력하게 했으며 코드는 커밋하지 않도록 지시함

적용한 리팩터링 계획

  • 1단계 — FirestoreClient 클래스 추출

    • 도메인 쿼리 조정과 Firestore HTTP 전송 책임을 분리함
    • reqwest::Client, project_id, MetadataAuth, URL·인증 헤더 처리를 새 구조체로 옮김
    • 계획상 FirestoreStore 구현에서 약 1,200줄을 줄이고 클라이언트에 약 120줄을 추가함
  • 2단계 — extract_doc_id, new_link 함수 추출

    • 20개 문서 파서의 ID 추출과 62회 반복된 Link 생성을 공통화함
    • 약 500줄 절감을 예상함
  • 3단계 — 링크 쿼리 파이프라인 함수 추출

    • 약 15곳의 쿼리 결과 수집과 약 8곳의 단일 대상 ID 조회 패턴을 공통화함
    • 약 200줄 절감을 예상함
  • 4단계 — FakeStoreInner 링크 조건 함수 추출

    • 약 15개 메서드에 반복된 inner.links.iter() 변형을 두 메서드로 분리함
    • 약 120줄 절감을 예상함
  • 5단계 — Firestore 값 생성 함수 도입

    • 128회 이상 반복된 문자열·타임스탬프 등의 json! 표현을 네 개의 함수 호출로 교체함
    • 여러 줄 매크로를 한 줄 호출로 바꿔 약 80줄 절감을 예상함
  • 6단계 — FieldsBuilder 추출

    • 약 20개 인코더의 필드 맵 생성 패턴을 빌더로 통합함
    • 약 40줄짜리 인코더를 약 12줄로 줄여 총 500~600줄 절감을 예상함
  • 7단계 — queries.rs 분리

    • 32개 LinkQuery 상수와 관련 타입을 별도 모듈로 이동함
    • 기존 호출부를 변경하지 않고 mod.rs에서 약 800줄을 줄임
  • 8단계 — traits.rs 분리

    • 17개 공개 트레이트와 관련 오류 타입을 이동하고 다시 내보냄
    • mod.rs에서 약 1,900줄을 줄이지만 새 파일도 약 1,900줄이 됨
  • 9단계 — traits/ 도메인별 분리

    • 트레이트를 planning.rs, content.rs, people.rs, system.rs로 나눔
    • 정의와 호출부를 바꾸지 않고 파일별 크기를 약 300~650줄로 제한함
  • 10단계 — codec.rs 분리

    • 문서 인코더·디코더, 파서, FieldsBuilder, 값 생성 함수를 이동함
    • 6단계 이후 약 400~500줄짜리 모듈이 되며 mod.rs에서 약 500줄을 줄임
  • 11단계 — fake_store.rs 분리

    • FakeStore, FakeStoreInner, 18개 트레이트 구현을 이동함
    • mod.rs에서 약 4,700줄을 줄임
  • 12단계 — FirestoreStore 구현 분리

    • store/mod.rs에는 구조체, 생성자, FirestoreClient, MetadataAuth를 두고 트레이트 구현은 도메인별 파일로 나눔
    • 약 10,000줄짜리 파일을 각각 120~650줄인 10개 파일로 바꾸고 mod.rs는 약 100줄짜리 재내보내기 파일로 만듦
  • 13단계 — 테스트를 대상 모듈과 함께 배치

    • 테스트 코드는 바꾸지 않고 각 구현 파일 아래로 이동함
    • mod.rs에서 약 2,000줄을 줄이고 각 파일에는 관련 테스트 200~700줄이 추가됨

한계와 후속 실험

  • 리팩터링 계획 작성과 실행에 든 토큰을 별도로 세지 않아 리팩터링 투자 비용을 정확히 계산할 수 없음
  • 해당 시간대 전체 사용량을 기준으로 한 상한은 500만 토큰이지만, 여기에는 계획을 두 번 작성한 작업, 실험 및 대표 변경 설계, 기타 작업이 모두 포함됨
  • 실험 대상은 아직 그린필드 단계이고 한 개발자가 구축·관리하는 하나의 대규모 애플리케이션이므로 결과를 일반화할 수 없음
  • 후속 작업으로 정확한 리팩터링 토큰 측정, 더 복잡한 변경, 더 넓은 범위의 리팩터링, 지속적 리팩터링, 접근 방식별 상대 가치 비교가 필요함
  • 이번 실험은 리팩터링으로 얻는 시간·금전적 가치와 리팩터링 자체 비용을 함께 측정할 수 있는 출발점이 됨

댓글과 토론

Hacker News 의견들
  • 대부분의 IT 회사가 무시하던 개발자 모범 사례가 AI 모범 사례로 재발명되는 모습이 재미있음
    예전에는 코드 안에 문서를 두고, Jira 작업만 던지지 말고 프로젝트 전체 맥락을 알려주며, 장기 생산성을 위해 리팩터링하라고 하면 지루하게 여겼음
    이제 같은 내용을 AI 문서는 코드와 CLAUDE.md에 두고, 프롬프트로 세세하게 통제하지 말며, AI 생산성을 위해 리팩터링하자고 하면 흥미롭게 받아들여짐

    • 인간 동료보다 AI 에이전트가 같은 일을 일관되게 수행하도록 만들기 훨씬 쉬움
      인간은 옳은 방법을 알아도 바쁘거나 집중력이 흐트러지지만, 에이전트는 지루한 작업에 싫증 내지 않으므로 인간에게 효과가 입증됐지만 꾸준히 적용하기 어려웠던 절차가 현실적으로 가능해짐
      공통 명세를 바탕으로 구현과 테스트를 별도 에이전트가 작성하고 감사 에이전트가 검증하게 해 서로의 결과에 오염되지 않도록 했는데, 이는 IBM이 1980년대 인간을 위해 개발한 클린룸 공학을 AI로 폭넓고 일관되게 적용한 것임
    • 이 글과 관련된 인물은 20여 년 전 책 《Refactoring》을 써서 해당 용어를 대중화한 Martin Fowler
      낡은 관행을 AI 유행에 맞춰 새것처럼 포장하는 게 아니라, 20년 넘은 모범 사례가 여전히 유효하다는 점을 근거와 함께 보여주는 것임
    • AI 이전과 이후의 큰 차이는 인간에게는 꽤 좋은 장기 맥락 관리 능력이 있다는 것임
      에이전트는 세션마다 맥락을 새로 습득해야 하므로 모범 사례의 가치가 훨씬 커지고 효과도 즉시 나타남
    • AI 열풍 덕분에 원하던 개발자 경험 개선 작업에 예산을 받을 수 있게 됐지만, 그 이유가 잘못됐다는 점은 씁쓸함
      그래도 한 시간 동안 CLI를 100번 실행시켜 새 플래그의 사용성을 시험할 수 있는 건 좋음
    • 인간은 SharePoint의 낡은 문서, 회의 중 흘려들은 전체 맥락, 낮은 리팩터링 우선순위 속에서도 품질과 일정이 나빠질 뿐 어떻게든 결과를 만들어냄
      반면 AI는 이런 기반이 없으면 매우 형편없이 수행하거나 아예 작동하지 않으므로, 건전한 엔지니어링 관행이 장기적 개선책이 아니라 필수 전제조건이 됨
      실제 순효과가 전혀 없더라도 AI를 작업 흐름에 넣으면 제대로 된 개발 관행을 도입할 명분이 생긴다는 점에서는 유용함
  • 이 글은 AI 도구가 실제로 어떻게 쓰이는지에 기반해 구체적이고 정량적으로 비판한다는 점이 좋음
    실제 사용 사례 없이 사회적 위험을 막연히 논하는 글보다, AI가 무엇을 못하는지 측정값으로 보여주는 글이 훨씬 유익함
    같은 이유로 Boko Haram 조직원을 인터뷰해 AI가 테러에 어떻게 활용됐는지 조사한 보고서도 인상적이었음

  • AI 없이 직접 하는 리팩터링을 정말 좋아함
    눈에 보이는 변화는 없지만 지금 당장 성과가 드러나지 않을 웹사이트를 미래에 훨씬 다루기 쉽게 만든다는 데 만족감을 느낌
    이미 정립된 패턴으로 해결된 문제를 과거의 기괴한 우회 코드가 다시 풀고 있는 모습을 찾아 모범 사례 쪽으로 옮기되 새 기술 부채를 만들지 않는 과정이 퍼즐처럼 즐거움
    인증까지 모든 것을 엉성하게 직접 구현해 어려운 방식으로 내부 원리를 배웠고, 그 결과 앞으로 10년간 즐길 리팩터링 거리도 생겼음

    • Fowler의 《Refactoring》을 읽고 과학·연구용 코드에도 효과가 있을지 의심했지만, 불만스러운 코드 구조에 실험적으로 적용한 뒤 관점이 완전히 바뀌었음
      코드베이스는 하나의 시스템이라는 말을 구체적으로 이해하게 됐고, 코드를 당기고 눌러볼 수 있는 연속적인 조직이나 그물처럼 높은 수준에서 보게 됨
      AI가 이런 학습 과정을 없앨 수 있다는 점이 주니어 개발자 문제를 부각함. 직관을 얻으려면 직접 깊이 파고드는 수밖에 없으며, Naur가 40년 전에 경고했어도 이 교훈은 계속 잊힘
    • Windows 98 디스크 조각 모음 화면을 볼 때처럼 도파민 보상을 받기 때문일 수도 있음
    • 그 감정은 장인으로서의 자부심임. 이해하는 사람에게는 설명이 필요 없고, 이해하지 못하는 사람에게는 어떤 설명도 통하지 않음
    • 리팩터링 중 회귀를 막기 위해 테스트 스위트를 어느 정도 안전장치로 구축했는지 궁금함
    • 여러 리팩터링 패턴과 실제 적용 사례를 공부하는 과정이 즐거움
  • 에이전트가 리팩터링할 때는 인간 참여가 필수적이라고 봄
    생성 모델이 초기 작업에 집중하며 놓친 부분을 검토 모델이 찾을 수는 있지만, 프로젝트 전체의 목적과 코드가 결합되는 방식을 실제로 이해해 중복이나 더 우아한 구조를 판별할 수 있는지는 의문임
    코딩 에이전트에게 리팩터링을 맡기는 일은 외상외과 의사에게 운동 능력을 높여달라고 하는 것과 비슷하며, 제대로 하려면 전체론적 관점이 필요함
    큰 파일을 여러 파일로 나누는 것만으로는 피상적 리팩터링에 그침. 어떤 코드가 함께 있어야 하고 무엇을 유틸리티 함수로 추출할지에 대한 이론이 없다면 인수분해가 아니라 큰 수를 작은 수로 쪼갠 뒤 다시 더하는 것에 가까움
    에이전트는 API에서 이미 가져오는 값을 다시 저장하고 계산하는 시스템을 만들기도 하지만, 인간은 프로젝트 전체를 보면서 JSON의 특정 키에 필요한 데이터가 이미 있다는 사실을 정밀하게 찾아낼 수 있음

    • 현재 LLM도 특정 코드 구간에 구체적인 리팩터링을 지시하면 충분히 잘 수행함. 예를 들어 데이터 클래스 대신 functools.partialCommand 패턴을 구현하라는 복잡한 요구도 처리 가능함
      파일 경계는 논리적 하위 시스템의 경계를 나타내 추론을 쉽게 하며, 다른 파일의 내용은 기본적으로 불투명하게 취급한다는 개념도 학습 데이터에 풍부함
      이 구조의 이점은 인간 인지의 우연한 특성만이 아니라 객관적인 측면도 있다고 봄
    • 인간이 옆에서 방향을 설명하는 방식으로 몇 달 걸릴 리팩터링을 약 일주일 만에 대부분 끝냈음
      리팩터링 경력과 타인의 코드베이스를 다룬 방식, 원래 설계자로서 과거와 현재의 의도를 설명할 수 있었던 점이 도움 됐음
      의존성 취약성이 적고 LLM이 다루기 쉬운 비주류 언어였으며, JavaScript와 Python 쪽 편향을 제거한 뒤에는 작업 속도가 크게 붙었음
      여러 인기 언어로 스크립트를 작성하되 환경 요구에 따라 모두 JVM에서 실행하는 JSR-223 프로젝트였음: https://en.wikipedia.org/wiki/Scripting_for_the_Java_Platform
    • 에이전트가 리팩터링을 못한다는 평가는 낡았으며, 지금은 매우 뛰어남
      이 채용 시장에서는 최신 최전선 모델 기반 코딩 에이전트를 사용하고 그 능력과 한계를 정확히 알아야 하며, 면접에서 반대 평가를 내놓으면 탈락 사유가 될 수 있음
  • 간결한 맥락은 토큰 소비만 줄이는 것이 아니라 추론을 개선하고, 한 맥락에 더 많은 계층을 넣어 지능적으로 다룰 수 있게 함
    좋은 추상화를 향한 리팩터링은 시험한 사례뿐 아니라 내삽·외삽된 사례에서도 맞을 가능성이 높은, 더 잘 일반화되는 소프트웨어를 만듦
    이를 뒷받침하는 정보이론 및 베이즈 수학이 있으며, 경제적·에너지 효율이 높은 소프트웨어가 더 정확해지는 것은 절묘한 우연처럼 보임
    핵심은 코드의 엔트로피를 줄이는 것

    • 세계와 우주의 어디에서든 엔트로피 감소는 무언가를 건설하는 일로 볼 수 있음
    • 인간 가독성을 목표에서 버리고 토큰 소비 감소만 목적 함수로 삼으면 어디에 도달할지 알기 어려움
      LLM은 이미 적은 맥락으로도 의미를 꽤 잘 추론함
  • 데이터가 제시된 점이 흥미로우며, 잘 분리된 코드에서 LLM이 크게 이득을 보지만 스스로 그런 코드를 만드는 능력은 그다지 뛰어나지 않다는 내 체감과 일치함
    대부분의 인간 개발자도 비슷할 것임

    • 별도로 엉성한 코드 제거 시간을 예산에 넣고 있으며 지금도 바로 옆 창에서 그 작업을 하고 있음
      전체적으로 AI의 이득은 크지만 정리 시간도 필요하고, 여전히 모든 줄을 읽어야 한다고 봄
      다른 팀의 진행을 막지 않으려고 일부 검토를 미뤘다가 나중에 평소보다 큰 기술 부채를 갚고 있는데, 먼저 병목을 푸는 편이 가치 있었음
      AI는 모든 의미에서 기술 부채를 더 쉽게 끌어다 쓰게 했으며, 안내만 잘하면 부채 해소도 꽤 잘함. 다만 결과는 사람마다 다름: https://news.ycombinator.com/item?id=49035455
    • 기본 상태에서는 같은 결과를 봤지만, 리팩터링 방향을 구체적으로 잡아주면 더 잘 분리된 코드를 만들 수 있었음
      잘 구성된 코드의 예시나 오픈소스 저장소를 통해 해야 할 것과 하지 말아야 할 것을 보여주면 큰 도움이 됨
  • 리팩터링의 경제적 이익 대부분은 토큰 절약보다 인간의 이해도 향상에서 나옴
    새벽 3시 장애 호출을 더 빨리 해결하고, 운영 환경에 들어가는 버그를 줄이며, 경쟁사보다 빠르게 출시할 수 있음
    무엇보다 시스템을 이해하면 책임과 소유권을 기꺼이 맡게 되어 문제가 생겼을 때 더 빨리 고치고 개선할 부분에도 적극적으로 뛰어들게 됨

  • 요점은 리팩터링이 토큰 소비를 줄인다는 것이며, 추상적으로 논하지 않고 효과를 정량화한 점은 좋음
    하지만 Fowler는 《Refactoring》에서 리팩터링의 필수 전제조건이 견고한 테스트라고 했고, AI와 무관하게 진짜 이점은 여기에 있다고 봄
    좋은 테스트는 인간이나 로봇이 만든 회귀를 막고, 양쪽 모두 읽을 수 있는 명세를 코드로 남김: https://www.oreilly.com/library/view/refactoring-improving-the/9780134757681/

    • 글이 martinfowler.com에 실렸지만 Martin이 쓴 것은 아니며, 저자는 Thoughtworks CTO인 Giles Edwards-Alexander로 표시돼 있음
    • 실제 핵심은 절약액이 겨우 수십 센트 수준이라는 것임
      Sonnet 5 가격을 MTok당 3달러로 계산하면 데이터 접근 계층을 건드리는 향후 변경에서 절약되는 금액은 39.7센트임
      OpenAI의 가격 인하와 개방형 모델, 장기적인 토큰 가격 하락을 고려하면 시간당 100달러쯤 하는 시니어 개발자가 리팩터링을 안내하는 비용과 맞지 않을 수 있음
  • 에이전트가 만든 코드는 에이전트만 읽고 이해할 수 있을 정도로 거대한 덩어리가 됐고, 이는 기능인지 버그인지 창발적 속성인지보다 현실 자체가 중요함
    AI 도구로 생성한 코드를 다루기 위해 다시 AI 도구에 종속되고 있음
    다만 인간도 이미 끔찍하게 큰 파일과 모노리포를 만들었고, LLM 덕분에 이를 편집하고 리팩터링하는 일이 비로소 감당 가능해짐
    코드베이스가 인간이 이해하기엔 너무 크고 엉망이 된 상황에서 LLM이 우리를 구할 수도 있으며, 개인적으로 거대 파일을 혐오하지만 Fowler식 정리 원칙은 더는 중요하지 않을 수도 있어 씁쓸함

    • 에이전트 코드가 에이전트만 이해할 수 있다는 말은 근본적으로 사실이 아니며, 그렇게 느낀다면 LLM 사용법이 잘못된 것임
    • 나쁜 코드는 원래부터 있었지만 AI는 나쁜 채용의 피해 범위를 1,000배 키우는 새로운 문제임
      평균적이거나 가끔 잘하는 직원조차 예전에는 회사 절차 때문에 못 하던 일을 번개처럼 실행하게 만들어 오히려 나쁜 직원으로 바꿀 수 있음
    • LLM이 100% 작성한 코드베이스도 읽거나 원하는 위치를 찾는 데 문제가 없었고, 직접 작성했을 때보다 어렵지 않았음
    • 에이전트가 만든 코드가 인간이 만든 최악의 코드보다 나쁜 경우는 본 적이 없음
      에이전트가 거대한 파일이나 함수를 만들면 그러지 말라고 지시하기만 해도 따름
  • 리팩터링은 건강한 개발팀을 보여주는 가장 좋은 징후 중 하나라고 봄
    리팩터링 자체의 이점도 있지만, 제품 책임자나 기능 작업표에서는 그 가치가 잘 보이지 않음
    팀이 전체 소프트웨어의 건강을 위해 리팩터링한다면 개발자가 좋은 소프트웨어를 위한 제안을 편하게 내고, 그 제안이 진지하게 받아들여진다는 뜻임
    소프트웨어 부패는 팀이 고품질 소프트웨어라는 비전을 실현할 동기나 권한이 없을 때 가장 심해지며, 팀이 탁월함에 대한 판단을 따를 수 있다면 대체로 좋은 신호임
    물론 Ruby, Node, Rust를 거쳐 다시 에이전트 친화적 기술로 전면 재작성하는 식의 과잉도 있지만, 기업 환경에서는 개선할 허가가 없다고 느끼는 팀이 훨씬 더 흔함