다음에 올 것을 만들어가는 기술에 대한 심층 기사.

JavaScript 프레임워크의 숨은 AI 비용

AI 코딩 에이전트는 JS 프레임워크마다 토큰 소모가 다릅니다. 왜 그런지, 그리고 내 스택의 AI 비용을 측정하는 법을 알아봅니다.

두 개의 컨베이어 벨트를 그린 아이소메트릭 일러스트. 한쪽은 깔끔한 소포를 부드럽게 옮기고, 다른 쪽은 커다란 상자로 꽉 막혀 있음
목적지는 같아도 배송비는 천차만별입니다. 어떤 프레임워크를 고르느냐에 따라 에이전트가 타는 컨베이어가 결정됩니다.

에이전트는 코드를 한 줄도 쓰기 전에 마이그레이션 가이드를 11분 동안 읽고 있었습니다. 여러분의 에이전트가 아니라, 지난주 동료가 SvelteKit 프로젝트에 같은 방식으로 던져 본 에이전트 이야기입니다. 여러분이 한 시간 전에 React 앱에 주었던 것과 같은 프롬프트였죠. 여러분의 작업은 약 8분, 400만 토큰에 끝났습니다. 상대는 17분, 거의 1,000만 토큰이 들었고, 그 차이의 상당 부분은 모델이 학습 때 본 적 없는 프레임워크 버전을 처음부터 다시 익히는 데 쓰인 것이었습니다. 이제 이 격차에는 이름이 붙었습니다. 바로 JavaScript 프레임워크의 AI 비용입니다. 그리고 업계에서 보기 드문 일, 즉 누군가 주장만 하지 않고 실제로 측정을 했기 때문에 이제 이 비용을 가늠할 실제 숫자가 생겼습니다.

Nolan Lawson은 수년간 프론트엔드의 통념을 실제 벤치마크로 바꿔 온 사람인데, 최근 아무도 귀찮아서 하지 않던 당연한 일을 했습니다. 검색, 필터링, 상세 페이지, PokéAPI 데이터가 들어가는 작지만 만만치 않은 포켓몬 앱을 정의하고, 코딩 에이전트에게 12가지 방식으로 만들게 한 것입니다. Astro, Next.js, Nuxt, SvelteKit, React Router, SolidStart, Qwik, Angular, TanStack Start, htmx를 얹은 Hono, Lit을 쓴 Gracile, 그리고 UI 프레임워크 없이 순수 Vite만 쓴 빌드까지 포함했습니다. 프레임워크마다 같은 프롬프트로 독립적인 실행을 5번씩 했고, 에이전트가 속일 수 없도록 모든 빌드를 적합성 테스트 스위트로 검증했으며, 비용, 시간, 토큰, Lighthouse 지표로 점수를 매겼습니다. 완벽한 실험은 아니고 Lawson 본인도 그렇게 말합니다. 그래도 대부분의 팀이 순전히 감으로 정하는 결정에 가격표를 붙이려는 첫 번째 정직한 시도라고 생각합니다.

벤치마크가 실제로 측정한 것

