← 목록으로

AI Coding Agent 시대, 라이브러리는 어떻게 스스로를 설명해야 할까

TL;DR — 이제 라이브러리의 독자는 사람만이 아닙니다. AI 코딩 에이전트가 직접 코드를 짜는 시대에는, 에이전트도 라이브러리의 실제 사용자입니다. 그런데 막상 시켜보면 에이전트는 문법보다 맥락에서 더 자주 흔들려요. README는 사람을 위한 설명이고, 에이전트에게는 “그래서 지금 어떻게 써야 하는데?”에 답해주는 실행 지식(Skill)이 따로 필요합니다. TanStack Intent 는 그 Skill을 npm 패키지와 함께 배포·버저닝·검증하게 해주는 CLI고요. 이 글은 같은 라이브러리의 intent 버전plain 버전을 만들어 직접 비교해 본 기록입니다.

에이전트한테 라이브러리를 맡겨보면 생기는 일

작은 라이브러리를 하나 만들고, 에이전트한테 “이거 써서 기능 좀 붙여줘”라고 시켜본 적 있으신가요? 해보면 좀 묘합니다. API 자체는 귀신같이 잘 찾아요. 그런데 그다음이 문제입니다.

provider를 엉뚱한 데 두거나, 이미 권장하지 않는 옛날 경로를 고르거나, 초기화 순서를 슬쩍 틀립니다. API를 몰라서가 아니에요. “이 라이브러리를 어떻게 쓰는 게 맞는지”를 몰라서 생기는 실수입니다.

라이브러리를 만들 때 이 간극이 계속 신경 쓰였습니다. 분명 문서에 다 적어뒀는데 왜 자꾸 틀릴까. 그러다 TanStack Intent 라는 도구를 알게 됐고, 직접 패키지에 붙여서 안 붙인 버전과 나란히 비교해봤습니다. 결론부터 말하면, 흥미로웠습니다. 다만 마냥 장밋빛은 아니었고요.

예전엔 사람한테만 설명하면 됐는데

생각해보면 예전 라이브러리의 일은 단순했습니다. 사람 개발자한테만 자기를 설명하면 됐거든요. README 잘 쓰고, 문서 정리하고, 예제 몇 개 던져주면 끝이었습니다.

그런데 요즘은 점점 더 많은 코드가 AI 에이전트의 손을 거칩니다. 이 친구들은 문서를 읽는 데서 그치지 않고 실제로 코드를 만들고, 고치고, 연결해요. 그러니까 에이전트는 더 이상 멀찍이서 문서만 보는 독자가 아니라, 라이브러리를 직접 쓰는 사용자가 된 거죠.

여기서부터 미묘해집니다. 에이전트는 코드도 문서도 읽을 수 있지만, 그렇다고 매번 올바르게 쓰는 건 아니거든요. 사람은 README를 읽고, 예제 몇 개를 비교해보고, “아 보통 이렇게 쓰는구나”를 경험과 버무려 추론합니다. 반면 에이전트는 짧은 순간에 다음 행동을 정해야 하고, 그 와중에 라이브러리가 의도한 사용 방식까지 안정적으로 잡아내진 못합니다.

사람이 읽기 좋게 설명하는 것과, 에이전트가 바로 행동으로 옮길 수 있게 알려주는 것. 이 둘은 생각보다 많이 다릅니다.

에이전트는 문법보다 맥락에서 흔들린다

에이전트가 실수하는 장면을 가만히 보면, 의외로 문법을 몰라서 틀리는 경우는 별로 없습니다. 대부분은 맥락을 못 잡아서 흔들려요. 이를테면 이런 식입니다.

  • 필요한 API는 찾았는데, 초기화 순서를 거꾸로 합니다
  • provider랑 hook을 어떻게 연결해야 하는지 규칙을 놓칩니다
  • 이미 deprecated된 경로를 멀쩡하게 골라옵니다
  • SSR이나 hydration 같은 환경 제약을 그냥 지나칩니다
  • 문서·예제·이슈에 흩어진 암묵지를 하나의 실행 규칙으로 못 엮습니다

이게 에이전트가 멍청해서 그런 거냐 하면, 그건 아닙니다. 라이브러리의 실전 사용 규칙이 어디에도 또렷하게 적혀 있지 않으니 흔들리는 거예요. 사람은 적혀 있지 않은 부분까지 알아서 채워 읽지만, 에이전트한테 그걸 기대하긴 아직 이릅니다.

