-
AI는 왜 있는 함수를 두고 새로 짜는가 — 재사용의 병목은 설계가 아니라 '모델의 기억'이다IT 2026. 8. 3. 21:00
코딩 에이전트에게 기능 하나를 맡겼더니, 저장소에 이미 있는 날짜 파싱 유틸을 두고 똑같은 일을 하는 함수를 새로 짜서 넣었다. 처음엔 "DRY(Don't Repeat Yourself, 같은 로직을 두 번 쓰지 말라는 원칙)를 모르는군" 하고 웃어넘겼다. 그런데 이게 나만의 경험이 아니었다.
2026년 4월 MSR(Mining Software Repositories) 학회에 발표된 연구가 파이썬 저장소의 풀 리퀘스트 3,858건을 분석했다. 에이전트가 만든 코드는 사람이 만든 코드보다 중복도가 1.87배 높았다(p<0.001). 더 결정적인 숫자는 다른 연구에 있었다. 리팩터링의 동기를 분류해 보니, "중복 제거"를 이유로 코드를 정리하는 비율이 사람은 13.7%인데 에이전트는 1.1%였다. 사람은 열 번에 한 번 이상 중복을 지우러 들어가고, 에이전트는 백 번에 한 번 들어간다.
여기서 자연스럽게 나오는 해석이 있다. "AI가 코드를 공짜로 뽑아주니 재사용이라는 규율이 무너진다"는 것이다. 그럴듯하지만, 이 해석이 원인과 증상을 뒤바꿨다고 본다. 에이전트는 DRY를 안 지키는 게 아니다. 당신의 함수가 존재한다는 사실을 모르는 것이다.
재사용은 원래 코드의 문제가 아니었다
재사용이 성립하려면 소비자가 두 가지를 알아야 한다. 첫째, 그게 존재한다는 사실을 알아야 한다. 둘째, 어떻게 쓰는지를 알아야 한다. 지금까지 이 "앎"은 사람이 해결했다. 문서를 읽고, 동료에게 묻고, 저장소를 grep하고, 스택오버플로를 뒤졌다. 코드 텍스트는 그 앎이 끝난 뒤에 나오는 결과물이었을 뿐, 재사용의 본체가 아니었다.
이제 코드를 쓰는 소비자가 모델이다. 그리고 모델이 아는 것은 딱 두 곳에 있다 — 학습된 가중치 안에 있거나, 추론 시점의 컨텍스트(모델이 답을 만들 때 실제로 읽는 입력 구간) 안에 있거나, 둘 중 하나다. 이 둘 바깥에 있는 코드는, 모델 입장에서는 존재하지 않는 코드다. 재사용의 병목이 설계에서 기억으로 옮겨간 것이다.
다이어그램 설명. 에이전트가 코드를 만들 때 실제로 갈라지는 분기는 "이걸 재사용할까, 새로 짤까"가 아니다. "모델의 기억 안에 이게 있는가"다. 있으면 재사용은 오히려 심화되고, 없으면 조용히 재구현된다. 여기서 중요한 함정은, 이 분기가 코드의 품질이나 설계의 좋고 나쁨과 아무 상관이 없다는 점이다. 아주 잘 짜인 자체 유틸이라도 모델의 기억 밖에 있으면 그냥 없는 것으로 취급된다. 반대로 오래되고 낡은 라이브러리라도 학습 데이터에 많이 있으면 계속 불려 나온다. 아래 두 절에서 이 두 갈래를 하나씩 본다.
기억 안에 있으면, 재사용은 오히려 심해진다
"AI가 재사용을 죽인다"는 통념과 정반대되는 데이터가 있다. 킹스칼리지런던·UCL·GitHub Next 연구진이 여덟 개 모델(GPT-4o, Claude 3.5 Sonnet, Llama, Qwen, DeepSeek 등)에게 525개 과제를 각각 100번씩 풀게 하고, 어떤 라이브러리를 골라 쓰는지 셌다. 결과는 놀랍도록 좁았다.
PyPI(파이썬 패키지 저장소)에는 이 과제들에 쓸 만한 패키지가 7,000개 넘게 있다. 그런데 모델들이 실제로 손을 뻗은 라이브러리는 32~39종뿐이었다. 상위 3개(NumPy·pandas·Matplotlib)는 모든 모델에서 동일했고, 4위와의 격차가 22%포인트 이상 벌어졌다. 개별 숫자는 더 노골적이다.
웹 프레임워크에서 Flask(2010년 출시)가 88%, FastAPI(2018년 출시)가 9%였다. FastAPI가 깃허브 스타 성장 속도로는 Flask의 3배인데도 그렇다. 데이터 처리에서는 pandas가 58%를 가져갔고, 같은 일을 훨씬 빠르게 하는 Polars는 0% — 단 한 번도 선택받지 못했다. 시각화는 Matplotlib 57%, Plotly는 세 모델이 문제 하나에서 쓴 게 전부다. 고성능이 명시적으로 요구된 시나리오에서도 58%는 파이썬을 골랐고, Rust는 다섯 번의 기회에서 단 한 번도 등장하지 않았다. 아예 필요 없는데 NumPy를 끌어오는 경우도 최대 48%였다.
이건 재사용이 무너진 그림이 아니다. 재사용이 소수 승자에게 극단적으로 집중되는 그림이다. AI는 인기 있는 라이브러리를 더 인기 있게 만든다. 학습 데이터에 많이 등장한 것이 더 많이 생성되고, 더 많이 생성된 것이 다시 학습 데이터가 된다. 연구진의 표현대로 "코딩 생태계를 균질화하고 오픈소스의 발견 가능성을 훼손"하는 되먹임이다. 신생 라이브러리 입장에서는, 아무리 좋아도 학습 데이터에 축적될 시간을 벌지 못하면 영영 선택받지 못한다.
기억 밖에 있으면, 조용히 재구현된다
반대편 갈래가 우리가 실제로 아파하는 쪽이다. 직접 만든 유틸, 갓 나온 라이브러리, 모델의 학습 컷오프 이후에 바뀐 API — 이것들은 모델의 기억 밖에 있다.
그 결과를 가장 선명하게 보여주는 게 사용 중단(deprecated) API 연구다. 일곱 개 모델에 28,125개의 코드 완성 과제를 주고 "이미 폐기된 옛 API를 얼마나 쓰는지" 쟀더니 25~38%였다. 그런데 진짜 발견은 그 다음이었다. 주변 코드가 이미 낡아 있으면 폐기 API 사용률이 70~90%로 뛰고, 주변 코드가 최신이면 9~18%로 떨어졌다. 모델은 자기가 본 것을 충실히 재생산한다. 레거시 코드베이스에 에이전트를 풀어놓으면, 그 레거시를 성실하게 이어 쓴다.
더 까다로운 건 이 중복이 눈에 띄지 않는다는 점이다. 앞서 언급한 MSR 연구는 에이전트가 만드는 중복이 주로 "Type-4 클론" — 텍스트는 서로 다른데 의미는 같은 코드 — 라고 짚었다. 기존 클론 탐지 도구는 텍스트 유사도를 보므로 이걸 못 잡는다. CI(지속적 통합, 커밋마다 자동으로 테스트·검사를 돌리는 파이프라인)는 조용히 통과한다. 같은 연구에서 리뷰어들은 오히려 AI가 낸 PR에 더 우호적인 반응을 보였다. 리뷰어는 "이게 돌아가는가"를 보지 "이게 이미 있는가"를 보지 않기 때문이다.
여기서 자주 인용되는 GitClear의 수치 — 복사·붙여넣기가 리팩터링을 앞질렀다, 새 코드가 기존 함수를 부르는 빈도가 35% 떨어졌다 — 도 같은 방향을 가리킨다. 다만 이건 조심해서 인용해야 한다. 단일 벤더의 자체 지표이고, 독립 재현된 적이 없으며, AI가 쓴 커밋과 사람이 쓴 커밋을 분리하지 않은 시계열 상관이다.
그래서 라이브러리들이 컨텍스트에 자리를 사기 시작했다
이 진단이 맞다면, 처방은 자명하다. 가중치에 못 들어간 코드는 컨텍스트에 자리를 사야 한다. 그리고 2025~2026년에 벌어진 일이 정확히 그것이었다 — 다만 아무도 그걸 이 이름으로 부르지 않았을 뿐이다.
다이어그램 설명. 라이브러리가 에이전트에게 선택받는 경로는 두 개뿐이다. "모델 가중치에 들어간다"는 경로는 학습 데이터에 충분히 누적돼야 열리므로, 신생 라이브러리나 직접 만든 코드에는 원천적으로 닫혀 있다. 남는 게 "추론 시점 컨텍스트에 들어간다"는 경로다. 이게 지금 라이브러리 벤더들이 실제로 하고 있는 일이다. 다만 이 경로에는 값이 붙는다 — 컨텍스트는 유한하고, 뒤에서 볼 안정성 문제가 아직 풀리지 않았다. 어쨌든 라이브러리가 자기 사용법을 소비자의 작업 기억 속으로 밀어 넣으려 한다.
가장 노골적인 사례가 Laravel이다. PHP 진영의 대표 웹 프레임워크인데, 2025년 8월 Laravel Boost를 내놓으면서 발표문에 이렇게 썼다. "대형 언어 모델은 PHP를 꽤 잘한다. 학습 데이터가 많으니까. 하지만 그것으로는 충분하지 않다. 맥락이 없으면 모델은 없는 API를 지어내고, 프레임워크 관용구를 오용하고, 테스트를 건너뛴다." 그리고 실제로 무엇을 만들었냐면 — 자기네 문서 17,000개 항목을 버전별로 쪼개서 벡터화한 검색 API를 Composer 패키지로 배포했다. 프레임워크가 자기 문서에 대한 검색 인프라를 구축해서 배포한 것이다. 결정적인 신호는 홈페이지 태그라인 변경이다. "The clean stack for Artisans and agents" — 프레임워크가 비인간을 사용자 계층으로 명시했다.
Stripe도 같은 곳에 도착했다. 결제 회사가 내놓은 에이전트 연결 도구 목록을 보면, 절반이 결제가 아니다.
search_stripe_documentation(문서 검색),stripe_api_search(API 메서드 검색),stripe_implementation_planner(연동 설계 안내). 결제 처리 도구가 아니라 연동 노하우를 호출 가능한 엔드포인트로 파는 것이다. 그리고 Context7이라는 서비스는 아예 제3자 입장에서 남의 라이브러리 문서를 대신 버전별로 벡터화해 준다. 이런 회사가 존재한다는 사실 자체가 충족되지 않은 수요의 증거다.이게 감(感)에 기댄 얘기가 아니라는 하드 데이터도 하나 있다. 저장소 루트에 두는 에이전트 지침 파일(AGENTS.md)의 효과를 대조 실험으로 잰 연구가 있다. 저장소 10개, PR 124건을 병합 직전 상태로 복원해 놓고, 같은 에이전트를 지침 파일이 있을 때와 없을 때로 나눠 돌렸다. 작업 완료 시간 중앙값이 98.6초에서 70.3초로 28.6% 줄었고, 출력 토큰은 16.6% 줄었다. 파일 하나로 이만큼 나온다.
그리고 이 지침 파일들이 담는 내용을 자세히 보면, 사람용 문서와 장르가 다르다.
# AGENTS.md — 에이전트가 이 저장소를 열 때 가장 먼저 읽는 파일 ## 이미 있는 것 (새로 만들지 말 것) # 서술이 아니라 "재구현 금지" 목록이다. 에이전트가 grep으로 못 찾을 것을 미리 박아 둔다. - 날짜 파싱: utils/dates.py 의 parse_kst() — 타임존 처리까지 포함돼 있다 - HTTP 재시도: utils/http.py 의 request_with_backoff() — 지수 백오프 내장 ## 이 저장소의 규범 (행동 제약) # 사람에게는 굳이 안 적는 것들. 사람은 취향과 관성이 있어서 알아서 하지만, 모델은 그게 없다. - 새 함수를 추가하기 전에 utils/ 아래를 먼저 검색한다 - 테스트 없이 코드를 추가하지 않는다 (pytest, tests/ 하위)코드 설명. 이 파일이 하는 일은 API를 설명하는 게 아니라 행동을 제약하는 것이다. 사람용 레퍼런스 문서는 "이 함수는 이런 인자를 받습니다"를 서술하지만, 이 파일은 "이미 있으니 새로 만들지 마라", "먼저 검색하고 나서 짜라"라고 명령한다. 사람에게는 이런 걸 적어 줄 필요가 없었다 — 사람에겐 취향과 관성이 있어서, 팀 관례를 한 번 겪으면 알아서 따른다. 모델에겐 그게 없다. 그래서 이 시기에 가장 새로운 문서 장르는 레퍼런스가 아니라 규범이었고, Laravel이 "AI 가이드라인"이라는 이름으로 프레임워크 차원에서 배포하기 시작한 것도 정확히 이 종류다.
그런데 그 자리는 아직 안전하지 않다
여기까지만 쓰면 깔끔한 해피엔딩인데, 정직하게 말하면 이 처방에는 두 개의 큰 구멍이 있다.
첫째, 그냥 파일을 발행하는 방식은 이미 실패했다. 2024년 9월에 제안된 llms.txt는 "사이트 루트에 모델이 읽기 좋은 요약 파일을 두자"는 발상이었다. Ahrefs가 도메인 137,210개의 서버 로그를 분석한 결과, 발행된 llms.txt 파일의 97%가 한 달 동안 단 한 번도 요청되지 않았다. 존재하지 않는 llms.txt에 대한 요청은 0건이었다 — 모델들은 애초에 그 파일을 찾으러 오지 않는다. 구글은 공식 문서에 "AI 기능에 노출되기 위해 새로운 기계가독 파일을 만들 필요가 없다"고 못 박았다. 살아남은 건 수동적 발행이 아니라, 앞서 본 Laravel·Stripe·Context7 형태의 추론 시점 능동 검색이다. 이기는 산출물은 파일이 아니라 질의 엔드포인트였다.
둘째, 그 자리는 공짜가 아니라 경매장이다. Thoughtworks는 2026년 4월 기술 레이더에서 "일단 MCP부터 붙이고 보는" 관행을 보류(Hold) 등급에 올렸다. 이유는 "추상화 세금" — 에이전트와 API 사이에 프로토콜 계층이 낄 때마다 충실도가 깎이고, 그 손실이 누적된다는 것이다. Anthropic 자신도 도구 정의만으로 컨텍스트의 절반가량(약 13만 토큰)이 날아갈 수 있다고 인정하고, 도구 정의를 컨텍스트에 넣는 대신 모델이 코드를 짜서 호출하게 하는 방식으로 15만 토큰을 2천 토큰으로 줄였다. 컨텍스트는 무한한 선반이 아니다. 자리를 사려는 라이브러리가 늘어날수록, 그 자리의 값은 올라간다.
정리 — 재사용은 설계 문제에서 검색 문제가 됐다
정리하면 이렇다. AI가 재사용을 죽인 게 아니다. 재사용이 성립하기 위한 조건 — 소비자가 그게 있다는 걸 아는가 — 을 판정하는 주체가 사람에서 모델로 바뀌었고, 모델의 앎은 가중치와 컨텍스트라는 두 개의 좁은 문으로만 들어온다. 그 문 안에 있는 것은 전보다 더 심하게 재사용되고(Flask 88%, Polars 0%), 문 밖에 있는 것은 조용히 재구현된다(중복 1.87배, 중복 제거 리팩터링 1.1%).
그래서 아키텍트가 던져야 할 질문이 바뀐다. "이 로직을 어떤 공용 모듈로 빼낼까"가 아니라 "이 모듈이 있다는 걸 에이전트가 어떻게 알게 할까"다. 좋은 추상화를 만드는 일과, 그 추상화를 모델이 발견하게 만드는 일은 이제 별개의 작업이고, 후자를 안 하면 전자는 없는 셈 친다.
당장 내 저장소에 적용할 수 있는 것도 여기서 나온다. 잘 나눠 둔 유틸 모듈이 있다면, 그 존재를 지침 파일에 재구현 금지 목록으로 적어 두는 것만으로 28% 빨라진다는 실측이 있다. 코드를 잘 짜는 것과 별개로, 그 코드가 모델의 시야에 들어오게 만드는 일 — 그게 지금의 재사용이다.
참고한 공개 자료:
- More Code, Less Reuse: AI 생성 PR의 코드 품질과 리뷰어 반응 — MSR '26, arXiv (https://arxiv.org/abs/2601.21276)
- Agentic Refactoring: 에이전트와 사람의 리팩터링 동기 비교 — arXiv (https://arxiv.org/abs/2511.04824)
- A Study of LLMs' Preferences for Libraries and Programming Languages — King's College London·UCL·GitHub Next, arXiv (https://arxiv.org/abs/2503.17181)
- How and Why LLMs Use Deprecated APIs in Code Completion — arXiv (https://arxiv.org/abs/2406.09834)
- Announcing Laravel Boost — Laravel 공식 블로그 (https://laravel.com/blog/announcing-laravel-boost)
- Stripe MCP 서버의 도구 목록 — Stripe 공식 문서 (https://docs.stripe.com/mcp)
- Context7 — 버전별 라이브러리 문서 주입 (https://github.com/upstash/context7)
- AGENTS.md 표준 및 도입 현황 (https://agents.md/)
- llms.txt 도입 실태 — 137,210개 도메인 서버 로그 분석, Ahrefs (https://ahrefs.com/blog/llmstxt-study/)
- Google 검색 AI 기능 문서 — 별도 기계가독 파일 불필요 (https://developers.google.com/search/docs/appearance/ai-features)
- Skills vs Dynamic MCP Loadouts — Armin Ronacher (https://lucumr.pocoo.org/2025/12/13/skills-vs-mcp/)
- MCP by default — Hold 등급, Thoughtworks Technology Radar Vol.34 (https://www.thoughtworks.com/radar/techniques/mcp-by-default)
- Code execution with MCP — Anthropic Engineering (https://www.anthropic.com/engineering/code-execution-with-mcp)
- Self-Admitted GenAI Usage in Open-Source Software — GitClear churn 주장 반박, arXiv (https://arxiv.org/abs/2507.10422)
이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.
'IT' 카테고리의 다른 글
AI가 나를 19% 느리게 만들었는데, 나는 20% 빨라졌다고 믿었다 — METR RCT가 흔든 생산성 통념 (0) 2026.08.04 MCP 샌드박싱의 사정거리 — 무엇이 걸리고 무엇이 정문으로 나가는가 (1) 2026.08.04 The S in MCP stands for Security — 로컬 MCP 서버에는 인증이 없다 (0) 2026.08.04 통합에서 발견으로 — AI 시대 '진입 장벽 낮추기'의 진짜 정체 (0) 2026.08.03 AI가 빨리 짜준 코드의 청구서는 6개월 뒤에 온다 — 30만 커밋이 말하는 기술부채 (0) 2026.08.03 표준이 둘로 갈렸다가 하나로 — ACP가 A2A에 합류한 이야기 (0) 2026.08.02 에이전트 호출의 생명주기 — 왜 그냥 API 호출로는 안 되나 (0) 2026.08.02 에이전트는 서로를 어떻게 찾는가 — 발견, 그리고 에이전트의 '명함' (0) 2026.08.02 AI 에이전트의 두 개의 축 — 도구를 붙이는 일과 동료를 부르는 일은 다르다 (0) 2026.08.02 서브에이전트 출력 압축 — 토큰 절약의 잊힌 세 번째 축, 메인 컨텍스트 예산 (0) 2026.08.01