실험 설계는 의도적으로 중립적이었습니다. 에이전트에게는 스펙을 주고, 해당 프레임워크의 최신 버전을 쓰라고 하고, SSR이든 CSR이든 아키텍처는 알아서 고르게 했습니다. 프레임워크가 공식 MCP 서버, 에이전트 스킬, 플러그인을 제공하면 그것도 사용할 수 있게 해서, 학습 데이터에서 소외됐다는 불만이 나오지 않도록 했습니다. 적합성 테스트는 원시 DOM이 아니라 접근성 트리를 대상으로 돌렸는데, 한 후보가 shadow DOM으로 렌더링하기 때문에 이게 중요했습니다. 프레임워크당 5번씩 실행했고 결과는 중앙값으로 보고합니다. 다만 Angular는 두 번이나 테스트 가능한 앱을 만들어 내지 못해서, 일부 수치는 3번 실행한 결과입니다.

  • 빌드 비용은 앱당 중앙값 기준 약 $2.67에서 $4.97까지 나왔습니다. 가장 싼 프레임워크와 가장 비싼 프레임워크 사이에 대략 2배 차이가 난 셈입니다.
  • 토큰 소모도 같은 이야기를 더 시끄럽게 들려줬습니다. 가장 저렴한 스택은 약 400만 토큰, 가장 비싼 스택은 거의 1,000만 토큰이었습니다.
  • 걸린 시간도 비용과 거의 나란히 움직였습니다. 빠른 쪽은 약 8분, 느린 쪽은 17분이었습니다.
  • SvelteKit, Gracile+Lit, Angular는 일관되게 가장 비싼 빌드였고, Astro와 Hono+htmx 조합은 일관되게 저렴했습니다.
  • 놀랍게도 프레임워크를 쓰지 않은 순수 Vite 빌드가 실제 프레임워크 여러 개보다 성적이 나빴습니다. 기계에게도 구조가 없는 것보다 어느 정도 구조가 있는 편이 낫다는 뜻입니다.

빌드당 2달러면 별것 아닌 것 같습니다. 한 번의 빌드만 보면 실제로 별것 아닙니다. 하지만 에이전트 개발은 본질적으로 반복적입니다. 첫 번째 결과물을 그대로 받아들이는 사람은 없죠. 이 차이를 개발자 한 명이 일주일에 수십 번 돌리는 에이전트 세션으로 곱하고, 그걸 팀 전체, 1년 단위로 확장하면 스택에 붙은 2배짜리 토큰 배수는 실제 예산 항목이 됩니다. 더 중요한 점은 토큰이 돈보다 제가 더 중요하게 보는 것의 대리 지표라는 겁니다. 바로 모델이 여러분의 프레임워크로 올바른 코드를 내기까지 시행착오가 얼마나 필요한가입니다. 토큰이 많이 나온다는 건 대개 에이전트가 헷갈려서 문서를 다시 읽고 재시도하고 있다는 뜻입니다. 비용의 탈을 쓴 품질 신호인 셈이죠.

왜 어떤 프레임워크는 에이전트를 비싸게 만드는가

수년간 모델을 학습시키고 평가해 온 입장에서 보면, 결과는 겉보기만큼 신비롭지 않습니다. 거의 모든 차이는 세 가지 메커니즘으로 설명되고, 셋 중 어느 것도 전통적인 의미에서 어느 프레임워크가 ‘더 좋은가’와는 상관이 없습니다.

학습 데이터의 밀도가 운명을 정한다

에이전트 시대에 React의 가장 큰 장점은 프로그래밍 모델이 아니라, 10년 동안 쌓인 튜토리얼, GitHub 저장소, Stack Overflow 답변이 그 관용구를 모든 최상위 모델의 가중치 안에 압축해 넣었다는 점입니다. React 코드를 쓰는 에이전트는 대부분 기억을 떠올리는 것이고, Gracile 코드를 쓰는 에이전트는 대부분 새로 알아내는 것입니다. 실제로 벤치마크에서 프레임워크를 모르는 에이전트들은 저장소를 통째로 복제하거나 node_modules에서 컴파일된 소스를 뒤적였습니다. 사용자 코드가 생기기도 전에, 기초부터 다시 배우는 데 토큰을 태운 것입니다. 이는 개발자가 지식을 찾는 방식 전반을 바꾸고 있는 것과 같은 역학입니다. Stack Overflow가 저물면서 개발자 지식의 말뭉치가 어떻게 바뀌는지는 이전 글에서 따로 다뤘는데, 프레임워크 이야기는 그중에서도 아주 날카로운 특수 사례입니다. 인기 없는 도구는 커뮤니티만 부족한 게 아니라, 모델 자체에 존재감이 없는 겁니다.