README는 사람 거, Skill은 에이전트 거

오해를 막자면, README가 필요 없다는 얘기가 절대 아닙니다. 배경·철학·개념·큰 그림을 전하는 데는 README만 한 게 없어요. 개념을 넓게 펼치고, 선택지를 비교하고, 처음 온 사람을 안내하는 온보딩 문서로는 최고입니다.

다만 README는 본질적으로 사람한테 읽어주는 글입니다. 에이전트는 설명이 풍부한 것보다 “지금 뭘 해야 하는지”가 또렷한 게 더 급해요. 가령 이런 걸 직접적으로 알고 싶어 합니다.

  • 이 상황이면 어떤 순서로 설정해야 하지?
  • 어떤 패턴은 피해야 하지?
  • 이 환경에선 어떤 경로를 써야 하지?
  • 지금 권장되는 방식이 뭐지?

이 지점에서 Skill이 등장합니다. 설명보다 “어떻게 행동해야 하는가”를 더 곧장 전달하는 층이에요. 그래서 README와 Skill은 경쟁 상대가 아닙니다. 역할이 다를 뿐이죠.

READMESkill
주 독자사람 개발자코딩 에이전트
답하는 질문”무엇이 있나” / “왜 그런가""그래서 지금 어떻게 하나”
형식설명 중심실행 지침 중심
강점개념·철학·온보딩권장/금지 경로, 순서, 환경별 분기

그래서 TanStack Intent가 뭐냐면

TanStack Intent 는 라이브러리 저자가 이런 Skill을 코드와 함께 만들고, 검증하고, 배포할 수 있게 해주는 CLI입니다. 공식 설명으로는 “Agent Skills를 패키지 아티팩트와 함께 배포하고 소비하게 해주는 CLI”고요.

포인트는 Skill을 어딘가 따로 떠다니는 문서가 아니라 패키지에 딱 붙어 다니는 지식으로 다룬다는 데 있습니다. 좀 더 풀면 이런 그림이에요.

  • Skill을 라이브러리 소스와 같이 관리하고
  • 패키지 버전과 함께 버저닝하고
  • 에이전트가 설치된 의존성 안에서 그걸 발견하게 하고
  • validate / stale 체크로 코드랑 Skill이 어긋나는 걸 줄입니다

흐름 자체는 단순합니다. 저자가 Skill을 스캐폴드하고 → 내용을 채우고 → validate로 형식을 점검하고 → stale로 낡은 게 없는지 확인하고 → 패키지와 함께 배포하면, 에이전트가 설치된 패키지에서 그걸 발견해 씁니다.

진짜 핵심은 “Skill 파일 하나 잘 쓰는 것”이 아니라, 그 Skill이 릴리스 흐름 안에서 같이 관리되고 유지되고 소비된다는 점이에요. 문서를 한 장 더 쓰는 일과는 결이 다릅니다.

그래서 직접 붙여봤습니다

말로만 들으면 좋아 보이는 도구는 많죠. 그래서 그냥 써봤습니다. 똑같이 생긴 React 토스트 라이브러리를 두 개 만들었어요. 둘 다 ToastProvider(앱 루트에 마운트) + useToast()(leaf 컴포넌트에서 호출)로 성공/실패 토스트를 띄우는 구조고, ToastProvider / useToast() / toast / dismissToast를 똑같이 내보냅니다. src/index.jsx바이트 단위로 동일해요. 차이는 단 하나 — demo-lib-intent는 TanStack Intent로 만든 agent-facing Skill을 동봉했고, demo-lib-plain은 평범한 README만 있습니다.

Skill을 만드는 과정은 이랬습니다. npx @tanstack/intent@latest scaffold를 돌리면 파일이 뚝딱 생기진 않고 세 단계로 안내해줘요. 먼저 domain discovery로 이 라이브러리의 핵심 도메인과 실패 패턴을 정리하고, tree generation으로 어떤 skill을 만들지 정하고(이번엔 React 통합 패턴 하나로 단순하게 갔습니다), 마지막 generate skill에서 실제 SKILL.md를 만들면서 권장 방식과 피해야 할 패턴을 적습니다. 끝나고 intent validate로 형식까지 점검했고요.