API 변경은 반복되는 토큰 세금이다

SvelteKit이 부진했던 원인은 구체적이고 조금 웃기기까지 합니다. 에이전트가 매 실행마다 SvelteKit v3 마이그레이션 가이드를 읽었는데, 그 버전이 너무 새로워서 모델의 학습 데이터에 없었던 것입니다. 프레임워크가 내놓는 파괴적 변경은 모델이 외워 둔 패턴을 전부 무효화하고, 추론 시점에 문서에서 올바른 API를 매번 다시 도출하도록 강요합니다. 그 비용은 모든 세션마다, 모든 사용자가 토큰으로 치릅니다. 프레임워크들은 메이저 버전 변경을 마케팅 이벤트처럼 취급합니다. 하지만 에이전트 사용자 입장에서는 반복되는 할증료입니다. 3년 동안 API를 깨뜨리지 않은 지루한 프레임워크는 이 기준으로 보면 프리미엄 기능인 셈입니다.

장황함은 반복 루프 안에서 복리로 불어난다

Angular의 비용은 코드 양 그 자체와 맞아떨어지는 것처럼 보였습니다. 생성되는 줄이 많으면 출력 토큰이 늘고, 이후 수정할 때마다 다시 읽어야 할 토큰도 늘고, 에이전트가 걸려 넘어질 표면적도 넓어집니다. 이건 일반화할 수 있습니다. 출력이 장황한 도구, 시끄러운 빌드 로그, 느린 테스트 명령을 가진 스택은 매 반복마다 에이전트가 더 많은 텍스트를 헤쳐 나가게 만들고, 실패한 린트나 타입 체크 하나하나가 또 한 번의 비싼 왕복을 유발합니다. 실무자들도 어디서나 같은 패턴을 보고합니다. 에이전트 지출을 지배하는 건 생성 비용이 아니라 반복 비용이라는 겁니다. 빠르고 조용하고 엄격한 툴체인을 가진 프레임워크가 느슨한 프레임워크보다 운영 비용이 낮습니다. 엄격함이 에이전트의 실수를 다섯 번이 아니라 한 번의 사이클에서 잡아내기 때문입니다.

프레임워크가 내놓는 파괴적 변경 하나하나는 이제 누군가 토큰으로 치르는 세금입니다. 그리고 변경로그를 읽는 사람과 달리, 모델은 매 세션마다 그 세금을 냅니다.

에이전트 벤치마크의 주사위 문제

여기서 제 예전 ML 평가 습관이 발동합니다. 이 연구에서 가장 중요한 디테일은 오차 막대입니다. LLM 출력은 한 점이 아니라 분포입니다. React Router의 빌드 비용 중앙값은 Hono+htmx보다 약 1달러 비쌌습니다. 그런데 React Router의 가장 싼 실행 한 번이 Hono의 가장 비싼 실행보다 낮았습니다. 범위가 상당히 겹칩니다. SvelteKit 실행 결과는 약 $3.20에서 $6.80까지 널뛰었습니다. 때로는 에이전트가 그냥 낮게 굴러가서 곁길로 새고, 프레임워크와는 전혀 상관없는 이유로 토큰 수백만 개를 날려 버리기도 합니다.

어두운 도서관에서 책상 램프 아래 높이 쌓인 매뉴얼 더미를 읽고 있는 작은 로봇
학습 데이터에 프레임워크가 없으면 에이전트는 직접 조사를 하고, 그 모든 페이지의 비용은 여러분이 냅니다.