그리고 양쪽에 똑같은 시작 앱(토스트가 아직 안 붙은, 저장 폼만 있는 화면)과 똑같은 프롬프트를 줬습니다.

이 앱에 저장 성공/실패 toast를 추가해줘. 이미 설치된 토스트 라이브러리(package.json 확인)를 사용하고, 새 패키지는 설치하지 마. 앱 구조에 맞는 위치에 provider를 배치하고, 새 코드에는 권장 경로를 사용해줘.

재현 조건은 이렇게 맞췄습니다.

  • 에이전트/모델: 동일 프롬프트를 받은 신선한 Claude 에이전트(Sonnet). 매 런 독립 컨텍스트, 격리된 디렉토리에서 실행.
  • 반복: 각 버전 10회씩, 총 20런. (에이전트는 매번 다르게 답하니까 n=1로는 아무것도 말 못 합니다.)
  • 통제: 라이브러리 기능·공개 API·시작 앱·프롬프트·모델 전부 동일. 딱 하나, Skill 동봉 여부만 다름.
  • 채점: 정적 분석으로 5개 기준(아래)을 자동 판정 + 빌드 통과 여부.
  • 버전: @tanstack/intent 0.0.42 기준.

한 가지는 솔직히 짚고 가야 해요. 에이전트는 node_modules 속 SKILL.md를 저절로 읽지 않습니다. 소비자가 한 번 intent install을 돌려야 에이전트 설정 파일에 “설치된 intent 패키지의 skill을 찾아 따르라”는 가이드가 생기고, 그제서야 스킬을 인식해요. 그러니까 intent 쪽 우위는 “소비자가 intent install을 1회 해둔 전제”에서 나옵니다. plain 쪽엔 그 설정이 없고요. 이 차이를 빼놓고 결과만 보면 과장이 됩니다.

생성된 SKILL.md, 이렇게 생겼습니다

백 마디 설명보다 실물을 보는 게 빠르겠죠. scaffold가 만들어준 SKILL.md는 frontmatter + “이렇게 써라(Core Patterns)” + “이건 하지 마라(Common Mistakes)“로 구성됩니다. 핵심만 발췌하면 이래요.

--- name: react-toast-integration description: Add demo-lib-intent to a React app by mounting ToastProvider once, calling useToast in leaf components, and avoiding the legacy import path. library_version: "0.1.0" --- ## Core Patterns ### Mount the provider once near the app root ```jsx import { ToastProvider } from "demo-lib-intent"; export function AppShell() { return ( <ToastProvider> <SettingsPage /> </ToastProvider> ); } ``` ### Use the root export for new integrations Only use `demo-lib-intent/legacy` when updating older imperative code. ## Common Mistakes ### CRITICAL Using useToast outside ToastProvider `useToast()` reads ToastContext, so rendering it without a mounted provider throws. ### HIGH Starting a new integration from legacy The legacy export still works, but starting there bypasses the provider-plus-hook flow that the library wants new code to follow. ### MEDIUM Emitting toasts while rendering Toast APIs are side effects — calling them during render creates duplicate notifications. Call them inside an event handler or useEffect instead.

눈에 띄는 건 단순히 “이렇게 쓰세요”가 아니라 금지 패턴에 CRITICAL / HIGH / MEDIUM 등급까지 매겨둔다는 점이에요. “legacy도 동작은 하지만 새 코드는 provider+hook 흐름을 쓰라” 같은, README에는 잘 안 적는 저자의 의도가 그대로 들어갑니다.

결과: intent vs plain

자, 그래서 똑같은 프롬프트를 각 10번씩 던졌더니 어떻게 갈렸을까요? 기준별 성공 횟수는 이렇습니다.

기준demo-lib-plaindemo-lib-intent
ToastProvider를 루트에 1회 마운트10/1010/10
useToast() 훅을 leaf에서 사용5/1010/10
권장 경로 사용(legacy/자체구현 회피)8/1010/10
렌더 중 호출 안 함10/1010/10
빌드 통과10/1010/10
종합 성공 (위 전부 충족)3/1010/10

숫자만 보면 극적이지만, 흥미로운 건 plain이 “망하진 않았다”는 점이에요. provider는 매번 잘 마운트했고, 빌드도 10번 다 통과했습니다. 그런데도 종합 성공은 3/10에 그쳤어요. 발목을 잡은 건 거의 다 “의도된 방식과 미묘하게 다른” 코드였습니다.