도구 사용 데이터도 같은 얘기를 합니다. 프레임워크들은 MCP 서버와 스킬 파일을 배포했고, 에이전트들은 그것을 때때로 사용했습니다. Nuxt의 MCP 서버는 다섯 번의 실행 동안 한 번도 건드려지지 않았습니다. TanStack Start의 스킬 파일은 다섯 번 중 두 번에서만 발견됐습니다. React Router의 스킬은 매번 사용됐습니다. 같은 프롬프트, 같은 하네스인데도 행동은 천차만별입니다. 이것이 도구의 확률적 본질입니다. 그래서 ‘프레임워크 X가 에이전트에게 훨씬 낫다, 나는 앱 전체를 다시 짰다’는 식의 트위터 스레드는, 오후 한나절 바이브 코딩 한 번에 기대서 잡음을 재고 있는 겁니다. 한 번의 실행은 일화일 뿐입니다. AI 비용이 아키텍처 결정에 영향을 주도록 허락할 생각이라면(저는 그래야 한다고 봅니다), 이 벤치마크를 포함해 무엇이든 믿기 전에 반복 실행의 중앙값을 요구하세요.

출력 품질은 결국 전부 무난하게 수렴한다

가장 놀라운 결과는 오히려 차이가 없었던 지표입니다. Lighthouse 성능, 접근성, 누적 레이아웃 이동 점수는 12개 스택 전체에서 거의 포화 상태였습니다. 거의 모든 곳에서 99점과 100점이었죠. 명확한 스펙과 적합성 테스트 스위트가 주어지면, 최신 에이전트는 사실상 어떤 프레임워크로든 능숙하고 접근 가능한 작은 앱을 만들어 냅니다. 콘텐츠 중심 사이트에서는 프레임워크가 결과물을 거의 구별하지 못할 만큼 품질의 바닥이 올라왔습니다.

차이가 실제로 있었던 품질 지표는 전송된 JavaScript 바이트였습니다. 아일랜드 방식의 Astro와 Hono+htmx 빌드는 0 KiB, 가장 무거운 SPA 결과물은 약 142 KiB까지 나왔습니다. Total Blocking Time은 전반적으로 사소한 수준이었고, LCP는 너무 노이즈가 커서 깊이 해석하기 어려웠습니다. 여기엔 솔직한 단서가 두 가지 붙습니다. 테스트 앱은 Figma보다 Wikipedia에 가까워서 멀티 페이지 아키텍처에 유리하고, Lighthouse 자체가 구조적으로 SPA에 불리합니다. 그럼에도 바닐라 JavaScript 결과는 잠깐 멈춰 볼 만합니다. 프레임워크 없이 순수 Vite를 쓰라고 지시받은 에이전트가 실제 프레임워크 여러 개보다 나쁜 점수를 냈고, 어떤 빌드보다 높은 레이아웃 이동을 기록했습니다. 프레임워크는 관례를 인코딩하고, 에이전트는 관례에 강하게 기댑니다. 모델에게 잘 닦인 홈을 주면 그 안에 머물고, 빈 캔버스를 주면 즉흥적으로 만들며, 그게 늘 잘되지는 않습니다.

이 벤치마크가 말해 줄 수 없는 것

포켓몬 데모를 근거로 실제 프로덕션 앱을 다시 짜기 전에, 범위부터 솔직하게 짚어 봅시다. 이것은 작고 대부분 콘텐츠 중심인 애플리케이션이며, 횡단 상태가 거의 없고, 현지화도 없고, 복잡한 폼도 없고, 5년 동안 유지보수할 사람도 없는 실험입니다. 이건 분명한 한계이고, 제가 이 블로그에서 계속 맴도는 함정과 같습니다. AI 벤치마크는 실제 업무의 대부분을 체계적으로 놓칩니다. 그린필드 장난감 앱에서 에이전트에게 좋은 프레임워크를 만드는 특성들, 즉 익숙함, 단순함, 정적 구조는, 엉망인 제품의 18개월 차에 중요한 특성들과 같지 않습니다.

토론에서 프레임워크 회의론자들이 짚은 더 깊은 지점도 있습니다. 프레임워크의 역사적 가치 대부분은 무엇을 할 수 있게 해 주느냐가 아니라, 무엇을 금지하느냐에 있었습니다. 자바가 기업 개발을 장악한 것은, 일부분 수많은 프로그래머가 비슷하게 생긴 코드를 쓰도록 강제했기 때문입니다. 프레임워크는 들어오고, 떠나고, 서로를 오해하는 사람들로 이루어진 팀을 위한 제약 시스템입니다. 에이전트에게는 지루함이나 이력서 주도 개발을 막는 가드레일이 필요하지 않습니다. 명확한 스펙과 테스트 스위트만 있으면 됩니다. 한 실무자는 htmx에서 정확히 이 역전을 경험했다고 보고했습니다. 에이전트는 단순한 페이지는 거뜬히 해냈지만, 복잡한 상태가 있는 폼에서 허우적댔고, 상태를 잃어버리고 토글을 망가뜨렸습니다. React였다면 한 번에 해냈을 문제들이었죠. 충분한 테스트가 생기고 나서야 정직하게 유지되었습니다. 에이전트에게 중요한 제약은 프레임워크가 아닙니다. 적합성 테스트 스위트입니다.

그리고 맞습니다, 가장 싼 빌드가 가장 싼 코드베이스는 아닙니다. 팀이 깊이 이해하고 수년간 유지보수할 수 있는 스택을 위해 에이전트 세션당 2달러를 더 쓰는 것은 명백히 옳은 선택입니다. 하지만 이 주장에는 숫자가 필요하다는 점에 주목하세요. AI 비용을 측정하는 핵심은 승자를 뽑는 게 아니라, ‘이 프레임워크가 에이전트에게 더 좋다’는 말을 채용 풀, 생태계 성숙도, 번들 크기와 저울질할 수 있는 수치로 바꾸는 데 있습니다. 감은 DX 논쟁에서 이미 졌습니다. 에이전트 논쟁에서까지 기본값으로 이기게 해서는 안 됩니다.

내 스택의 AI 비용을 측정하는 법

누군가의 벤치마크, 심지어 이 벤치마크를 근거로 여러분의 코드베이스를 추정하지 마세요. 여러분의 저장소, 여러분의 스펙, 여러분이 고른 모델이 각자 고유한 분포를 만들어 냅니다. 좋은 소식은 AI 비용을 측정하는 일이 정말 쉽다는 겁니다. 코딩 에이전트가 필요한 정보를 이미 전부 보고하기 때문입니다. 계측을 하기 전에 루프, 컨텍스트, 권한이 어떻게 맞물리는지 이해하고 싶다면 에이전트형 코딩 CLI가 실제로 어떻게 동작하는지를 다룬 글이 좋은 출발점입니다. 그다음 아래를 해 보세요.

  1. 실제 업무를 대표하는 수직 슬라이스를 고르세요. 랜딩 페이지가 아니라 데이터 계층, 상태 관리, UI를 모두 건드리는 기능이어야 합니다.
  2. 적합성 테스트를 먼저 작성하세요. 테스트는 품질 게이트이자 속임수 방지 장치입니다. 테스트가 없는 에이전트는 일찍 승리를 선언해 버립니다.
  3. 후보 스택이나 설정마다 같은 프롬프트를 최소 5번 실행하세요. 단일 실행이 아니라 중앙값과 범위를 보고하세요.
  4. 총 토큰(캐시 읽기, 입력, 출력으로 나눠서), 실제 소요 시간, 비용, 도구 호출 수와 재시도 루프 수를 기록하세요.
  5. 문서 읽기에 얼마나 많은 토큰이 쓰였는지 추적하세요. 마이그레이션 가이드, 변경로그, node_modules 뒤지기가 여기 해당합니다. 이것이 학습 데이터 결핍 세금을 직접 측정한 값입니다.
  6. 주요 프레임워크 업그레이드 후 벤치마크를 다시 돌리세요. API가 변하고 학습 컷오프가 이동함에 따라 AI 비용은 계속 달라집니다.