가장 큰 차이는 useToast() 훅 사용(5/10 vs 10/10). plain 쪽 절반은 이렇게, 훅 대신 imperative 전역 API로 처리하더군요.

import { useState } from 'react' + import { toast } from 'demo-lib-plain' import { saveProfile } from './storage.js' ... const result = await saveProfile(form) setStatus('success') + toast.success(`Profile saved at ${result.savedAt}`)

동작은 합니다. 토스트도 잘 떠요. 하지만 라이브러리 저자가 “새 코드는 provider+hook 흐름으로 써달라”고 한 그 길은 아니죠. 심지어 한 번은 demo-lib-plain을 토스트 라이브러리로 알아보지도 못하고, src/toast.jsx를 새로 만들어 자체 토스트를 구현해버렸습니다(import { ToastProvider } from './toast.jsx'). 설치된 라이브러리를 두고 말이죠.

반면 intent 버전은 10번 모두 저자가 의도한 그대로였습니다.

+ import { ToastProvider } from 'demo-lib-intent' import { SettingsPage } from './settings-page.jsx' export function AppShell() { return ( + <ToastProvider placement="bottom-right"> <div className="app-shell"> ... </div> + </ToastProvider> ) }
import { useState } from 'react' + import { useToast } from 'demo-lib-intent' import { saveProfile } from './storage.js' ... + const { success: toastSuccess, error: toastError } = useToast() ... const result = await saveProfile(form) + toastSuccess(`Profile saved at ${result.savedAt}`) } catch (error) { + toastError(error.message) }

같은 모델, 같은 프롬프트, 같은 API였는데도요. 차이를 만든 건 모델 머리가 아니라, 라이브러리가 에이전트에게 건넨 실행 지식이었습니다.

”그거 llms.txt랑 뭐가 달라요?”

이쯤 되면 누군가는 이렇게 물을 겁니다. “그거 llms.txtAGENTS.md, MCP, Cursor rules랑 뭐가 다른데요?” 좋은 질문이고, 실제로 결이 다릅니다.

접근위치 / 주체버저닝성격
llms.txt / AGENTS.md리포 루트, 단일 파일리포에 종속프로젝트 전역 안내
MCP 서버런타임 도구 제공서버 측동적 도구/데이터
Cursor / Claude rules소비자 측 설정소비자 관리내 작업환경 규칙
TanStack Intent패키지 동봉패키지 버전과 함께저자가 배포하는 실행 지식

한 줄로 줄이면, TanStack Intent의 차별점은 지식이 저자에서 출발해 패키지 버전에 묶인 채 소비자의 node_modules까지 따라온다는 거예요. “내가 방금 설치한 바로 그 버전”에 맞는 사용법이 함께 온다는 게 다른 방식들과 갈리는 지점입니다.

좋았던 점, 그리고 솔직히 아쉬웠던 점

도구 후기에서 칭찬만 있으면 좀 수상하잖아요. 직접 써보니 좋은 점도, 갸웃하게 되는 점도 있었습니다.

좋았던 점부터. scaffold가 곧장 파일을 뱉지 않고 “이 라이브러리의 도메인과 실패 패턴이 뭐냐”부터 묻고 들어가는 흐름이 의외로 합리적이었어요. 덕분에 Skill이 “기능 나열”이 아니라 “실수 방지” 중심으로 써집니다. 금지 패턴에 CRITICAL/HIGH/MEDIUM 등급을 매기는 포맷도 좋았고요. 그리고 결과가 말해주듯, 같은 모델로도 첫 시도에 의도된 패턴으로 수렴하는 비율이 확연히 올라갔습니다(3/10 → 10/10).

그런데 솔직히 아쉽거나, 비용으로 따져봐야 할 것들도 있어요.

가장 먼저 발견(discovery)이 공짜가 아닙니다. 위에서 말했듯 소비자가 intent install을 한 번 돌려놔야 에이전트가 skill을 찾습니다. 저자가 아무리 잘 써둬도 소비자 쪽 설정이 없으면 그냥 안 읽혀요. 이 한 단계가 생각보다 큰 장벽일 수 있습니다.

다음은 유지보수 이중 부담. 코드를 바꾸면 Skill도 같이 늙습니다. stale 체크가 있긴 한데, “코드가 바뀌었다”는 신호를 줄 뿐 “그래서 Skill의 어느 문장을 고쳐야 하는지”까지 짚어주진 않아요. 결국 사람이 다시 들여다봐야 합니다.