하네스 자체는 하루 오후면 스크립트로 만들 수 있습니다. 제가 쓴 골격은 다음과 같습니다. CLI 플래그의 세부 사항은 에이전트마다 다르지만, 모양은 어디서나 같습니다.

import json
import statistics
import subprocess
FRAMEWORKS = ["astro", "react-router", "sveltekit"]
RUNS = 5
SPEC = open("spec.md").read()
def build_once(framework: str) -> dict:
"""One full agent session: build the app, return usage stats."""
result = subprocess.run(
[
"agent-cli", "run",
"--prompt", SPEC,
"--context", f"Build this with the latest {framework}.",
"--output-format", "json",
],
capture_output=True,
text=True,
check=True,
)
return json.loads(result.stdout)
for framework in FRAMEWORKS:
runs = [build_once(framework) for _ in range(RUNS)]
costs = [r["cost_usd"] for r in runs]
tokens = [r["tokens_total"] for r in runs]
print(
f"{framework}: "
f"median ${statistics.median(costs):.2f} "
f"(range ${min(costs):.2f}-${max(costs):.2f}), "
f"median {statistics.median(tokens) / 1e6:.1f}M tokens"
)

토큰 총합만큼 재시도 횟수도 면밀히 보세요. 제 경험상 ‘통과한 테스트 하나당 토큰’이 가장 정직한 지표입니다. 비용, 혼란, 정확성을 하나의 숫자로 압축하고, 실제로 아픈 실패 모드, 즉 에이전트가 컴파일 에러 루프를 다섯 번씩 헤매다가 겨우 통과하는 상황에 불이익을 줍니다. 에이전트가 첫 번째나 두 번째 시도에 깔끔하게 통과하는 프레임워크는, 매번 계속 수정이 필요한 이름만 ‘더 싼’ 프레임워크를 항상 이깁니다.

나무 책상 위에서 금화와 빛나는 반투명 큐브를 저울에 올려 무게를 재는 황동 저울
토큰은 점점 아키텍처 비용의 단위가 되고 있습니다. 결정 과정에서 다른 모든 것과 함께 저울질해야 합니다.

실용적인 결론

그렇다면 에이전트가 더 싸다고 하니 Angular 앱을 Astro로 다시 짜야 할까요? 아닙니다. 달러 차이는 작고, 편차는 크며, 테스트 앱은 장난감이고, 마이그레이션에 드는 에이전트 토큰이 10년 동안 아끼는 것보다 많을 겁니다. ‘에이전트를 위해’ 프레임워크 마이그레이션을 파는 사람은, 업계가 늘 해 온 감에 의존한 추론을 새 명분만 붙여서 똑같이 하고 있는 겁니다.

하지만 AI 비용은 이제 채용 풀, 생태계 깊이, 번들 크기와 나란히 의사결정 테이블에 앉을 자격이 있습니다. 그린필드 프로젝트에서 증거는 한 방향을 가리킵니다. 학습 데이터 표현이 풍부하고, API 변화가 느리고, 엄격하고 조용한 툴체인을 갖추고, 모델이 만 번은 본 관례를 가진 스택을 고르세요. 지루한 기술은 언제나 실용적인 선택이었습니다. 에이전트는 지루함을 측정 가능하게 만들었을 뿐입니다. 프레임워크 버전은 고정하세요. 모델이 따라잡을 때까지 모든 업그레이드는 추론 시점의 세금이기 때문입니다. 그리고 어떤 프레임워크를 고르든 적합성 테스트에 투자하세요. 테스트는 모든 에이전트를 더 싸게 만들고, 허우적댈 때 정직하게 붙잡아 주며, 지금 쓰는 모델이 구식이 된 뒤에도 오래 값을 합니다. 프레임워크는 계속 바뀔 겁니다. 살아남는 것은 테스트와 측정하는 습관입니다.