컨텍스트 비용도 무시 못 합니다. Skill도 토큰을 먹어요. 토스트 하나엔 가볍지만, 의존성 수십 개가 저마다 Skill을 동봉하는 미래를 상상하면 “무엇을 언제 로드할지”가 새 숙제가 됩니다.

마지막으로 채택의 닭-달걀. 이 모든 가치는 라이브러리 저자가 Skill을 써줘야 생깁니다. 생태계에 충분히 퍼지기 전까진, 내가 쓰는 라이브러리 중 intent를 지원하는 건 극소수일 거예요.

그리고 당연한 얘기지만 — n=10, 토스트 하나, 에이전트 하나(Claude Sonnet)짜리 실험입니다. 경향은 뚜렷했지만 “모든 라이브러리에서 3배 좋아진다”는 식으로 일반화할 근거는 아니에요.

그래서 언제 특히 쓸 만한가

솔직히 모든 라이브러리에 똑같이 필요한 건 아닙니다. 다만 이런 경우엔 확실히 설득력이 커져요.

초기화 순서가 중요한 라이브러리. provider·client·adapter·runtime을 어떤 순서로 엮느냐가 중요하다면, “어떤 API가 있나”보다 “무슨 순서로 연결하나”가 훨씬 중요하죠.

환경별 제약이 큰 라이브러리. SSR, hydration, server/client 분리, edge runtime, bundler 차이… 예외가 많을수록 README만으로 모든 분기를 행동 규칙으로 전하긴 버겁습니다.

권장 경로와 금지 경로가 뚜렷한 라이브러리. “동작은 하지만 이제 권장 안 함” 같은 함정이 있을 때, 에이전트는 오래된 예제를 따라가 “되긴 되는데 의도랑 다른” 결과를 잘 만듭니다.

에이전트 사용 비중이 빠르게 느는 생태계. 사람들이 문서를 깊게 읽기보다 에이전트로 코드를 뽑는 비중이 커질수록, 저자가 에이전트 친화적인 지식 표면을 설계할 이유도 커집니다.

무엇을 해결하고, 무엇은 아닌가

기대를 정확히 맞추는 게 중요할 것 같아서 정리해둡니다.

TanStack Intent가 해결하려는 것은 — 에이전트가 소비할 실행 지식을 라이브러리와 함께 배포하고, 패키지 버전과 함께 관리하고, 낡은 가이드가 남는 문제를 줄이고, 사용 의도를 더 또렷하게 전달하는 것입니다.

반대로 해결해주지 않는 것도 분명합니다. 모델 자체의 추론 한계를 없애주진 않고, 모든 구현 오류를 자동으로 막아주지도 않으며, 복잡한 라이브러리 설계를 단순하게 만들어주지도, 좋은 API·좋은 문서를 대체하지도 않습니다.

그러니까 이건 README를 없애는 도구도, 에이전트를 완벽하게 만드는 도구도 아니에요. 에이전트가 더 나은 결정을 내리도록 라이브러리 쪽 지식 표면을 정리해주는 도구에 가깝습니다.

정리하며

길게 돌아왔지만 핵심은 단순합니다.

에이전트는 문법보다 맥락에서 더 자주 흔들립니다. 그래서 README는 사람을 위해, Skill은 에이전트를 위해 따로 필요해요. TanStack Intent는 그 Skill을 배포 가능한 지식으로 만들어 패키지에 붙여 다니게 해줍니다.

결국 AI 코딩 에이전트 시대의 라이브러리는 API만 잘 제공해서는 조금 부족할지도 모릅니다. 사람에게는 문서가, 에이전트에게는 Skill이 필요한 거죠.

직접 써본 입장에서 한 줄로 정리하면 — “권장/금지 경로가 뚜렷한 라이브러리를 만들고 있고, 에이전트로 쓰는 사용자가 많다면 지금 붙여볼 만하다. 다만 발견 설정과 유지보수 비용은 감안하고.” 토이 프로젝트에 당장 필수는 아니지만, 적어도 “에이전트가 내 라이브러리를 어떻게 쓰는가”를 설계 대상으로 보기 시작하게 만든다는 점에서 한 번쯤 굴려볼 가치는 충분했습니다.

참고 자료